一、簡介
從影像讀取到辨識,前幾個教學單元都是圍繞在攝影機與硬體的控制教學上。其實在不藉助外接設備的情況下,單靠顯示螢幕與按鍵就能製作不少小專案,像是利用兩個按鍵即可選字的留言板,或是創作一些簡單的小遊戲。
這個單元就讓我們跳脫 AIoT 的應用,以製作趣味小玩具為目標吧!
談到簡單又好玩的小遊戲,非 Chrome Dino Game 莫屬了,這是 Google Chrome 瀏覽器在連不上網際網路時,自動觸發的小遊戲,只需要簡單的按下空白鍵就能暢玩,過程中會有不少障礙,速度與顏色也會隨著遊玩的分數改變,相當有趣,不知道各位夥伴們最高分數紀錄是多少呢?
要製作這樣的小遊戲有幾個需要考慮的元素,第一個是我們的主角恐龍,第二是障礙物仙人掌,接著是隨機生成的遊戲背景,以及不讓畫面過於單調的雲,總共四大元素。
基本上除了小恐龍我們可以控制之外,其他元素一律由程式自動產生,就讓我們來看看如何製作這個小遊戲吧!
二、圖樣產生
不論是仙人掌還是恐龍,都是由一個像素一個像素拼接而成,我們可以用一些自己熟悉的工具,設計出可以放進畫面大小內的圖樣。最簡單的就是 Windows 的小畫家,透過鉛筆工具繪製恐龍、仙人掌……等。
我們的顯示螢幕程式庫並沒有辦法直接讀取圖片檔案,需要透過轉換格式的工具來協助我們轉換為 XBM 檔案,如下圖所示,這是小恐龍轉換後的內容,可讓程式碼直接讀取,並顯示在螢幕上。
轉換方式很簡單,請點選連結,開啟免費的線上轉換工具「Convert Image to XBM」。
接著點選「瀏覽」開啟剛剛繪製好的圖片,並按下「Convert and Download」下載轉換後的檔案。
使用文字編輯器打開轉換後的檔案,如下圖所示,前兩行是我們圖樣的長度與寬度大小,大括弧{}內的資料就是我們小恐龍的圖樣資料。
後面我們將會用到這些資料,並填入程式當中。
三、所需設備
1. pixel:bit x1
2. Micro USB to USB Type-A 數據傳輸線 x1
四、範例程式下載
若您之前已下載過範例程式,可以直接在之前下載的資料夾中找到「05_Dino_Game」。如果還沒下載,請點選連結,進到網頁看到「Code」按鈕,點選後選擇「Download ZIP」就能將檔案整個下載下來。
解壓縮後,這個單元的範例程式,就放在資料夾名稱為「05_Dino_Game」裡面。
五、程式解析
1. 牛刀小試
我們先從最簡單的顯示開始,請開啟名稱為「PixelBit_Image_Show」的資料夾。
打開裡面的程式,完整程式如下:
與之前的顯示程式最大的不同,就是新加入了「Sprite」功能,Sprite 功能就像是一個可以自由設定大小的獨立畫布,您可以把圖形繪製到這個獨立的畫布上,並且可以同時擁有多個 Sprite,方便管理。最大優點是Sprite 之間可以重疊,例如在背景存在的情況下,我們可以建置恐龍的 Sprite 與仙人掌的 Sprite,並將它們像貼貼紙一樣黏在背景上。
程式碼中的第三行,我們建立了一個預備使用 Sprite 的物件「img」,接著我們將剛剛圖片轉換成的資料放在「PROGMEM unsigned char dino[]」裡面。
在「setup()」區塊的部份,透過「createSprite(33, 35)」創建了一個大小與恐龍圖片一樣的 Sprite,接著由「drawXBitmap(0, 0, dino, 33, 35, TFT_BLACK, TFT_WHITE)」將恐龍繪製上去,括弧內前兩個參數表示繪製的起始座標,接著是圖檔、圖檔大小、與顯示色彩和背景色彩。
最後由「pushSprite(105, 104)」設定好要顯示在螢幕的座標位子後,圖片就會出現在螢幕上了。
2. ATmega328p 的程式
遊戲執行的過程只有單純的按鈕輸入與螢幕顯示,螢幕的部份歸 ESP32 負責,ATmega328p 只有負責按鈕的部份。聰明的大家應該猜的到,不就是單純讀取按鈕是否有按下,然後再發送訊息通知 ESP32 這麼簡單嗎?沒錯!
您可以依照「Pixel:Bit 教學(二)」的做法自己撰寫這個程式,想要挑戰的朋友可以自己設計看看。為了能與待會的 ESP32 程式溝通,您需要設計按鈕 A 與按鈕 B,分別按下與放開的指令,如下表所示:
只要朝這個方向設計,就能直接接軌待會的 ESP32 程式。範例程式這邊給出不一樣的思路給大家參考,現在請開啟名稱為「PixelBit_Dino_Game_328p」的資料夾,並打開程式。
程式有主程式「PixelBit_Dino_Game_328p.ino」與副程式「config.h」,副程式 config.h 是用於設定參數與對照表,類似將一些較攏長的指令與變數定義全部集合在這裡,再由程式匯入副程式這個檔案,取用裡面的內容。
主程式則是將一些常用的功能或是自定義的功能全寫在裡面,除了這個單元會用上的按鈕 A(左邊按鈕)及按鈕 B(右邊按鈕)之外,也將上個單元的遙控車控制馬達的功能,一併放在這裡。
主程式看似複雜,但仔細研讀會發現,這樣系統化的做法可讓往後擴充更便利,程式碼也較整齊。
上述給大家做參考,同時鼓勵大家可以用自己理解的方式寫寫看。不論您是自己撰寫,還是直接取用範例程式,都不要忘記將程式先燒錄到 ATmega328p 內。
3. ESP32 的程式
比起 ATmega328p,ESP32 這邊的程式就複雜許多,雖說是顯示而已,但顯示遊戲內容還是比單純的文字和圖形複雜的多。請開啟名稱為「PixelBit_Dino_Game_esp32.ino」的資料夾,並打開程式。
程式由五個部份組成,分別是主程式與其他四個副程式,「config.h」這個副程式與 ATmega328p 那邊的功用相同,都是用來存放一些設定的參數與對應的變數。其餘三個副程式都是用來存放圖檔,「noInternet.h」存放的是遊戲開始畫面,完美呈現沒有網路的無奈畫面。「gameover.h」存放的是小恐龍撞到障礙物時,結束遊戲的畫面。
「imgData.h」則分別存放小恐龍(三個畫面)、雲朵(一個畫面)、路面凸起小土丘(兩個畫面)與障礙物(兩個畫面)。有些項目會有多個畫面是為了增加豐富性,例如恐龍在移動時會需要多個畫面交叉顯示,這樣看起來才會像跑動的樣子。
了解其餘副程式的功能後,讓我們回來看主程式,首先與剛剛牛刀小試裡介紹的一樣,我們需要創造幾個「Sprite」來放置圖形。
「img」用來放置背景的元素,「img2」專門放置小恐龍,「e」、「e2」則是分別放置兩種不同造型的障礙物。
讀取從 ATmega328p 送過來的按鈕資訊部份就不解釋了,掌管圖形顯示與變化最關鍵的程式是圖中的「drawS()」。
「drawS()」負責處理背景的線條與隨機放置小土丘、雲朵和障礙物,小恐龍會依照按下按鈕而有跳起和落下的動畫,沒按按鈕時會有跑動的動畫。
另一個重要的程式是「checkColision()」,用來確認小恐龍有沒有撞上障礙物,有的話會停止遊戲並顯示「遊戲結束畫面」。
在「loop()」裡運行的完整流程,第一步先確認是否有收到從 ATmega328p 傳送過來的按鈕訊息,第二步則是依照按鈕狀態調整小恐龍的動作,看是要繼續跑動還是跳起與落下。接著統一顯示所有圖像,雲朵、障礙物和背景……等,最後確認小恐龍有沒有撞上障礙物。讓我們將程式燒錄到 ESP32 裡面。
4. 實際操作展示
現在就讓我們開始玩遊戲吧!
六、結論
這個單元教了大家除了影像辨識外的趣味專案,我們完成了在 Pixel:bit 運行 Chrome Dino Game。像這樣簡單的小遊戲,其實還有很多種,只要是能單靠兩顆按鈕操作的遊戲,您都能透過自己的想像力與程式碼將這些遊戲移到 Pixel:bit 上面,還不趕緊製作屬於自己的遊戲跟朋友們分享!
若您有 Pixel:Bit 研習的需求,歡迎填寫表單,日後有相關課程資訊將在第一時間通知您!