基于stm32、0.96寸OLED实现的贪吃蛇小游戏(详细源码注释)
簡介:本實驗基于stm32最小系統(tǒng)、0.96寸OLED(68*128)和搖桿實現(xiàn)一個經(jīng)典的貪吃蛇小游戲。項目源碼地址:點擊下載。
硬件設(shè)計:
普通搖桿,0.96寸OLED 單色屏幕(SPI協(xié)議通訊),stc32f103c8t6最小系統(tǒng)開發(fā)板,如下所示。
器件齊全后,用杜邦線將搖桿和oled正確地連接到stm32開發(fā)板上,注意各個器件的電源需要接到同一電壓,下圖是接線說明:
?接好線之后,將源碼編譯下載,進入調(diào)試,正常運行如下圖所示,如果屏幕出現(xiàn)花屏,那么將res引腳接到GND進行復(fù)位,再重新進行調(diào)試或單片機復(fù)位:
接著按下?lián)u桿的中鍵就可以進入游戲:
屏幕的上方顯示得分,通過搖桿控制蛇的運動方向。
游戲失敗后可按下?lián)u桿中鍵重新開始游戲。
代碼設(shè)計:?
源代碼下載解壓后,利用keil4工具打開工程可看到:
上面已表明各個文件的作用,?可重點看Snake.c游戲設(shè)計文件。如果代碼里面的注釋是亂碼,點擊Edit->Configuration->Editor->Encoding->選擇Chinese GB2312。下面面只列舉部分代碼說明。
main函數(shù)
int main(void) {RCC_PCLK1Config(RCC_HCLK_Div4);USART1_Configuration(); //初始化串口TIME_Configuration(); //初始化定時器ADC_Configuration(); //初始化搖桿的ad采集OLED_Init(); //oled初始化默認(rèn)參數(shù)GameReady(); //進入游戲準(zhǔn)備界面Tick_Updata(&sysms);while (1){event=JoyState(); //獲取搖桿的狀態(tài)ret=Game_InputHandle(event);//蛇移動if(ret){ //ret=1 表示屏幕需刷新GameMapToLcdCache(); //將像素從游戲圖像gamemap位圖經(jīng)過放大后寫進LcdCache顯存OLED_Updata();//將LcdCache[8][128]顯存的數(shù)據(jù)發(fā)送到屏幕進行顯示sprintf(str,"Score=%d",GameScore);OLED_DispString(0,0,str); //屏幕上方顯示分?jǐn)?shù)}} }main函數(shù)并不復(fù)雜,while循環(huán)里面不斷獲取搖桿狀態(tài),將狀態(tài)傳進Game_InputHandle函數(shù)進行游戲操作。
實現(xiàn)原理:
運用鏈表的特性,蛇的每一個節(jié)點就是鏈表的節(jié)點,節(jié)點的內(nèi)容是該點的x,y坐標(biāo),如上圖所示。遍歷鏈表逐個讀取蛇身的每個節(jié)點里面的x,y坐標(biāo),根據(jù)該坐標(biāo)在屏幕上描點,即可描繪出蛇的形狀來。
蛇的運動的原理是從蛇尾節(jié)點開始,其x,y坐標(biāo)等于前一個節(jié)點的坐標(biāo),直至到頭節(jié)點,頭節(jié)點的新x,y坐標(biāo)跟蛇運動的方向有關(guān)。每當(dāng)蛇遲到食物時,尾部追加節(jié)點。
void GAME_NewSnake(SNAKELIST* SnakeList) //初始化鏈表,初始化蛇長度,4+1節(jié) {int x=4,y=15,i;//蛇的初始位置SnakeList->x=x;SnakeList->y=y++;SnakeList->prev=SnakeList;SnakeList->next=SnakeList;for(i=0;i<4;i++){GAME_SnakeListAddNode(SnakeList,x,y+i);}GAME_SnakeFillInGameMap(gamemap,SnakeList); }GAME_NewSnake游戲開始前,給蛇初始化5個節(jié)點,頭節(jié)點在x=4,y=15處,其余4個節(jié)點在其下方。通過GAME_SnakeFillInGameMap函數(shù)將蛇在gamemap上描畫出來。gamemap再放大映射到LCDcache顯存里面去,再通過spi把整個屏幕的像素發(fā)送到屏幕進行顯示。
void GAME_NewFood(unsigned char (*gamemap)[WIDTH]) //在地圖上隨機產(chǎn)生新的食物 {unsigned int seed1,seed2;int x,y;while(1){Tick_Updata(&seed1);Tick_Updata(&seed2);x=seed1%WIDTH;y=seed2%HEIGHT;if(gamemap[y][x]==0){gamemap[y][x]=2;break;}} }GAME_NewFood在地圖上隨機生成一個食物,當(dāng)然這里的隨機數(shù),利用不斷變化的時鐘進行求余,得到的隨機坐標(biāo)后,先判斷該左邊是否可用,若是已經(jīng)存在東西(蛇身或者邊框)則繼續(xù)獲取隨機數(shù),如此反復(fù)直到得到一個空的的隨機坐標(biāo)。所以,當(dāng)游戲玩到最后,蛇身很長的時候(界面沒有多少空白點),產(chǎn)生食物的時間會長很多。
unsigned char Game_InputHandle(unsigned char event)//對輸入按鍵事件的處理 {unsigned char ret=0;if(GameStatus==GAMEPAUSE&&event!=RESTART_EV){ //游戲狀態(tài)未運行時,除非按下restart,否則不進入return 0;}if(event==5-Snokedirection){//按下蛇前進的相反方向時,忽略event=NON; }switch(event){case NON:speed_max=200;if(If_TimeOut(&speed_move,SPPED_MOVE)){ //自動前進Tick_Updata(&speed_move);event=Snokedirection;}else{break;}case TURN_LEFT_EV: //蛇向左移動case TURN_RIGHT_EV://蛇向右移動case TURN_DOWN_EV: //蛇向下移動 case TURN_UP_EV: //蛇向上移動 if(If_TimeOut(&speed_turn,speed_max)){Tick_Updata(&speed_turn);speed_max=150;Snokedirection=event;ret=GAME_SnakeMove(gamemap,&SnokeHeadNode,event,&GameScore); printf("event=%d\r\n",event);}break;case RESTART_EV://游戲復(fù)位if(If_TimeOut(&speed_restart,SPPED_RESTART_MAX)){Tick_Updata(&speed_restart);GameStatus=GAMERUNING;GameScore=0;Snokedirection=TURN_UP_EV;GAME_BackgroundInit(gamemap);GAME_NewSnake(&SnokeHeadNode);GAME_NewFood(gamemap);ret=1;printf("event=%d\r\n",event);}break;default://errorbreak;}return ret; }Game_InputHandle函數(shù)在main函數(shù)里被調(diào)用,SPPED_MOVE這個宏是控制蛇自動移動的速度的,所設(shè)置的值越低則運動的越快。speed_max的值是控制手動移動的速度,當(dāng)搖桿狀態(tài)被持續(xù)維持為一個方向時,就會按照該速度進行前進。
源碼添加了許多注釋,歡迎下載。若有疑問歡迎提出。
相關(guān)推薦:
基于stm32、0.96寸OLED實現(xiàn)的俄羅斯方塊小游戲(詳細源碼注釋)
?
<<天下難事,必做于易;天下大事,必做于細。——老子>>
總結(jié)
以上是生活随笔為你收集整理的基于stm32、0.96寸OLED实现的贪吃蛇小游戏(详细源码注释)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于stm32、0.96寸OLED实现的
- 下一篇: stm32之电源管理(实现低功耗)