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