這是我以前做的一個貪吃蛇課程設計。
此次的ARM7最小系統(tǒng)的課程設計是基于LPC2124以及LCD-CSTN20GG0906N7CUN6和按鍵電路。采用ISIS7 Professional軟件自行搭建電路。里面帶有實驗報告,里面都是干貨,希望對大家有用。
目錄
1. 課程設計內容
2. 課程設計目的
3. 背景知識
4. 工具/準備工作 4
5. 設計步驟與方法 4
5.1. 步驟1:在Proteus仿真軟件上設計電路圖 4
5.2. 步驟2:畫蛇 5
5.2.1. 步驟1.1:蛇的產生 5
5.3. 步驟3:食物的產生 6
5.4. 步驟4:蛇的移動 7
5.4.1. 步驟1.1:按鍵的掃描 8
5.5. 步驟5:蛇節(jié)的增長 8
5.5.1. 步驟1.1:判斷蛇是否吃到食物 9
5.5.2. 步驟1.2:速度的增長 10
5.6. 步驟6:游戲是否結束 10
5.7. 步驟7:LCDHDG12864L-6的顯示 11
5.8. 步驟8:重新開始與暫停按鍵 11
6. 設計結果及分析 12
7. 設計結論 13
8. 問題及心得體會 13
9. 對本設計過程及方法、手段的改進建議 14
10. 參考文獻 14
11. 課程設計評價(教師) 14
全民貪吃蛇
1. 課程設計內容此次ARM7最小系統(tǒng)的課程設計是基于LPC2124以及LCD-CSTN20GG0906N7CUN6和按鍵電路。采用ISIS 7 Professional軟件自行搭建電路。本系統(tǒng)的特點是性能高、成本低并且耗能小等特點。 2. 課程設計目的此次課程設計的主要目的是讓我們提高代碼的熟練度,以及發(fā)揮自主創(chuàng)新,將平時上課學到的理論知識與實驗知識相結合。讓我們對arm7芯片以及ISIS 7 Professional仿真模擬器更為了解。 - 熟練掌握向量中斷IRQ的初始化和對中斷的處理過程。
- 熟練掌握定時器的控制和使用方法。
- 熟練掌握C語言的使用原理及編程方法。
- 熟練掌握仿真電路圖的連接方法。
- 熟練掌握兩個不同的液晶顯示器的顯示控制原理及編程方法。
3. 背景知識ARM處理器的三大特點是:耗電少功能強、16位/32位雙指令集和合作伙伴眾多。 1、體積小、低功耗、低成本、高性能; 2、支持Thumb(16位)/ARM(32位)雙指令集,能很好的兼容8位/16位器件; 3、大量使用寄存器,指令執(zhí)行速度更快; 4、大多數(shù)數(shù)據(jù)操作都在寄存器中完成; 5、尋址方式靈活簡單,執(zhí)行效率高; 6、指令長度固定。 設計原理:貪吃蛇游戲是一款經典的游戲,既簡單又耐玩。通過控制蛇頭方向吃蛋,使得蛇變長,從而獲取積分。用游戲把子上下左右控制蛇的方向,尋找吃的東西,每吃一口就能得到一定的積分,而且蛇的身子會越吃越長,身子越長玩的難度就越大,不能碰墻,不能咬到自己的身體,更不能咬自己的尾巴,等到了一定的分數(shù),就能過關,然后繼續(xù)玩下一關。
4. 工具/準備工作- CodeWarrior project file軟件。
- ISIS 7 Professional軟件。
- 了解Proteus仿真軟件和ARM編程軟件的使用方法。
- 了解ARM7芯片的編程方法。
5. 設計步驟與方法5.1.步驟1:在Proteus仿真軟件上設計電路圖  5.2.步驟2:畫蛇由于采用的是LCD-CSTN20GG0906N7CUN6,首先根據(jù)其數(shù)據(jù)手冊對該LCD進行繪畫,先寫入命令對其進行寫操作WR_CMD(0xBC);WR_DATA(0); WR_DATA(00); WR_DATA(00); 然后寫入命令WR_CMD(0x75);意為寫入x軸,后接x軸的具體數(shù)據(jù)以及x軸的最大值。緊接著寫入WR_CMD(0x15);意為寫入y軸,后接y軸的具體數(shù)據(jù)以及y軸的最大值。 void snake_display(int x,int y) { int i,j; WR_CMD(0xBC); WR_DATA(0); WR_DATA(00); WR_DATA(00); WR_CMD(0x75); WR_DATA(x); WR_DATA(63); WR_CMD(0x15); WR_DATA(y); WR_DATA(95); WR_CMD(0x5c); for(j=0;j<1;j++) { for(i=0;i<1;i++){ WR_DATA(0xf8);//0xff WR_DATA(0x00); }} } 5.2.1步驟1.1:蛇的產生首先創(chuàng)建一個蛇的結構體Point,該結構體內存儲了蛇的x、y坐標,以及蛇的長度和蛇的方向,然后通過rand函數(shù)產生隨機數(shù)存在Snake的x、y中,即蛇的初始位置是隨機的,然后再通過snake_init()函數(shù)中對蛇進行初始化,然后通過循環(huán)在snake_display(int x,int y)函數(shù)中把蛇畫出來。 - void snake_init()
- {
- int i;
- snake_state();
- Snake.x[0] = rand()%62;
- Snake.y[0] = rand()%95;
- Snake.x[1] = Snake.x[0]+1;
- Snake.y[1] = Snake.y[0];
- Snake.x[2] = Snake.x[1] +1;
- Snake.y[2] = Snake.y[0] ;
- Snake.num = 3;
- for(i=0;i<Snake.num;i++)
- snake_display(Snake.x[i],Snake.y[i]);
- }
復制代碼
5.3.步驟3:食物的產生首先創(chuàng)建一個食物的結構體point,在該結構體的基礎上定義一個數(shù)組food_map,通過這個結構體對地圖進行修改。該結構體內存儲了食物的x、y坐標,以及食物的長度,然后通過rand函數(shù)產生隨機數(shù)保存在food_map中,即食物的出現(xiàn)位置是隨機的,然后再通過food_init()函數(shù)中對食物進行初始化,然后通過循環(huán)在food_display(int x,int y)函數(shù)中把食物畫出來(食物的畫法與步驟一中蛇的畫法是一樣的,只不過食物的顏色是黃色,蛇的顏色是紅色,便于確認)。 當蛇吃了一定數(shù)量的食物時,通過調用食物產生函數(shù),重新產生新的食物,以保證食物的存在性。
- void food()
- {
- int i;
- if(create_food==1)
- {
- for(i=food_long;i<food_long+8;i++)
- {
- food_map[i].x=rand()%62;
- food_map[i].y=rand()%93;
- }
- food_long+=8;
- create_food=0;
- }
- }
- void food_map_init()
- {
- int i;
- food();
- for(i=0;i<food_long;i++)
- food_display(food_map[i].x,food_map[i].y);
- }
復制代碼
5.4.步驟4:蛇的移動若相應方向的按鍵被按下,則蛇就會往相應的方向移動。首先要把蛇之前走過的痕跡擦掉(擦掉的函數(shù)如同畫蛇,把顏色數(shù)據(jù)改為背景色即可),然后將蛇從最后個節(jié)點向前一個節(jié)點移動,這是蛇的最核心算法。最后通過switch case判斷哪一個按鍵被按下,然后對蛇頭的方向,即Snake.direction進行修改。蛇的移動函數(shù)放在中斷中,每次發(fā)生中斷都會重新畫蛇(蛇的移動即把原來的蛇尾巴擦掉,然后根據(jù)新的坐標重新畫蛇)。當按鍵沒有被按下時,蛇會按照上一次按下按鍵的方向去移動(初始化時默認向右)。
- void snake_move()
- {
- char i;
- int j;
- if(flag==1)
- {
- Snake.num++;
- flag=0;
- }
- for(i=0;i<food_long;i++)
- food_display(food_map[i].x,food_map[i].y);
- clear_snake(Snake.x[Snake.num-1],Snake.y[Snake.num-1]);
- for(i = Snake.num - 1; i > 0; i--) // 將蛇從最后個節(jié)點向前一個節(jié)點移動
- {
- Snake.x[i] = Snake.x[i - 1];
- Snake.y[i] = Snake.y[i - 1];
- }
- snake_state();
- switch(Snake.direction)
- {
- case 1:
- Snake.x[0] -=1 ;
- break;
- case -1:
- Snake.x[0] +=1 ;
- break;
- case 2:
- Snake.y[0] -=1 ;
- break;
- case -2:
- Snake.y[0] +=1 ;
- break;
- }
- for(i=0;i<Snake.num;i++)
- snake_display(Snake.x[i],Snake.y[i]);
- }
復制代碼
5.4.1. 步驟1.1:按鍵的掃描 通過IOxPIN來確定按鍵是否按下,由于按鍵接在P1.20-P1.23,因此是I01PIN。通過讀取各個按鍵的狀態(tài)封裝在snake_state函數(shù)里。如果上鍵按下,Snake.directio則相應為上(Snake.direction是蛇的結構體Point里的成員用于確定蛇的方向)。其余方向的設置同上。 void snake_state() { if(!(IO1PIN&key_w))Snake.direction=1;//上 else if(!(IO1PIN&key_s))Snake.direction= -1;//下 else if(!(IO1PIN&key_a))Snake.direction= 2;//左 else if(!(IO1PIN&key_d))Snake.direction= -2;//右 }
5.5.步驟5:蛇節(jié)的增長 如果蛇吃到了食物,此時的蛇應該變長,即Snake.num++,在蛇尾的部分添加一個點即可,新的一節(jié)先放在看不見的位置,下次循環(huán)就取前一節(jié)的位置。先把這條蛇擦掉,然后重新畫蛇。 if(flag==1) { Snake.num++; flag=0; }
5.5.1. 步驟1.1:判斷蛇是否吃到食物 如果蛇頭的x、y坐標與food_map中的任一x、y坐標均相等,則說明蛇已經吃了食物,此時要對食物進行擦除(食物的擦除與食物的繪畫是一樣的,只需要把顏色改為跟背景色一樣即可)。
- void checkeat()
- {
- int i,time;
- for(i=0;i<food_long;i++)
- { if((Snake.y[0]==food_map[i].y)&&(Snake.x[0]==food_map[i].x)||(Snake.y[Snake.num-1]==food_map[i].y)&&(Snake.x[Snake.num-1]==food_map[i].x))
- {
- flag=1;
- NUMBER++;//
- if(NUMBER>9)NUMBER=0;
- print_score();//
- eat++;
- if(eat%4==0)create_food=1;
- if(eat%1==0)
- {
- LEVEL++;
- speed-=50;
- if(LEVEL>9)LEVEL=0;
- print_level();
- }
- clear_food(food_map[i].x,food_map[i].y);
- food_map[i].x=NULL;
- food_map[i].y=NULL;
- break;
- }
- }
- }
復制代碼
5.5.2. 步驟1.2:速度的增長 當蛇吃到一定數(shù)量的食物時,游戲的等級會增加,此時蛇的速度就會變快,通過改變定時器的定時時長可以實現(xiàn),即改變T0TR,首先設定一個speed變量值,當游戲中的LEVEL++時,speed的值減小,此時定時器的定時時長會縮短,會,從而導致蛇的移動掃描變快,因而實現(xiàn)了蛇的速度的變化。 void speed_change() { T0PR = speed; }
5.6.步驟6:游戲是否結束 如果蛇跑出了LCD所能表示的范圍,即蛇頭小于0或者大于63,蛇尾小于0或者大于95,則視為死亡,游戲結束,顯示結束圖片。如果需要繼續(xù)游戲則按下重新開始按鈕。 如果蛇頭撞上了身體的任意環(huán)節(jié)(通過循環(huán)來一節(jié)節(jié)地進行判斷),則視為死亡,游戲結束,顯示結束圖片。如果需要繼續(xù)游戲則按下重新開始按鈕。 反之,游戲繼續(xù)。 如果最終的等級大于9級,則游戲勝利,顯示勝利圖片。如果需要繼續(xù)游戲則按下重新開始按鈕。
- void snake_life()
- {
- int i;
- if(Snake.x[0] < 0 || Snake.x[0] > 63 || Snake.y[0] < 0 || Snake.y[0] >95) die=1;
- for(i=3;i<Snake.num;i++)
- {
- if(Snake.x[i]==Snake.x[0]&&Snake.y[i]==Snake.y[0])
- {
- die=1;
- break;
- }
- }
- }
復制代碼
5.7.步驟7:LCDHDG12864L-6的顯示 該LCD用來顯示游戲的名稱、制作人、等級以及分數(shù)。根據(jù)該LCD的數(shù)據(jù)手冊首先寫入的是y的值,然后寫入x的值,來確定所寫的字的位置,先寫字的上半部分,然后重新寫入y的值,x的值不變,再寫字的下半部分。 每次蛇吃到食物時,分數(shù)就會增加。分數(shù)的字模放在一個數(shù)組里,通過下標調用顯示。當蛇吃到了一定數(shù)量的食物之后,等級就會隨之增加,等級的字模也是放在一個數(shù)據(jù)里,通過下標調用顯示。 void print_level() { int j; WR_CMD1(0xb0+4); WR_CMD1(0x10); WR_CMD1(0x00+51); for(j=0;j<8;j++) { WR_DATA1(number[LEVEL][0][j]); } WR_CMD1(0xb0+5); WR_CMD1(0x10); WR_CMD1(0x00+51); for(j=0;j<8;j++) { WR_DATA1(number[LEVEL][1][j]); } }
5.8.步驟8:重新開始與暫停按鍵 設置兩個按鍵用于重新開始游戲以及暫停游戲。 重新開始游戲時,先把顯示蛇的LCD的屏幕清屏。把成績與等級初始化為0,然后對游戲的所有參數(shù)重新進行初始化。 暫停按鈕的實現(xiàn)十分簡單,只需要把蛇的移動方向設為空即可。此時,蛇不會再移動。若要繼續(xù)游戲,則按任意方向鍵繼續(xù)。 void button() { if(!(IO1PIN&restart)) { LCD_clear(); die=0; LEVEL=0; NUMBER=0; flag=0; eat=0; speed=1000; Snake.direction=NULL; food_map_init(); create_food=0; score_init(); print_score(); print_level(); snake_init(); food_map_init(); } if(!(IO1PIN&stop)) { Snake.direction=NULL; } } 6. 設計結果及分析設計結果:蛇的出現(xiàn)位置與食物的出現(xiàn)位置都是隨機的。當按下相對應的按鍵時,蛇會往那個方向走,當蛇吃到食物時,分數(shù)會增加。當蛇吃到一定數(shù)量的食物時,等級和速度也會隨之增加,當食物少于一定數(shù)量時,會出現(xiàn)新的食物。當?shù)燃夁_到9時,游戲結束,玩家勝出,播放勝利圖片。如果蛇吃到自身,或者撞到墻,則游戲結束,玩家失敗,播放失敗圖片。 設計分析:這個程序的關鍵是表示蛇的圖形以及蛇的移動。用一個小矩形表示蛇的一節(jié)身體,身體每長一節(jié),增加一個矩形塊。如果不按任何鍵,蛇自行在當前方向上前移,當游戲者按了有效的方向鍵后,蛇頭朝著指定的方向移動,一步移動一節(jié)身體,所以當按了有效的方向鍵后,先確定蛇頭的位置,然后蛇身體隨著蛇頭移動,圖形的實現(xiàn)是從蛇頭的新位置開始畫出蛇,這時原來蛇的位置和新蛇的位置差一個單位,所以看起來蛇會多一節(jié)身體,所以將蛇的最后一節(jié)用背景色覆蓋。食物的出現(xiàn)和消失也是畫矩形塊和覆蓋矩形塊。 
7. 設計結論經過奮戰(zhàn)我的課程設計終于完成了。在沒有做課程設計以前覺得課程設計只是對嵌入式最小系統(tǒng)這門課程所學知識的單純總結,但是通過這次做課程設計發(fā)現(xiàn)自己的看法有點太片面。課程設計不僅是對前面所學知識的一種檢驗,而且也是對自己能力的一種提高。通過這次課程設計使我明白了自己原來知識還比較欠缺。自己要學習的東西還太多,以前老是覺得自己什么東西都會,什么東西都懂,有點眼高手低。通過這次課程設計,我才明白學習是一個長期積累的過程,在以后的工作、生活中都應該不斷的學習,提高自己的知識和綜合素質。 8. 問題及心得體會通過這次的課程設計讓我學到了許多編程知識,提高運用C語言解決實際問題的能力,鞏固了C語言的語法規(guī)則、掌握和理解,還提高了自學以及查閱資料的能力。我發(fā)現(xiàn)只有理論知識是不夠的,僅僅運用課上所學無法編實際問題,實際執(zhí)行過程與預想不一致,經常會出現(xiàn)bug。還因為在仿真軟件中用錯了一個LCD顯示器,導致程序卡在那里好幾天,當時用的是12864-6,一直卡在蛇的顯示,非常考驗我的邏輯與耐心。后來一怒之下?lián)Q了一個實驗中講過的LCD顯示器。必須把所學的理論知識和自身的實踐相結合,在編程中我學到了許多編程知識,還學會了如何去看器件的數(shù)據(jù)手冊,在實際編程中,我遇到許多困難,例如:蛇的頭部與食物的檢測問題,蛇的移動與顯示問題,蛇的轉向問題,食物的隨機生成問題等等,我通過在網上搜集資料與自己的分析。最后,終于完成了這個游戲。 9. 對本設計過程及方法、手段的改進建議在食物的設計的方面,可以放上帶道具的食物,使蛇吃完后具有保護,穿墻等特種功能,而且難度逐漸變難。還有設計一些障礙物,當蛇撞到障礙物時死亡。
全部資料51hei下載地址:
Snake.zip
(281.7 KB, 下載次數(shù): 122)
2018-12-2 18:46 上傳
點擊文件名下載附件
|