找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8618|回復(fù): 9
打印 上一主題 下一主題
收起左側(cè)

STM32打地鼠小游戲程序設(shè)計(jì)與源碼說明

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:361500 發(fā)表于 2018-12-13 09:12 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
打地鼠程序說明文檔:
項(xiàng)目是一款打地鼠的游戲,程序用到了延時(shí)函數(shù)、LED、電阻屏、按鍵燈功能,這些功能的初始化例程里面都有,我們可以直接調(diào)用來完成初始化。
    完成了初始化就開始程序的主干了,既然我們用到了電阻屏,肯定就需要對它進(jìn)行校準(zhǔn),校準(zhǔn)函數(shù)在觸摸屏例程也有,我們可以通過KEY0按鍵直接調(diào)用校準(zhǔn)函數(shù),用來防止觸摸屏不準(zhǔn)。
    然后我們先進(jìn)行的是界面顯示,先通過圖片取模軟件取出一個(gè)背景圖,注意取模的時(shí)候由于例程顯示那里標(biāo)注了,在液晶上畫圖(僅支持:從左到右,從上到下 or 從上到下,從左到右 的掃描方式。,圖片數(shù)據(jù)(必須包含圖片信息頭, 4096色/16位真彩色/18位真彩色/24位真彩色/32位真彩色的圖像數(shù)據(jù)頭),針對STM32,不能選擇image2lcd的"高位在前(MSB First)"選項(xiàng),否則imginfo的數(shù)據(jù)將不正確!我們按照標(biāo)注選擇了16位真彩色的取模方式,通過PS將圖片改為屏幕合適尺寸,就可以在屏幕上顯示出背景了。將前20行用來顯示分?jǐn)?shù),等級,生命屬性,他們通過字符串和數(shù)字變量的顯示函數(shù)來實(shí)現(xiàn), 后面300行做成3*3的地鼠洞,地鼠洞通過例程里面的畫實(shí)心圓來表示,用一個(gè)for來遍歷每個(gè)圓心坐標(biāo),讓代碼簡介,在用個(gè)隨機(jī)數(shù)函數(shù)產(chǎn)生0-8的數(shù)字來代表老鼠出現(xiàn)的位置,然后通過同樣的方法取出老鼠的圖片,根據(jù)洞圓心的坐標(biāo),找到老鼠顯示的坐標(biāo)顯示出老鼠,這里背景是指顯示一次的,老鼠變換一次刷新一次屏幕,刷新就只用刷新你目前的狀態(tài),洞的顯示和老鼠的位置,讓洞把老鼠覆蓋就可以不用刷新背景了。再游戲結(jié)束之后再重新刷新背景顯示游戲結(jié)束和繼續(xù)就好了。
    顯示完成了接下來就是觸摸,由于它的例程里面自帶觸摸函數(shù),可以直接調(diào)用來返回當(dāng)前的x,y坐標(biāo),這樣觸摸就很容易了
    key_9=(tp_dev.x[0]+1)/80+3*(tp_dev.y[0]+1-20)/100;
    用以上這段代碼就可以識別出觸摸的是之前分的3*3的那個(gè)位置,返回的1-9,然后再和老鼠對應(yīng)的坐標(biāo)進(jìn)行判斷就可以知道打?qū)εc否,對就加分,分到就升級,升級了就提高地鼠刷新次數(shù),錯就減分,減生命,分為0時(shí)就不減了,生命為0就游戲結(jié)束。還有不管對錯,只要點(diǎn)擊了屏幕地鼠的持續(xù)時(shí)間就會減短,馬上刷新下一只地鼠。就不用多余的等待。

單片機(jī)源程序如下:
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"
  5. #include "lcd.h"
  6. #include "key.h"  
  7. #include "24cxx.h"
  8. #include "myiic.h"
  9. #include "touch.h"
  10. #include "stdlib.h"

  11. #ifndef __IMAGE2LCD_H
  12. #define __IMAGE2LCD_H
  13. #include "sys.h"

  14. __packed typedef struct _HEADCOLOR
  15. {
  16.    unsigned char scan;
  17.    unsigned char gray;
  18.    unsigned short w;
  19.    unsigned short h;
  20.    unsigned char is565;
  21.    unsigned char rgb;
  22. }HEADCOLOR;  
  23. void image_display(u16 x,u16 y,u8 * imgx);//在指定位置顯示圖片
  24. void image_show(u16 xsta,u16 ysta,u16 xend,u16 yend,u8 scan,u8 *p);//在指定區(qū)域開始顯示圖片
  25. u16 image_getcolor(u8 mode,u8 *str);//獲取顏色
  26. extern const u8 gImage_1[];
  27. extern const u8 gImage_2[];
  28. #endif



  29. //ALIENTEK Mini STM32開發(fā)板范例代碼21
  30. //觸摸屏實(shí)驗(yàn)  
  31. //技術(shù)支持:www.openedv.com
  32. //廣州市星翼電子科技有限公司

  33. void Load_Drow_Dialog(void)
  34. {
  35.         LCD_Clear(WHITE);//清屏   
  36.          //POINT_COLOR=BLUE;//設(shè)置字體為藍(lán)色
  37.         //LCD_ShowString(lcddev.width-24,0,200,16,16,"RST");//顯示清屏區(qū)域
  38.           POINT_COLOR=RED;//設(shè)置畫筆藍(lán)色
  39. }
  40. ////////////////////////////////////////////////////////////////////////////////
  41. //電容觸摸屏專有部分
  42. //畫水平線
  43. //x0,y0:坐標(biāo)
  44. //len:線長度
  45. //color:顏色
  46. void gui_draw_hline(u16 x0,u16 y0,u16 len,u16 color)
  47. {
  48.         if(len==0)return;
  49.         LCD_Fill(x0,y0,x0+len-1,y0,color);        
  50. }
  51. //畫實(shí)心圓
  52. //x0,y0:坐標(biāo)
  53. //r:半徑
  54. //color:顏色
  55. void gui_fill_circle(u16 x0,u16 y0,u16 r,u16 color)
  56. {                                                                                          
  57.         u32 i;
  58.         u32 imax = ((u32)r*707)/1000+1;
  59.         u32 sqmax = (u32)r*(u32)r+(u32)r/2;
  60.         u32 x=r;
  61.         gui_draw_hline(x0-r,y0,2*r,color);
  62.         for (i=1;i<=imax;i++)
  63.         {
  64.                 if ((i*i+x*x)>sqmax)// draw lines from outside  
  65.                 {
  66.                          if (x>imax)
  67.                         {
  68.                                 gui_draw_hline (x0-i+1,y0+x,2*(i-1),color);
  69.                                 gui_draw_hline (x0-i+1,y0-x,2*(i-1),color);
  70.                         }
  71.                         x--;
  72.                 }
  73.                 // draw lines from inside (center)  
  74.                 gui_draw_hline(x0-x,y0+i,2*x,color);
  75.                 gui_draw_hline(x0-x,y0-i,2*x,color);
  76.         }
  77. }  
  78. //兩個(gè)數(shù)之差的絕對值
  79. //x1,x2:需取差值的兩個(gè)數(shù)
  80. //返回值:|x1-x2|
  81. u16 my_abs(u16 x1,u16 x2)
  82. {                        
  83.         if(x1>x2)return x1-x2;
  84.         else return x2-x1;
  85. }  
  86. //畫一條粗線
  87. //(x1,y1),(x2,y2):線條的起始坐標(biāo)
  88. //size:線條的粗細(xì)程度
  89. //color:線條的顏色
  90. void lcd_draw_bline(u16 x1, u16 y1, u16 x2, u16 y2,u8 size,u16 color)
  91. {
  92.         u16 t;
  93.         int xerr=0,yerr=0,delta_x,delta_y,distance;
  94.         int incx,incy,uRow,uCol;
  95.         if(x1<size|| x2<size||y1<size|| y2<size)return;
  96.         delta_x=x2-x1; //計(jì)算坐標(biāo)增量
  97.         delta_y=y2-y1;
  98.         uRow=x1;
  99.         uCol=y1;
  100.         if(delta_x>0)incx=1; //設(shè)置單步方向
  101.         else if(delta_x==0)incx=0;//垂直線
  102.         else {incx=-1;delta_x=-delta_x;}
  103.         if(delta_y>0)incy=1;
  104.         else if(delta_y==0)incy=0;//水平線
  105.         else{incy=-1;delta_y=-delta_y;}
  106.         if( delta_x>delta_y)distance=delta_x; //選取基本增量坐標(biāo)軸
  107.         else distance=delta_y;
  108.         for(t=0;t<=distance+1;t++ )//畫線輸出
  109.         {  
  110.                 gui_fill_circle(uRow,uCol,size,color);//畫點(diǎn)
  111.                 xerr+=delta_x ;
  112.                 yerr+=delta_y ;
  113.                 if(xerr>distance)
  114.                 {
  115.                         xerr-=distance;
  116.                         uRow+=incx;
  117.                 }
  118.                 if(yerr>distance)
  119.                 {
  120.                         yerr-=distance;
  121.                         uCol+=incy;
  122.                 }
  123.         }  
  124. }   
  125. const u16 POINT_COLOR_TBL[CT_MAX_TOUCH]={RED,GREEN,BLUE,BROWN,GRED};
  126. ////////////////////////////////////////////////////////////////////////////////
  127. //5個(gè)觸控點(diǎn)的顏色                                                                                                
  128. //電阻觸摸屏測試函數(shù)
  129.         u8 flag_1=5;
  130. void rtp_test(void)
  131. {
  132.         u8 key;
  133.         u8 i=0;         
  134.         u8 z=0;        
  135.         u16 o=rand()%9;
  136.         u8 key_9=0;
  137.         u16 score=0;
  138.         u8 flag=1;
  139.         u8 flag_2=1;
  140.         u8 level=1;
  141. //        for(z=0;z<9;z++)
  142. //        {
  143. //                        gui_fill_circle((z%3)*80+40,(z/3)*100+70,40,BLUE);        
  144. //        }
  145. //        LCD_ShowString(0,0,200,16,16,"SCORE");
  146.         
  147.         while(1)
  148.         {
  149.                  key=KEY_Scan(0);
  150.                 tp_dev.scan(0);
  151.                 key_9=(tp_dev.x[0]+1)/80+3*(tp_dev.y[0]+1-20)/100;
  152.                 if(flag_1==5)
  153.                 {
  154.                         
  155.                         LCD_Clear(WHITE);
  156.                         image_display(0,0,(u8*)gImage_1);
  157.                         LCD_ShowString(0,0,200,16,16,"SCORE");
  158.                         LCD_ShowString(79,0,200,16,16,"LEVEL");
  159.                         LCD_ShowString(159,0,200,16,16,"LIFE");
  160.                         flag_1=0;
  161.                 }
  162.                 if(flag_1<=3)
  163.                 {
  164.                         if(i==0)
  165.                         {
  166.                                 LCD_ShowNum(189,0,4-flag_1,4,16);
  167.                                 LCD_ShowNum(29,0,score,4,16);
  168.                                 LCD_ShowNum(109,0,level,4,16);
  169.                                 
  170.                                 for(z=0;z<9;z++)
  171.                                 {
  172.                                 gui_fill_circle((z%3)*80+40,(z/3)*100+70,25,BRRED);        
  173.                                 }
  174.                                 delay_ms(10);
  175.                                 //LCD_ShowNum(0,0,o,4,16);
  176.                                 //LCD_ShowNum((o%3)*80+36,(o/3)*100+62,o,1,16);
  177.                                 image_display((o%3)*80-17+40,(o/3)*100-17+70,(u8*)gImage_2);
  178.                         }
  179.                         //gui_fill_circle(119,159,40,BLUE);
  180.                 if(tp_dev.sta&TP_PRES_DOWN)                        //觸摸屏被按下
  181.                 {        
  182.                          if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height)
  183.                         {        
  184. //                                if(tp_dev.x[0]>(lcddev.width-24)&&tp_dev.y[0]<16)Load_Drow_Dialog();//清除
  185. //                                else
  186. //                                {
  187. //                                        TP_Draw_Big_Point(tp_dev.x[0],tp_dev.y[0],POINT_COLOR_TBL[i%5]);
  188. //                                       
  189. //                                }                                        //畫圖         
  190.                                 //        key_9=(tp_dev.x[0]+1)/80+3*(tp_dev.y[0]+1-20)/100;
  191.                                 
  192.                                 if((o+1)==key_9&&flag)
  193.                                 {
  194.                                         score++;
  195.                                         flag=0;
  196.                                 }
  197.                                 else if(flag)
  198.                                 {
  199.                                         if(score>0)score--;
  200.                                         flag=0;
  201.                                         flag_1++;
  202.                                 }
  203.                                 
  204.                                         i=(int)(100/(level*0.75)-15);
  205.                                 
  206.                         }
  207.                 }else delay_ms(10);        //沒有按鍵按下的時(shí)候            
  208.                 if(key==KEY0_PRES)        //KEY0按下,則執(zhí)行校準(zhǔn)程序
  209.                 {
  210.                         LCD_Clear(WHITE);//清屏
  211.                     TP_Adjust();  //屏幕校準(zhǔn)
  212.                         TP_Save_Adjdata();         
  213.                         Load_Drow_Dialog();
  214.                 }
  215.                
  216.                 if(score>19){level++;score=0;}
  217.                 i++;
  218.                 if(i>(100/(level*0.75)))
  219.                 {
  220.                         o=rand()%9;
  221.                         LED0=!LED0;
  222.                         flag=1;
  223.                         i=0;
  224.                 }
  225.         }
  226.                 if(flag_1>3)
  227.                 {
  228.                          if(flag_2){tp_dev.x[0]=0;tp_dev.y[0]=0;flag_2=0;
  229.                                 LCD_Clear(WHITE);//清屏
  230.                                  image_display(0,0,(u8*)gImage_1);
  231.                                 if(tp_dev.touchtype!=0XFF)LCD_ShowString(90,130,200,16,16,"GAME OVER");
  232.                         if(tp_dev.touchtype!=0XFF)LCD_ShowString(110,160,200,16,16,"continue");
  233.                          }
  234.                         //LCD_Clear(WHITE);
  235.                                 if(key_9==5)
  236.                                 {
  237.                                                 flag_1=5;
  238.                                                 level=1;
  239.                                                 score=0;
  240.                                                 flag=1;
  241.                                                 flag_2=1;
  242.                                 }
  243.                 }
  244.         }
  245. }

  246. //電容觸摸屏測試函數(shù)
  247. void ctp_test(void)
  248. {
  249.         u8 t=0;
  250.         u8 i=0;                     
  251.          u16 lastpos[5][2];                //最后一次的數(shù)據(jù)
  252.         while(1)
  253.         {
  254.                 tp_dev.scan(0);
  255.                 for(t=0;t<CT_MAX_TOUCH;t++)//最多5點(diǎn)觸摸
  256.                 {
  257.                         if((tp_dev.sta)&(1<<t))//判斷是否有點(diǎn)觸摸?
  258.                         {
  259.                                 if(tp_dev.x[t]<lcddev.width&&tp_dev.y[t]<lcddev.height)//在LCD范圍內(nèi)
  260.                                 {
  261.                                         if(lastpos[t][0]==0XFFFF)
  262.                                         {
  263.                                                 lastpos[t][0] = tp_dev.x[t];
  264.                                                 lastpos[t][1] = tp_dev.y[t];
  265.                                         }
  266.                                         lcd_draw_bline(lastpos[t][0],lastpos[t][1],tp_dev.x[t],tp_dev.y[t],2,POINT_COLOR_TBL[t]);//畫線
  267.                                         lastpos[t][0]=tp_dev.x[t];
  268.                                         lastpos[t][1]=tp_dev.y[t];
  269.                                         if(tp_dev.x[t]>(lcddev.width-24)&&tp_dev.y[t]<16)
  270.                                         {
  271.                                                 Load_Drow_Dialog();//清除
  272.                                         }
  273.                                 }
  274.                         }else lastpos[t][0]=0XFFFF;
  275.                 }
  276.                
  277.                 delay_ms(5);i++;
  278.                 if(i%20==0)LED0=!LED0;
  279.         }        
  280. }
  281. int main(void)
  282. {
  283.          delay_init();                     //延時(shí)函數(shù)初始化         
  284.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級
  285.         uart_init(9600);                 //串口初始化為9600
  286.         LED_Init();                                  //初始化與LED連接的硬件接口
  287.         LCD_Init();                                   //初始化LCD         
  288.         KEY_Init();                                //按鍵初始化                        
  289.         tp_dev.init();                        //觸摸屏初始化
  290.         POINT_COLOR=RED;//設(shè)置字體為紅色
  291.          
  292.         Load_Drow_Dialog();                 
  293.                 if(tp_dev.touchtype&0X80)ctp_test();        //電容屏測試
  294.                 else rtp_test();          //電阻屏測試
  295.                  
  296. }
復(fù)制代碼

所有資料51hei提供下載(源碼+文檔):
打地鼠V1.0.7z (414.54 KB, 下載次數(shù): 136)
說明文檔.docx (15.47 KB, 下載次數(shù): 100)


評分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:452469 發(fā)表于 2018-12-23 10:07 | 只看該作者
請問在這個(gè)程序中,是怎樣把打地鼠圖片的加入到程序中的,兩者之間是如何建立起關(guān)聯(lián)的啊
回復(fù)

使用道具 舉報(bào)

板凳
ID:361500 發(fā)表于 2018-12-26 15:15 | 只看該作者
嵌入式系統(tǒng) 發(fā)表于 2018-12-23 10:07
請問在這個(gè)程序中,是怎樣把打地鼠圖片的加入到程序中的,兩者之間是如何建立起關(guān)聯(lián)的啊

地鼠和背景圖片都是用的取模軟件,在工程里面有這個(gè)函數(shù)
回復(fù)

使用道具 舉報(bào)

地板
ID:457316 發(fā)表于 2018-12-28 15:00 | 只看該作者
STM32戰(zhàn)艦V3可以用嗎
回復(fù)

使用道具 舉報(bào)

5#
ID:202445 發(fā)表于 2019-9-29 10:03 | 只看該作者
試一下看行不行
回復(fù)

使用道具 舉報(bào)

6#
ID:436894 發(fā)表于 2019-12-11 10:13 來自手機(jī) | 只看該作者
為什么打不開
回復(fù)

使用道具 舉報(bào)

7#
ID:736884 發(fā)表于 2020-4-26 13:46 | 只看該作者
樓主這個(gè)key_9=(tp_dev.x[0]+1)/80+3*(tp_dev.y[0]+1-20)/100;是如何計(jì)算的?
回復(fù)

使用道具 舉報(bào)

8#
ID:736884 發(fā)表于 2020-4-26 13:48 | 只看該作者
樓主這個(gè)觸摸點(diǎn) key_9=(tp_dev.x[0]+1)/80+3*(tp_dev.y[0]+1-20)/100;是如何計(jì)算的?
回復(fù)

使用道具 舉報(bào)

9#
ID:999593 發(fā)表于 2022-1-4 10:21 | 只看該作者
顯示無法打開pdsc文件是什么原因
回復(fù)

使用道具 舉報(bào)

10#
ID:262 發(fā)表于 2022-1-4 18:27 | 只看該作者
759699071 發(fā)表于 2022-1-4 10:21
顯示無法打開pdsc文件是什么原因

用Keil5來編譯  你看我編譯的

51hei.png (59.64 KB, 下載次數(shù): 32)

51hei.png
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表