基于Arduino制作這款打地鼠的街機(jī)游戲
你有沒(méi)有覺(jué)得有必要吹掉一些蒸汽,釋放你內(nèi)心的孩子,或者只是重溫從你的街機(jī)輝煌的日子粉碎東西的快感?進(jìn)入正常!這款游戲是對(duì)經(jīng)典打地鼠游戲的高科技改造,融合了懷舊和工程學(xué)。
我們從頭開(kāi)始制作這款街機(jī)游戲:一個(gè)激光切割的木制盒子,里面裝著九個(gè)氣缸。但這不僅僅是蠻力,我們用磁鐵和3D磁傳感器取代了傳統(tǒng)的機(jī)械開(kāi)關(guān),使撞擊檢測(cè)快速而精確。當(dāng)然,我們也不能只使用自己3D打印的錘子,這樣就能承受最激烈的游戲玩法。我們還提供了完整的構(gòu)建指南:組裝、編碼和校準(zhǔn)。準(zhǔn)備好開(kāi)始了嗎?
游戲概述
在嘉年華上玩過(guò)打地鼠嗎?假鼴鼠會(huì)從不同的洞里鉆出來(lái)每次鉆出來(lái),你就試著敲它。正常!《T》將這一概念現(xiàn)代化:玩家擊碎由壓縮空氣驅(qū)動(dòng)的隨機(jī)彈出的9個(gè)氣動(dòng)活塞。但這不是你爺爺?shù)慕謾C(jī)游戲:
智能命中檢測(cè):活塞上的磁鐵與英飛凌最新系列的TLE493D磁性傳感器相互作用,取代機(jī)械開(kāi)關(guān),實(shí)現(xiàn)即時(shí)、精確的命中。
自動(dòng)游戲流程:xmc4700 Relax Lite kit微控制器套件是游戲的大腦,并使用OPTIGA?TrustMsecurity芯片隨機(jī)化活塞定時(shí)?;钊臍鈩?dòng)閥由使用單芯片的TLE94112ES 12倍半橋控制!最重要的是,游戲中的DPS368壓力傳感器和3d打印的錘子會(huì)在錘子被舉起時(shí)觸發(fā)游戲開(kāi)始。
時(shí)間和得分跟蹤:一個(gè)雙位數(shù)的7段顯示剩余的比賽時(shí)間和你的最終得分。
它是如何工作的
開(kāi)始:舉起錘子→DPS368測(cè)量錘子與游戲底座的高度差,觸發(fā)游戲開(kāi)始倒計(jì)時(shí)5秒。
播放:15秒倒計(jì)時(shí)開(kāi)始→OPTIGA?Trust M芯片隨機(jī)分配活塞→TLE94112ES激活閥門(mén)→活塞彈出。
得分:敲擊活塞→TLE493D檢測(cè)磁感應(yīng)→XMC4700點(diǎn)燃下一個(gè)活塞并增加得分。
接下來(lái)是什么?我們將開(kāi)始建立和測(cè)試9活塞氣動(dòng)系統(tǒng),然后整合3D磁傳感機(jī)制,添加雙7段顯示,最后我們3D打印智能錘子和組裝成一個(gè)拋光街機(jī)準(zhǔn)備的游戲。
硬件
氣動(dòng)系統(tǒng):
此版本中的氣動(dòng)系統(tǒng)基于Hackster項(xiàng)目:使用單個(gè)芯片驅(qū)動(dòng)氣動(dòng)系統(tǒng)。按照這個(gè)指南來(lái)創(chuàng)建你的主干!T游戲。
步驟2:將氣動(dòng)系統(tǒng)變?yōu)榛顒?dòng)活塞
為了準(zhǔn)備傳感器測(cè)試,我們現(xiàn)在將轉(zhuǎn)向組裝。確保所有的激光切割部件和3d打印部件都準(zhǔn)備好了,因?yàn)閺默F(xiàn)在開(kāi)始,它們將在每一步中使用(請(qǐng)參閱附件中的設(shè)計(jì)文件)。
讓我們從組裝活塞外殼開(kāi)始,它由激光切割的部件與9個(gè)活塞和傳感器的切口粘合在一起。之后,我們放置3d打印的活塞導(dǎo)軌,將它們鎖定在適當(dāng)?shù)奈恢?,防止旋轉(zhuǎn)。我們還增加了一些填充物的活塞支持,以幫助吸收沖擊。
接下來(lái),我們將9個(gè)活塞放入各自的插槽中,并將磁鐵粘在它們身上,因?yàn)樗鼈儗⒃诮酉聛?lái)的構(gòu)建中發(fā)揮重要作用。請(qǐng)注意,在照片中,我們也組裝了側(cè)墻,這是激光切割,也可以附加在最后的組裝。
接下來(lái),我們放置9個(gè)活塞墊,擰緊支撐活塞的木板。這塊板作為運(yùn)動(dòng)活塞和氣動(dòng)系統(tǒng)之間的中間層。最后,你可以把活塞系統(tǒng)安裝到氣動(dòng)系統(tǒng)上,就可以進(jìn)行測(cè)試了。
現(xiàn)在你已經(jīng)成功地制造了活塞和氣動(dòng)系統(tǒng)!隨后,我們將添加OPTIGA?Trust M芯片來(lái)隨機(jī)化活塞行為。你會(huì)注意到活塞的木制外殼上有一些切口。這些切口是為3D磁傳感器的支架設(shè)計(jì)的
3D磁傳感器可以測(cè)量三個(gè)方向的磁場(chǎng):X, Y和z。我們將在9個(gè)活塞之間放置4個(gè)傳感器,這樣就可以檢測(cè)到任何一個(gè)活塞受到撞擊時(shí)磁場(chǎng)的變化。
在圓柱體的底部,我們放置了磁鐵。這些磁鐵能讓我們探測(cè)到圓柱體被擊中的時(shí)間。
磁鐵被放置在盡可能靠近3D磁傳感器的地方,以確保磁場(chǎng)足夠強(qiáng),能夠被準(zhǔn)確檢測(cè)到。對(duì)于傳感器,我們使用3D磁傳感器的切割板。在附件的Fritzing文件中提供了接線說(shuō)明。
四個(gè)傳感器安裝在支架上,如下圖所示。
現(xiàn)在,我們可以把傳感器支架放在氣動(dòng)系統(tǒng)里。
為了使組裝更實(shí)用,我們創(chuàng)建了一個(gè)帶連接器的小板。布線如圖所附的fritz文件所示;按照這些方法進(jìn)行正確的連接。
現(xiàn)在我們可以把底板與9個(gè)氣缸在組裝和關(guān)閉一切的頂部。有了這一步,游戲的機(jī)制部分就完成了,可以進(jìn)行測(cè)試了。
最后,我們可以測(cè)試9個(gè)活塞和磁傳感器(測(cè)試代碼在附件文件中提供)。之后,我們可以移動(dòng)到7段屏幕的顯示部分。
分?jǐn)?shù)顯示
我們使用兩個(gè)相互連接的7段數(shù)字來(lái)顯示游戲中的剩余時(shí)間和最終比分。我們將把顯示器安裝在“搞怪!”T游戲,這是設(shè)計(jì)來(lái)保持它。開(kāi)始組裝激光切割的木制部件如下所示。一旦框架準(zhǔn)備好,將7段顯示器安裝到木板上,并通過(guò)木板布線,在那里它們將連接到XMC微控制器。
讓錘子更聰明
錘子是擊打的關(guān)鍵部分!T游戲。為了檢測(cè)錘子何時(shí)被舉起,我們使用了兩個(gè)DPS368空氣壓力傳感器:一個(gè)傳感器放置在錘子內(nèi)部。另一個(gè)被放置在里面!T框作為參考。
通過(guò)測(cè)量?jī)蓚€(gè)傳感器之間的壓力差,我們可以測(cè)量錘與游戲之間的高度差,精度為±2厘米,并檢測(cè)錘何時(shí)被舉起。壓力傳感器接線圖在工程文件中提供。
對(duì)于錘子組件,您可以使用提供的3d打印部件。stl文件。這里有一些建議:水平打印錘子以獲得更好的穩(wěn)定性。將填充量增加到50%以增加重量和提高耐久性,將壁厚增加到2.4mm以增加堅(jiān)固性。在電纜隧道區(qū)域(錘身)增加支架擋塊,避免支架難以拆除。
錘子由三部分組成:主錘體和兩個(gè)柔性TPU帽。這些蓋子可以在激烈的游戲過(guò)程中保護(hù)游戲免受損害。
在錘子的頂部,有放置DPS368壓力傳感器的空間。只需將傳感器推到位,如下圖所示:
另一個(gè)傳感器可以放置在任何地方。T游戲基地。
推動(dòng)游戲發(fā)展
XMC4700放松套件需要5 V電源,顯示器工作在12 V,壓縮機(jī)和閥門(mén)都需要9 V電源。為了實(shí)現(xiàn)必要的電壓轉(zhuǎn)換,需要一個(gè)降壓轉(zhuǎn)換器從9v降壓到5v,從9v升壓到12v
為此,我們使用兩個(gè)TLD5190 VOLT DEMO評(píng)估板。這些板允許您通過(guò)調(diào)整板上微調(diào)器來(lái)選擇所需的輸出電壓。有關(guān)設(shè)置和使用這些評(píng)估板的詳細(xì)說(shuō)明,TLD5190 VOLT DEMO評(píng)估板的用戶(hù)手冊(cè)提供了全面的解釋。
你可以通過(guò)向左轉(zhuǎn)動(dòng)微調(diào)器來(lái)增加電壓,通過(guò)向右轉(zhuǎn)動(dòng)來(lái)降低電壓。
軟件
現(xiàn)在讓我們一步一步地分解我們的Arduino代碼!首先,我們將闡明如何單獨(dú)使用和測(cè)試每個(gè)組件,然后我們將解釋整個(gè)應(yīng)用程序代碼的Whack!T游戲。
第1部分:組件代碼
7段顯示代碼
游戲開(kāi)始前會(huì)出現(xiàn)5秒倒計(jì)時(shí)。游戲在這個(gè)倒計(jì)時(shí)后開(kāi)始,另一個(gè)15秒倒計(jì)時(shí)從那里開(kāi)始。在這段時(shí)間里,你必須盡可能多地打汽缸。在第二次倒計(jì)時(shí)結(jié)束時(shí),你的最終得分顯示-所有這些都是使用7段顯示。為了測(cè)試這兩個(gè)7段數(shù)字,我們使用了下面的示例代碼。我們所做的唯一修改是將引腳分配更改為50 (segmentLatch), 51 (segmentData)和52 (segmentClock)。
代碼Optiga?信任M盾2go
Optiga?Trust M芯片在這里用于生成(真實(shí)且加密安全的)1到9之間的隨機(jī)值,這是我們項(xiàng)目中的關(guān)鍵一步,因?yàn)樗鼨z測(cè)到哪個(gè)圓柱體會(huì)彈出,使游戲變得不可預(yù)測(cè)和具有挑戰(zhàn)性。但在此之前,我們需要了解芯片的工作原理。
我們首先修改Optiga?Trust M Arduino庫(kù)中的一個(gè)示例,使其適應(yīng)我們的需求。首先,讓我們看一下這段代碼的基礎(chǔ):
頭文件和定義
要開(kāi)始,我們需要包含“OPTIGATrustM.h”庫(kù),它使我們能夠訪問(wèn)TrustM功能。我們定義了隨機(jī)數(shù)生成的最大字節(jié)長(zhǎng)度-將其設(shè)置為8確保我們一次可以生成最多8個(gè)隨機(jī)字節(jié)。
一個(gè)額外的調(diào)整:默認(rèn)代碼包括彩色輸出(來(lái)自“fprint.h”),但為了簡(jiǎn)單起見(jiàn),我們選擇禁用它。
設(shè)置函數(shù)
一切就緒后,是時(shí)候初始化芯片了。setup功能確保Trust M板準(zhǔn)備好生成安全隨機(jī)數(shù)。
這里有一個(gè)有趣的特性是電流限制——這個(gè)設(shè)置會(huì)影響主板的運(yùn)行速度。如果我們?cè)黾与娏飨拗?,電路板就?huì)加速。對(duì)于這個(gè)設(shè)置,我選擇了8 mA的限制(setCurrentLimit(8)),以便在性能和穩(wěn)定性之間取得更好的平衡。
循環(huán)函數(shù):生成隨機(jī)數(shù)
每次循環(huán)運(yùn)行時(shí),Optiga?Trust M模塊通過(guò)函數(shù)getRandom(RND_MAXLENGTH, rnd)提供8字節(jié)的隨機(jī)數(shù)據(jù)。但是我們需要一個(gè)介于1和9之間的數(shù)字,因此我們將原始字節(jié)數(shù)組轉(zhuǎn)換為int64_t數(shù)字(convertByteArrayToInt64()),并使用對(duì)9 + 1取模將其映射到我們想要的范圍。這確保了我們總是在目標(biāo)范圍內(nèi)得到結(jié)果。
結(jié)果看起來(lái)像這樣:
3D磁傳感器代碼
這部分在我們的Hackster文章中有很好的記錄:下一代TLE493D: 3D磁感測(cè)指南,但對(duì)于這個(gè)特定的項(xiàng)目,我們需要使其適應(yīng)XMC4700微控制器。
在深入游戲機(jī)制之前,我們需要測(cè)試所有四個(gè)傳感器,以驗(yàn)證它們是否正確連接和運(yùn)行。下面的代碼是專(zhuān)門(mén)為快速診斷設(shè)計(jì)的,允許我們檢查每個(gè)傳感器是否可操作。使用四個(gè)#define語(yǔ)句,我們可以激活或停用單個(gè)傳感器以進(jìn)行測(cè)試。我們還定義了numavg,它決定了在計(jì)算平均值之前測(cè)量每個(gè)傳感器的次數(shù)。
平均傳感器值
一旦初始化,循環(huán)函數(shù)不斷地從傳感器讀取數(shù)據(jù)。函數(shù)average_sensor_value()測(cè)量多個(gè)讀數(shù)的值并取平均值,以獲得更穩(wěn)定的輸出。
傳感器的內(nèi)置函數(shù)getTemperature()和getMagneticField()用于提取數(shù)據(jù),而計(jì)時(shí)函數(shù)測(cè)量收集50個(gè)值所需的時(shí)間。
ps傳感器代碼
在我們的比賽中,時(shí)機(jī)就是一切。在玩家準(zhǔn)備好之前,游戲不應(yīng)該開(kāi)始——這就是DPS傳感器的作用所在。這些傳感器用于檢測(cè)錘子何時(shí)被舉起,發(fā)出倒計(jì)時(shí)開(kāi)始的信號(hào)。
為了實(shí)現(xiàn)這一點(diǎn),我們使用了兩個(gè)DPS傳感器:一個(gè)傳感器放置在錘子內(nèi)部來(lái)跟蹤它的運(yùn)動(dòng)。
第二個(gè)傳感器仍然固定在打!T設(shè)置,作為參考點(diǎn)。
關(guān)于如何使用傳感器的詳細(xì)解釋也可以在這篇Hackster文章中找到,但這里是我們?nèi)绾卧谖覀兊捻?xiàng)目中實(shí)現(xiàn)它。
頭文件和對(duì)象
Dps3xx.h包含在#include中,創(chuàng)建兩個(gè)Dps傳感器對(duì)象:
設(shè)置/循環(huán)
在我們追蹤錘子的運(yùn)動(dòng)之前,我們需要初始化傳感器并建立基線讀數(shù)。
設(shè)置功能確保兩個(gè)傳感器都正確初始化。
由于兩個(gè)傳感器在不同的位置,它們的壓力讀數(shù)自然會(huì)不同。這種差異可能相當(dāng)于高達(dá)8米的高度差異,因此我們首先計(jì)算一個(gè)初始參考差作為基線。
高度差是在ight()函數(shù)中計(jì)算的,稍后我們將使用該函數(shù)來(lái)檢測(cè)運(yùn)動(dòng)。如果高度差大于10厘米,游戲?qū)㈤_(kāi)始。
通過(guò)使用這兩個(gè)DPS傳感器,我們創(chuàng)造了一個(gè)直觀的游戲啟動(dòng)機(jī)制。玩家不需要按下按鈕或打開(kāi)開(kāi)關(guān)——當(dāng)他們把錘子舉得足夠高時(shí),游戲就會(huì)自動(dòng)開(kāi)始。
Part 2: Code for Whack!T游戲
顯示屏設(shè)置為顯示游戲時(shí)間和分?jǐn)?shù),而DPS和3D磁傳感器分別用于檢測(cè)舉起錘子和成功擊中。為了建立一個(gè)可靠的參考,在比賽開(kāi)始前記錄初始傳感器值。
DPS傳感器-檢測(cè)當(dāng)錘子被舉起,信號(hào)的游戲開(kāi)始。
3D磁傳感器-跟蹤撞擊時(shí),活塞被擊中。
多半橋和執(zhí)行器-控制彈出的活塞,讓玩家擊中。
壓縮機(jī)—提供空氣壓力以移動(dòng)活塞。
顯示-顯示比賽時(shí)間和比分更新。
設(shè)置
在操作開(kāi)始之前,需要初始化系統(tǒng)的所有組件。setup()函數(shù)負(fù)責(zé)這一點(diǎn),準(zhǔn)備顯示器、傳感器和執(zhí)行器。
顯示屏設(shè)置為顯示比賽時(shí)間和分?jǐn)?shù),而DPS和3D傳感器配置為檢測(cè)錘的運(yùn)動(dòng)和成功命中。為了建立一個(gè)可靠的參考,在游戲開(kāi)始之前記錄初始傳感器值(measure_initial_values())。控制負(fù)責(zé)移動(dòng)活塞的執(zhí)行器的多半橋(MHB)通電,壓縮機(jī)開(kāi)始積聚空氣壓力(kompressor.start()),確保活塞能夠正常移動(dòng)。
短暫的延遲可以讓所有組件在游戲進(jìn)入主循環(huán)之前穩(wěn)定下來(lái)。幾個(gè)關(guān)鍵文件管理游戲的不同方面:display.hpp處理顯示功能,airpressure_sensor.hpp處理來(lái)自空氣壓力傳感器的數(shù)據(jù),3d_sensor.hpp檢測(cè)圓柱體何時(shí)被擊中,push.hpp控制執(zhí)行器,game_matrix.hpp管理活塞運(yùn)動(dòng)的核心游戲邏輯。
GameLoop
一旦設(shè)置好一切,游戲便進(jìn)入主循環(huán),在此它將持續(xù)監(jiān)視玩家的行動(dòng),更新顯示內(nèi)容并管理游戲邏輯。
游戲如何在循環(huán)中運(yùn)行:
1?游戲計(jì)時(shí)器管理
函數(shù)getRemainingSeconds()檢查還剩下多少時(shí)間。
如果游戲處于活動(dòng)狀態(tài)(start_counting == true)并且還有剩余時(shí)間,它會(huì)在屏幕上顯示倒計(jì)時(shí)。
如果計(jì)時(shí)器達(dá)到零,游戲?qū)⒋鎯?chǔ)最終分?jǐn)?shù),重置命中計(jì)數(shù)器,并為新一輪做好準(zhǔn)備。
2?.命中檢測(cè)與計(jì)分
命中檢測(cè)是基于磁場(chǎng)的變化。當(dāng)氣缸的頂部位置與其當(dāng)前位置之間的差值超過(guò)0.1 mT時(shí),將記錄命中(compare_difference(piston_now, 0.1))。
分?jǐn)?shù)是用game_hit_counter實(shí)現(xiàn)的。
3?.氣缸體爆破機(jī)構(gòu)
游戲使用calculate_average(piston_now)連續(xù)檢查活塞運(yùn)動(dòng)。
一旦檢測(cè)到撞擊,系統(tǒng)隨機(jī)選擇一個(gè)活塞(1到10),并使用push(random(1,10))激活它。
這讓游戲變得不可預(yù)測(cè),確保玩家不知道下一個(gè)圓柱體會(huì)彈出哪個(gè)圓柱體,從而保持他們的沉浸感。
4? .游戲結(jié)束并重新開(kāi)始
如果計(jì)時(shí)器跑完,將顯示最終分?jǐn)?shù),游戲?qū)⒌却N子再次被舉起,然后重新開(kāi)始。
這種平滑的過(guò)渡確保了無(wú)縫的游戲體驗(yàn),而無(wú)需額外的按鈕或手動(dòng)重置。
倒數(shù)計(jì)時(shí)器
正常!游戲采用倒計(jì)時(shí)計(jì)時(shí)器,確保每回合持續(xù)固定時(shí)間(15秒)。getRemainingSeconds()函數(shù)通過(guò)測(cè)量游戲開(kāi)始后經(jīng)過(guò)的毫秒數(shù)來(lái)計(jì)算剩余時(shí)間。如果經(jīng)過(guò)的時(shí)間超過(guò)倒計(jì)時(shí)持續(xù)時(shí)間,則返回0。
開(kāi)始新游戲
在start_game()函數(shù)中,我們檢查游戲是否處于非活動(dòng)狀態(tài)(start_counting ==false),然后啟動(dòng)倒計(jì)時(shí)。當(dāng)?shù)褂?jì)時(shí)達(dá)到0時(shí),游戲開(kāi)始,記錄開(kāi)始時(shí)間(startMillis),設(shè)置游戲持續(xù)時(shí)間,并啟用倒計(jì)時(shí)。
該系統(tǒng)確保平穩(wěn)和自動(dòng)啟動(dòng),無(wú)需手動(dòng)輸入。
現(xiàn)在我們可以結(jié)束了!所以T游戲代碼,一切就緒,游戲就準(zhǔn)備開(kāi)始了!拿你的錘子瞄準(zhǔn)一些汽缸!!
本文編譯自hackster.io