|
源碼+需要用到的輔助軟件分享
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
我是一個(gè)普通二本學(xué)校電氣的學(xué)生。今年大三。
這個(gè)東西是我大二的時(shí)候做的玩的。
這里面有我做51單片機(jī)+12864液晶的貪吃蛇游戲機(jī)的詳細(xì)資料。仿真實(shí)物我都做過(guò),效果我自己比較滿意。花的精力也比較多,代碼也全都是自己一行一行的寫下來(lái)。所以做完之后想把這些東西都整理一下,然后放在上面,方便后面要做這些東西的人。
open精神在國(guó)內(nèi)是很重要的說(shuō)···0 0、
環(huán)境: keil V4.02 protues version 7.5
我先說(shuō)下我這個(gè)東西最主要的幾塊。
1.單片機(jī)用的是stc的,51內(nèi)核,你首先要會(huì)這個(gè)···
2.用狀態(tài)機(jī)實(shí)現(xiàn)按鍵。這個(gè)里面有別人寫的技術(shù)帖子··
3.液晶是12864,2種控制器都做過(guò),一個(gè)控制器是ST7920帶字庫(kù)的,一個(gè)控制器是KS0108不帶字庫(kù)的。2個(gè)的英文資料我都放在里面了。首先得弄懂液晶要怎么樣和單片機(jī)連接。
要在液晶上面做游戲,推薦先看英文資料,一定要看英文,研究液晶讀寫時(shí)序和初始化方法,然后找別人的程序,實(shí)現(xiàn)液晶的基本操作,畫點(diǎn),寫漢字什么的,讀液晶···然后自己寫程序?qū)崿F(xiàn)液晶的所有基本操作。這樣才能對(duì)液晶有充分的認(rèn)識(shí),才能開始在上面做游戲。有了這個(gè)基礎(chǔ),以后學(xué)別的液晶也會(huì)快的多。
4.菜單,游戲少不了要用到菜單,比如選擇難度,選擇地圖什么的。我里面放了一個(gè)別人的文檔,看了之后應(yīng)該就會(huì)自己寫了。(注意文檔里面講的是用函數(shù)指針實(shí)現(xiàn)菜單,但是KEIL這個(gè)環(huán)境下用51函數(shù)指針會(huì)很困難,推薦像我那樣直接傳菜單號(hào))
5.貪吃蛇游戲,推薦先不要看別人的程序,自己在電腦上面下個(gè)貪吃蛇游戲,玩的時(shí)候就觀察貪吃蛇游戲的特征···比如蛇在怎么動(dòng),蛇要怎么描述,是每個(gè)點(diǎn)都描述還是只要蛇頭蛇尾···蛇轉(zhuǎn)彎的時(shí)候怎么寫? 對(duì)于上面的問(wèn)題,可以參考別人的程序,然后就開始動(dòng)手畫圖什么的表示出來(lái)這些過(guò)程,一個(gè)功能一個(gè)功能逐一實(shí)現(xiàn)。(推薦看帶字庫(kù)的那個(gè)程序,那個(gè)程序代碼是最終優(yōu)化版本。思路很清晰···)
6.液晶的動(dòng)畫,動(dòng)畫實(shí)際上就是圖片一張一張的顯示,我在里面放了一個(gè)把彩色照片黑白二值化的工具,可以找到自己喜歡的GIF動(dòng)畫,用提取工具把照片一張一張?zhí)崛〕鰜?lái),然后黑白二值化,然后取模工具取模,然后實(shí)現(xiàn)···雖然過(guò)程蠻枯燥,但是效果還不過(guò),也可以學(xué)到不少東西。
最后希望大家在看這個(gè)的時(shí)候,特別是貪吃蛇游戲?qū)崿F(xiàn)的時(shí)候,哪一個(gè)方面有更好的辦法一定通知我,因?yàn)槲矣X(jué)得我實(shí)現(xiàn)貪吃蛇游戲的方法已經(jīng)很不錯(cuò)了。如果能有更好的,我會(huì)非常希望學(xué)習(xí)下····
單片機(jī)源程序如下:
- #include <st7920.h>
- #include <tanchishe_resource.h>
- #define num 15
- //用來(lái)描述蛇在液晶上面一個(gè)點(diǎn)的結(jié)構(gòu)體
- struct she
- {
- unsigned char x,y;
- unsigned int value;
- unsigned char direction;
- };
- struct loop_queue //利用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列,拐點(diǎn)不會(huì)超過(guò)15個(gè)。所以大小選15足以。
- {
- unsigned int front;
- unsigned int rear;
- unsigned int count;
- struct she dat[num];
- };
- //不熟悉數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列的可以在紙上畫一下操作過(guò)程
- struct she tou,wei,food; //蛇的頭尾節(jié)點(diǎn) 和食物點(diǎn)
- struct loop_queue queue;//循環(huán)隊(duì)列 蛇轉(zhuǎn)彎則形成拐點(diǎn) 將拐點(diǎn)入隊(duì)列 尾巴到達(dá)拐點(diǎn)則拐點(diǎn)出隊(duì)列
- unsigned char flag_exit_game; //返回標(biāo)志 為1時(shí) 從貪吃蛇游戲返回菜單
- unsigned char flag_game_over; //結(jié)束標(biāo)志 為1時(shí) 顯示游戲結(jié)束畫面 同時(shí)使返回標(biāo)志為1
- unsigned char tcs_key_flag; //貪吃蛇在一次移動(dòng)中 只允許捕獲一次按鍵 也就是只能產(chǎn)生一個(gè)拐點(diǎn)
- unsigned char tcs_key_state; //用于按鍵狀態(tài)機(jī)的實(shí)現(xiàn)
- unsigned int tcs_df; //貪吃蛇得分
- unsigned char tcs_stop;//貪吃蛇暫定功能的實(shí)現(xiàn)
- unsigned char tcs_nd; //貪吃蛇難度的選擇
- unsigned char tcs_dt; //貪吃蛇地圖的選擇 這2個(gè)是全局變量 在menu里面要用到
- void tcs_bianjie(unsigned int he);//貪吃蛇游戲地圖的實(shí)現(xiàn)和邊界
- void timer0_initial();
- void timer1_initial();
- //循環(huán)隊(duì)列的基本操作
- void queue_initial(struct loop_queue *q);
- void queue_in(struct loop_queue *q,struct she h) ;
- struct she queue_out(struct loop_queue *q) ;
- void tcs_game_initial();
- void food_produce();
- void tcs_game()
- {
- struct she check; //用與暫存蛇即將移動(dòng)的點(diǎn) 從而進(jìn)行判斷
- unsigned int he;
- unsigned char flag;//flag作為吃到食物的標(biāo)志
- flag_exit_game=0;
- flag_game_over=0;
- tcs_key_state=0;
- tcs_df=0;
- tcs_stop=1;
- // draw_lcd_picture(&tcs_picture[0]); //貪吃蛇游戲畫面
- // delay_ms(2000);
- tcs_bianjie(tcs_dt); //貪吃蛇游戲邊界
- tcs_game_initial();//貪吃蛇初始化 主要是設(shè)定蛇頭蛇尾 并顯示蛇
- timer0_initial(); //定時(shí)器0工作在方式2 8位自動(dòng)裝初值 只計(jì)數(shù)不中斷 用來(lái)產(chǎn)生隨機(jī)數(shù)
- timer1_initial(); //定時(shí)器1工作在方式1 16位 10ms中斷一次掃描鍵盤
- do
- {
- food_produce();//產(chǎn)生一個(gè)隨機(jī)數(shù) 即隨即產(chǎn)生x y value3個(gè)值確定一個(gè)點(diǎn)為食物
- he=test_point_exist(food.x,food.y,food.value);//檢測(cè)產(chǎn)生的點(diǎn)的地方是否已經(jīng)有點(diǎn)存在
- }
- while(he==food.value);//如果隨機(jī)數(shù)產(chǎn)生在蛇的身體以及邊界上 則重新再產(chǎn)生一個(gè)
- draw_lcd_point(food.x,food.y,food.value);//顯示食物 先讀取這個(gè)點(diǎn)所在xy的情況 以免破壞現(xiàn)場(chǎng)
-
- queue_initial(&queue);//初始化循環(huán)隊(duì)列 使隊(duì)列空 front rear 即頭尾指針為0
- while(1)
- {
- if(flag_exit_game==1)//如果游戲過(guò)程中按下返回鍵 則立即結(jié)束游戲 返回菜單
- break;
- if(flag_game_over==1)//如果游戲過(guò)程中蛇死了 則立即結(jié)束游戲 顯示結(jié)束動(dòng)畫 按鍵后返回菜單
- break;
-
- ET1=1; //允許掃描按鍵 貪吃蛇游戲難度決定蛇2次移動(dòng)之間的間隔時(shí)間 也就是檢測(cè)按鍵的時(shí)間
- tcs_key_flag=0; //允許捕獲按鍵 在檢測(cè)按鍵時(shí)間內(nèi) 只允許生產(chǎn)一個(gè)拐點(diǎn) 即捕獲到一個(gè)有效的
- //按鍵以后 就置一這個(gè)變量 不允許再增加拐點(diǎn)
- while(tcs_stop==0);//暫定鍵按下會(huì)取反tcs_stop的值 從而實(shí)現(xiàn)暫停功能
- switch(tcs_nd)
- {
- case 0: {delay_ms(10); break;}//0代表變態(tài)難度 蛇的2次移動(dòng)之間只有10ms的機(jī)會(huì)檢測(cè)鍵盤按下
- case 1: {delay_ms(50); break;}//難度減小 2次移動(dòng)間隔增加
- case 2: {delay_ms(100); break;}
- }
- ET1=0;
- switch(tou.direction)//這個(gè)switch用來(lái)根據(jù)蛇頭的x y value值以及當(dāng)前蛇頭移動(dòng)的方向
- //取出蛇頭要到達(dá)的下一個(gè)點(diǎn) 存入check中 來(lái)判斷是否撞墻 吃到食物 什么的···
- {
- case 0: {
- check.y=tou.y;
- if(tou.value==0x0001)//x的值要發(fā)生改變
- {
- if(tou.x==3)//蛇碰到上屏幕的右邊界 則回到左邊界
- check.x=0;
- else if(tou.x==11)//蛇碰到下屏幕的右邊界 則回到左邊界
- check.x=8;
- else
- check.x=tou.x+1;
- check.value=0x8000;
- }
- else
- {
- check.x=tou.x;
- check.value=tou.value>>1;
- }
- break ;
- }//->向右y不變
- case 1: {//向下value值不變
- check.value=tou.value;
- if(tou.y==31) //蛇頭從在上下屏之間移動(dòng)
- {
- if(tou.x<=3)//蛇頭從上屏移動(dòng)到下屏
- check.x=tou.x+8;
- else //蛇頭從下屏移動(dòng)到上屏
- check.x=tou.x-8;
- check.y=0;
- }
- else
- {
- check.y=tou.y+1;
- check.x=tou.x; //蛇頭的x值不變
- }
- break ;
- }
- case 2: {//<-向左y不變
- check.y=tou.y;
- if(tou.value==0x8000)//x的值要發(fā)生改變
- {
- if(tou.x==0)//蛇碰到上屏幕的左邊界 則回到右邊界
- check.x=3;
- else if(tou.x==8)//蛇碰到下屏幕的左邊界 則回到右邊界
- check.x=11;
- else
- check.x=tou.x-1;
- check.value=0x0001;
- }
- else
- {
- check.x=tou.x;
- check.value=tou.value<<1;
- }
- break ;
- }
- case 3: { //↑ 向上value不變
- check.value=tou.value;
- if(tou.y==0) //蛇頭從在上下屏之間移動(dòng)
- {
- if(tou.x<=3)//蛇頭從上屏移動(dòng)到下屏
- check.x=tou.x+8;
- else //蛇頭從下屏移動(dòng)到上屏
- check.x=tou.x-8;
- check.y=31;
- }
- else
- {
- check.y=tou.y-1;
- check.x=tou.x; //蛇頭的x值不變
- }
- break ;
- }
- }
- flag=0;//初始化吃到食物標(biāo)志 表示沒(méi)有吃到
- he=test_point_exist(check.x,check.y,check.value); // 檢測(cè)蛇頭移動(dòng)的下一個(gè)點(diǎn)是否幾經(jīng)有點(diǎn)存在
- if(he==check.value) //如果前面的點(diǎn)已經(jīng)存在 則可以是食物 或者是墻和蛇身
- {
- if( (check.x==food.x) && (check.y==food.y) && (check.value==food.value) )//吃到食物
- {
- flag=1;//吃到食物
- tcs_df++;
- write_lcd_shuzi(5,16,tcs_shuzi[tcs_df/100] ); //顯示分?jǐn)?shù)的百位
- write_lcd_shuzi(6,16,tcs_shuzi[ (tcs_df%100)/10] ); // 十
- write_lcd_shuzi(7,16,tcs_shuzi[tcs_df%10] ); // 個(gè)
-
- food.direction=tou.direction;//食物本沒(méi)有方向 但是為了下面的語(yǔ)句
- tou=food; //食物就成了蛇頭···蛇頭的方向依然不變
-
- do
- {
- food_produce();
- he=test_point_exist(food.x,food.y,food.value);
- }
- while(he==food.value);
- draw_lcd_point(food.x,food.y,food.value);//上面有說(shuō)過(guò) 這個(gè)是產(chǎn)生并顯示食物
- }
- else//撞到身體或者墻
- {
- flag_game_over=1; // 游戲結(jié)束
- }
- }
- else //什么都么有遇到 繼續(xù)前進(jìn)
- {
- check.direction=tou.direction;//這么做的理由同上 為了保持蛇頭當(dāng)前的移動(dòng)方向
- tou=check;
- draw_lcd_point(tou.x,tou.y,tou.value);//畫出此時(shí)的蛇頭
- }
- //下面是對(duì)尾巴的操作
-
- if(flag==1)//如果吃到食物 直接結(jié)束此輪循環(huán) 尾巴不做任何操作
- {
-
- }
- else
- {
- if ( (wei.x == queue.dat[queue.front].x) && ( wei.y==queue.dat[queue.front].y ) && ( wei.value== queue.dat[queue.front].value) ) //如果尾巴到達(dá)拐點(diǎn)
- {
- check=queue_out(&queue);
- wei.direction=check.direction; //尾巴按照拐點(diǎn)指示的方向走
- }
- else //如果沒(méi)有到達(dá)拐點(diǎn) 尾巴移動(dòng)的方向不變
- {
-
- }
-
- switch( wei.direction ) //這個(gè)是尾巴的移動(dòng) 以及尾巴節(jié)點(diǎn)數(shù)據(jù)的修改
- {
- case 0: {//->向右y不變
- clear_lcd_point(wei.x,wei.y,wei.value);
- if(wei.value==0x0001)//x的值要發(fā)生改變
- {
- if(wei.x==3)//蛇碰到上屏幕的右邊界 則回到左邊界
- wei.x=0;
- else if(wei.x==11)//蛇碰到下屏幕的右邊界 則回到左邊界
- wei.x=8;
- else
- wei.x=wei.x+1;
- wei.value=0x8000;
- }
- else
- {
- wei.value=wei.value>>1;
- }
- break;
- }
- case 1: {//向下value值不變
- clear_lcd_point(wei.x,wei.y,wei.value);
- if(wei.y==31) //蛇從在上下屏之間移動(dòng)
- {
- if(wei.x<=3)//蛇從上屏移動(dòng)到下屏
- wei.x=wei.x+8;
- else //蛇從下屏移動(dòng)到上屏
- wei.x=wei.x-8;
- wei.y=0;
- }
- else
- {
- wei.y=wei.y+1;
- }
- break ;
-
- }
- case 2: {//<-向左y不變
- clear_lcd_point(wei.x,wei.y,wei.value);
- if(wei.value==0x8000)//x的值要發(fā)生改變
- {
- if(wei.x==0)//蛇碰到上屏幕的左邊界 則回到右邊界
- wei.x=3;
- else if(wei.x==8)//蛇碰到下屏幕的左邊界 則回到右邊界
- wei.x=11;
- else
- wei.x=wei.x-1;
- wei.value=0x0001;
- }
- else
- {
- wei.value=wei.value<<1;
- }
- break;
- }
- case 3: {//↑ 向上value不變
- clear_lcd_point(wei.x,wei.y,wei.value);
- if(wei.y==0) //蛇從在上下屏之間移動(dòng)
- {
- if(wei.x<=3)//蛇從上屏移動(dòng)到下屏
- wei.x=wei.x+8;
- else //蛇從下屏移動(dòng)到上屏
- wei.x=wei.x-8;
- wei.y=31;
- }
- else
- {
- wei.y=wei.y-1;
- }
- break;
- }
- }
- }
- }
- TR0=0;
- TR1=0;
- ET1=0; //退出游戲時(shí) 關(guān)閉游戲過(guò)程中用到的定時(shí)器0和1 然后定時(shí)器中斷也要關(guān)閉
- }
- //狀態(tài)機(jī)實(shí)現(xiàn)按鍵 參考里面資料別人的技術(shù)貼
- void timer1() interrupt 3
- {
- unsigned char tou_last_direction; //記錄蛇頭原來(lái)的移動(dòng)方向
-
- TR1=0;
- TH1=0xDC;
- TL1=0x00;
- switch (tcs_key_state)
- {
- case 0: { // 按鍵初始態(tài)
- if ( (P2 & 0xfe) != 0xfe ) tcs_key_state = 1; // 鍵被按下,狀態(tài)轉(zhuǎn)換到鍵確認(rèn)態(tài)
- else tcs_key_state = 0;
- break;
- }
-
- case 1: { // 按鍵確認(rèn)態(tài)
- if ( (P2 & 0xfe) != 0xfe)
- {
- // 按鍵仍按下,此時(shí)確定記錄一次有效按鍵
- tcs_key_state = 2; // 狀態(tài)轉(zhuǎn)換到鍵釋放態(tài)
- if(tcs_key_flag==0) //如果此時(shí)允許捕獲按鍵
- {
- tou_last_direction=tou.direction;
- switch(P2 & 0xfe)
- {
- case 0xfc: break; // 確定鍵 不進(jìn)行任何操作
- case 0xfa: { flag_exit_game=1; break; }//返回鍵 結(jié)束游戲 返回菜單
- case 0xbe: { tou.direction=3;break; }//↑
- case 0xee: { tou.direction=2;break; }//←
- case 0xde: { tou.direction=1;break; }//↓
- case 0x7e: { tou.direction=0;break; }//->
- case 0xf6: { if(tcs_stop==0) tcs_stop=1; else tcs_stop=0; break;}//暫停鍵
- }
-
- if( (tou.direction==tou_last_direction) || (tou.direction+tou_last_direction==2) || (tou.direction+tou_last_direction==4) )
- //如果本來(lái)就是按此方向移動(dòng) 或者按鍵給的方向與蛇移動(dòng)方向相反 則不做任何操作 此次按鍵無(wú)效
- {
- tou.direction=tou_last_direction; // 還原蛇頭的移動(dòng)方向
- }
- else //否則記錄此頭結(jié)點(diǎn)成為拐點(diǎn)
- {
- queue_in(&queue,tou);
- tcs_key_flag=1; //已經(jīng)捕獲到一次按鍵信息 這次移動(dòng)拐點(diǎn)已經(jīng)產(chǎn)生 關(guān)閉捕獲鍵盤
-
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
51單片機(jī) 12864液晶貪吃蛇游戲機(jī)(完美版).7z
(6.69 MB, 下載次數(shù): 180)
2021-5-16 04:48 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|