定制网站基于STM32的小游戏——谷歌小恐龙(Chrome Dino Game)

        前言:定制网站使用的显示屏其实可以定制网站开发出许多定制网站有趣的小项目,比如:定制网站多功能菜单小游戏等等。其中,STM32F1XX定制网站由于芯片的性能一般定制网站计算量与内存),定制网站所以能够实现的小游戏不多,定制网站较为常见的:贪吃蛇,定制网站俄罗斯方块,定制网站飞机大战等。定制网站本文将给大家实现一款定制网站较为新颖的小游戏——定制网站谷歌小恐龙(Chrome Dino Game)。简单使用0.96寸OLED屏幕搭配STM32F1系列的MCU定制网站就可以实现,定制网站硬件要求很低。(定制网站本游戏代码基于HAL库实现,定制网站文末有代码开源

        实验硬件:STM32F103ZET6;0.96寸OLED;2个KEY按键

        定制网站硬件实物图:

        效果图:

引脚连接:

OLED模块:

VCC --> 3.3V

GND --> GND

SCL --> PB10

SDA --> PB11

KEY按键模块:

KEY0 --> PE3

KEY1 --> PE4

注意:定制网站这里按键直接采用了正定制网站点原子精英板上的固有按键,定制网站自己打板的话,定制网站视情况下而定。

一、谷歌小恐龙(Chrome Dino Game)简介

        谷歌小恐龙(Chrome Dino Game)顾名思义是由Google公司首创出来的小游戏。其初始目的为在Google浏览器出现互联网信号丢失时,排解用户等待联网信号时的无聊难受。

        这个游戏的最大优点是它可以在没有互联网的情况下玩。这是Chrome浏览器中一款原始的无止境跑步游戏。主角是一只可爱的霸王龙,它在古老的沙漠中小跑。当然,恐龙游戏有它的目的:避免仙人掌翼手龙。虽然游戏看起来很简单,但并不需要很长时间就能变得很难,因为游戏的速度会随着你的进步而不断提高。

        本文就以谷歌小恐龙(Chrome Dino Game)游戏为原型,使用STM32于0.96寸OLED屏幕上尽可能地复现了谷歌小恐龙游戏。

谷歌小恐龙(Chrome Dino Game)实机效果:

 原游戏网址:

二、OLED简介

        关于OLED的使用与原理不熟悉的笔者欢迎去笔者另一篇文章学习,由于篇幅问题,这里就不过多讲诉。

三、KEY按键

        开发板上除了有经典的流水灯之外,还有一个必备的练习硬件--按键(key)

        正常地独立按键KEY其实使用很简单,就是基于GPIO引脚的读取操作唯一需要注意的点:按键按下去之后到底时低电平还是高电平

        笔者这里直接使用了正点原子精英版STM32上的按键KEY,按键原理图如下:

        考虑到本次小游戏只使用2个按键KEY,这里取KEY0KEY1KEY0KEY1按下后为低电平有效。(这里读者朋友可以根据实际情况去设置

四、CubeMX配置

1、RCC配置外部高速晶振(精度更高)——HSE;

2、SYS配置:Debug设置成Serial Wire否则可能导致芯片自锁);

 3、I2C2配置:这里不直接使用CubeMX的I2C2,使用GPIO模拟(PB10:CLK;PB11:SDA)

4、KEY按键配置:PE3与PE4设置为端口输入(开发板原理图)

5、时钟树配置:

6、工程配置 

五、代码讲解

5.1 OLED驱动代码

        此部分OLED的基本驱动函数,笔者使用的是I2C驱动的0.96寸OLED屏幕。所以,首先需要使用GPIO模拟I2C通讯。随后,使用I2C通讯去驱动OLED。(此部分代码包含了屏幕驱动基础显示,如果对OLED显示不太理解的朋友可以去看看上文提到的笔者的另一篇文章

oled.h:

  1. #ifndef __OLED_H
  2. #define __OLED_H
  3. #include "main.h"
  4. #define u8 uint8_t
  5. #define u32 uint32_t
  6. #define OLED_CMD 0 //写命令
  7. #define OLED_DATA 1 //写数据
  8. #define OLED0561_ADD 0x78 // OLED I2C地址
  9. #define COM 0x00 // OLED
  10. #define DAT 0x40 // OLED
  11. #define OLED_MODE 0
  12. #define SIZE 8
  13. #define XLevelL 0x00
  14. #define XLevelH 0x10
  15. #define Max_Column 128
  16. #define Max_Row 64
  17. #define Brightness 0xFF
  18. #define X_WIDTH 128
  19. #define Y_WIDTH 64
  20. //-----------------OLED IIC GPIO进行模拟----------------
  21. #define OLED_SCLK_Clr() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET) //GPIO_ResetBits(GPIOB,GPIO_Pin_10)//SCL
  22. #define OLED_SCLK_Set() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET) //GPIO_SetBits(GPIOB,GPIO_Pin_10)
  23. #define OLED_SDIN_Clr() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET) // GPIO_ResetBits(GPIOB,GPIO_Pin_11)//SDA
  24. #define OLED_SDIN_Set() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET) // GPIO_SetBits(GPIOB,GPIO_Pin_11)
  25. //I2C GPIO模拟
  26. void IIC_Start();
  27. void IIC_Stop();
  28. void IIC_WaitAck();
  29. void IIC_WriteByte(unsigned char IIC_Byte);
  30. void IIC_WriteCommand(unsigned char IIC_Command);
  31. void IIC_WriteData(unsigned char IIC_Data);
  32. void OLED_WR_Byte(unsigned dat,unsigned cmd);
  33. //功能函数
  34. void OLED_Init(void);
  35. void OLED_WR_Byte(unsigned dat,unsigned cmd);
  36. void OLED_FillPicture(unsigned char fill_Data);
  37. void OLED_SetPos(unsigned char x, unsigned char y);
  38. void OLED_DisplayOn(void);
  39. void OLED_DisplayOff(void);
  40. void OLED_Clear(void);
  41. void OLED_On(void);
  42. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size);
  43. u32 oled_pow(u8 m,u8 n);
  44. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2);
  45. void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size);
  46. #endif

oled.c:

  1. #include "oled.h"
  2. #include "asc.h" //字库(可以自己制作)
  3. #include "main.h"
  4. /********************GPIO 模拟I2C*******************/
  5. //注意:这里没有直接使用HAL库中的模拟I2C
  6. /**********************************************
  7. //IIC Start
  8. **********************************************/
  9. void IIC_Start()
  10. {
  11. OLED_SCLK_Set() ;
  12. OLED_SDIN_Set();
  13. OLED_SDIN_Clr();
  14. OLED_SCLK_Clr();
  15. }
  16. /**********************************************
  17. //IIC Stop
  18. **********************************************/
  19. void IIC_Stop()
  20. {
  21. OLED_SCLK_Set() ;
  22. OLED_SDIN_Clr();
  23. OLED_SDIN_Set();
  24. }
  25. void IIC_WaitAck()
  26. {
  27. OLED_SCLK_Set() ;
  28. OLED_SCLK_Clr();
  29. }
  30. /**********************************************
  31. // IIC Write byte
  32. **********************************************/
  33. void IIC_WriteByte(unsigned char IIC_Byte)
  34. {
  35. unsigned char i;
  36. unsigned char m,da;
  37. da=IIC_Byte;
  38. OLED_SCLK_Clr();
  39. for(i=0;i<8;i++)
  40. {
  41. m=da;
  42. // OLED_SCLK_Clr();
  43. m=m&0x80;
  44. if(m==0x80)
  45. {OLED_SDIN_Set();}
  46. else OLED_SDIN_Clr();
  47. da=da<<1;
  48. OLED_SCLK_Set();
  49. OLED_SCLK_Clr();
  50. }
  51. }
  52. /**********************************************
  53. // IIC Write Command
  54. **********************************************/
  55. void IIC_WriteCommand(unsigned char IIC_Command)
  56. {
  57. IIC_Start();
  58. IIC_WriteByte(0x78); //Slave address,SA0=0
  59. IIC_WaitAck();
  60. IIC_WriteByte(0x00); //write command
  61. IIC_WaitAck();
  62. IIC_WriteByte(IIC_Command);
  63. IIC_WaitAck();
  64. IIC_Stop();
  65. }
  66. /**********************************************
  67. // IIC Write Data
  68. **********************************************/
  69. void IIC_WriteData(unsigned char IIC_Data)
  70. {
  71. IIC_Start();
  72. IIC_WriteByte(0x78); //D/C#=0; R/W#=0
  73. IIC_WaitAck();
  74. IIC_WriteByte(0x40); //write data
  75. IIC_WaitAck();
  76. IIC_WriteByte(IIC_Data);
  77. IIC_WaitAck();
  78. IIC_Stop();
  79. }
  80. void OLED_WR_Byte(unsigned dat,unsigned cmd)
  81. {
  82. if(cmd)
  83. {
  84. IIC_WriteData(dat);
  85. }
  86. else
  87. {
  88. IIC_WriteCommand(dat);
  89. }
  90. }
  91. void OLED_Init(void)
  92. {
  93. HAL_Delay(100); //这个延迟很重要
  94. OLED_WR_Byte(0xAE,OLED_CMD);//--display off
  95. OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
  96. OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
  97. OLED_WR_Byte(0x40,OLED_CMD);//--set start line address
  98. OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
  99. OLED_WR_Byte(0x81,OLED_CMD); // contract control
  100. OLED_WR_Byte(0xFF,OLED_CMD);//--128
  101. OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
  102. OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
  103. OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
  104. OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
  105. OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
  106. OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
  107. OLED_WR_Byte(0x00,OLED_CMD);//
  108. OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
  109. OLED_WR_Byte(0x80,OLED_CMD);//
  110. OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
  111. OLED_WR_Byte(0x05,OLED_CMD);//
  112. OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
  113. OLED_WR_Byte(0xF1,OLED_CMD);//
  114. OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
  115. OLED_WR_Byte(0x12,OLED_CMD);//
  116. OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
  117. OLED_WR_Byte(0x30,OLED_CMD);//
  118. OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
  119. OLED_WR_Byte(0x14,OLED_CMD);//
  120. OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
  121. HAL_Delay(100);
  122. OLED_FillPicture(0x0);
  123. }
  124. /********************************************
  125. // OLED_FillPicture
  126. ********************************************/
  127. void OLED_FillPicture(unsigned char fill_Data)
  128. {
  129. unsigned char m,n;
  130. for(m=0;m<8;m++)
  131. {
  132. OLED_WR_Byte(0xb0+m,0); //page0-page1
  133. OLED_WR_Byte(0x00,0); //low column start address
  134. OLED_WR_Byte(0x10,0); //high column start address
  135. for(n=0;n<128;n++)
  136. {
  137. OLED_WR_Byte(fill_Data,1);
  138. }
  139. }
  140. }
  141. //坐标设置
  142. void OLED_SetPos(unsigned char x, unsigned char y)
  143. { OLED_WR_Byte(0xb0+y,OLED_CMD);
  144. OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
  145. OLED_WR_Byte((x&0x0f),OLED_CMD);
  146. }
  147. //开启OLED显示
  148. void OLED_DisplayOn(void)
  149. {
  150. OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
  151. OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
  152. OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
  153. }
  154. //关闭OLED显示
  155. void OLED_DisplayOff(void)
  156. {
  157. OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
  158. OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
  159. OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
  160. }
  161. //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
  162. void OLED_Clear(void)
  163. {
  164. u8 i,n;
  165. for(i=0;i<8;i++)
  166. {
  167. OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
  168. OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
  169. OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
  170. for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
  171. } //更新显示
  172. }
  173. void OLED_On(void)
  174. {
  175. u8 i,n;
  176. for(i=0;i<8;i++)
  177. {
  178. OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
  179. OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
  180. OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
  181. for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA);
  182. } //更新显示
  183. }
  184. //在指定位置显示一个字符,包括部分字符
  185. //x:0~127
  186. //y:0~63
  187. //mode:0,反白显示;1,正常显示
  188. //size:选择字体 16/12
  189. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
  190. {
  191. unsigned char c=0,i=0;
  192. c=chr-' ';//得到偏移后的值
  193. if(x>Max_Column-1){x=0;y=y+2;}
  194. if(Char_Size ==16)
  195. {
  196. OLED_SetPos(x,y);
  197. for(i=0;i<8;i++)
  198. OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
  199. OLED_SetPos(x,y+1);
  200. for(i=0;i<8;i++)
  201. OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
  202. }
  203. else {
  204. OLED_SetPos(x,y);
  205. for(i=0;i<6;i++)
  206. OLED_WR_Byte(F6x8[c][i],OLED_DATA);
  207. }
  208. }
  209. //m^n函数
  210. u32 oled_pow(u8 m,u8 n)
  211. {
  212. u32 result=1;
  213. while(n--)result*=m;
  214. return result;
  215. }
  216. //显示2个数字
  217. //x,y :起点坐标
  218. //len :数字的位数
  219. //size:字体大小
  220. //mode:模式 0,填充模式;1,叠加模式
  221. //num:数值(0~4294967295);
  222. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
  223. {
  224. u8 t,temp;
  225. u8 enshow=0;
  226. for(t=0;t<len;t++)
  227. {
  228. temp=(num/oled_pow(10,len-t-1))%10;
  229. if(enshow==0&&t<(len-1))
  230. {
  231. if(temp==0)
  232. {
  233. // OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
  234. OLED_ShowChar(x+(size2/2)*t,y,'0',size2);
  235. continue;
  236. }else enshow=1;
  237. }
  238. OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
  239. }
  240. }
  241. //显示一个字符号串
  242. void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
  243. {
  244. unsigned char j=0;
  245. while (chr[j]!='\0')
  246. { OLED_ShowChar(x,y,chr[j],Char_Size);
  247. x+=8;
  248. if(x>120){x=0;y+=2;}
  249. j++;
  250. }
  251. }

5.2 谷歌小恐龙游戏图形绘制代码

        该部分为整个项目代码的核心部分之一,任何一个游戏都是需要去绘制构建游戏的图形以及模型的。好的游戏往往都具有很好的游戏模型精美UI,很多3A大作都具备这样的特性。

dinogame.h:

  1. #ifndef __DINOGAME_H
  2. #define __DINOGAME_H
  3. void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]);
  4. void OLED_DrawBMPFast(const unsigned char BMP[]);
  5. void oled_drawbmp_block_clear(int bx, int by, int clear_size);
  6. void OLED_DrawGround();
  7. void OLED_DrawCloud();
  8. void OLED_DrawDino();
  9. void OLED_DrawCactus();
  10. int OLED_DrawCactusRandom(unsigned char ver, unsigned char reset);
  11. int OLED_DrawDinoJump(char reset);
  12. void OLED_DrawRestart();
  13. void OLED_DrawCover();
  14. #endif

dinogame.c代码:

  1. #include "oled.h"
  2. #include "oledfont.h"
  3. #include "stdlib.h"
  4. /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
  5. void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
  6. {
  7. unsigned int j=0;
  8. unsigned char x,y;
  9. if(y1%8==0) y=y1/8;
  10. else y=y1/8+1;
  11. for(y=y0;y<y1;y++)
  12. {
  13. OLED_SetPos(x0,y);
  14. for(x=x0;x<x1;x++)
  15. {
  16. OLED_WR_Byte(BMP[j++],OLED_DATA);
  17. }
  18. }
  19. }
  20. // 快速绘制图像
  21. void OLED_DrawBMPFast(const unsigned char BMP[])
  22. {
  23. unsigned int j = 0;
  24. unsigned char x, y;
  25. for (y = 0; y < 8; y++)
  26. {
  27. OLED_SetPos(0, y);
  28. IIC_Start();
  29. IIC_WriteByte(0x78);
  30. IIC_WaitAck();
  31. IIC_WriteByte(0x40);
  32. IIC_WaitAck();
  33. for (x = 0; x < 128; x++)
  34. {
  35. IIC_WriteByte(BMP[j++]);
  36. IIC_WaitAck();
  37. }
  38. IIC_Stop();
  39. }
  40. }
  41. void oled_drawbmp_block_clear(int bx, int by, int clear_size)
  42. {
  43. unsigned int i;
  44. OLED_SetPos(bx, by);
  45. IIC_Start();
  46. IIC_WriteByte(0x78);
  47. IIC_WaitAck();
  48. IIC_WriteByte(0x40);
  49. IIC_WaitAck();
  50. for (i = 0; i < clear_size; i++)
  51. {
  52. if (bx + i>128) break;
  53. IIC_WriteByte(0x0);
  54. IIC_WaitAck();
  55. }
  56. IIC_Stop();
  57. }
  58. void OLED_DrawGround()
  59. {
  60. static unsigned int pos = 0;
  61. unsigned char speed = 5;
  62. unsigned int ground_length = sizeof(GROUND);
  63. unsigned char x;
  64. OLED_SetPos(0, 7);
  65. IIC_Start();
  66. IIC_WriteByte(0x78);
  67. IIC_WaitAck();
  68. IIC_WriteByte(0x40);
  69. IIC_WaitAck();
  70. for (x = 0; x < 128; x++)
  71. {
  72. IIC_WriteByte(GROUND[(x+pos)%ground_length]);
  73. IIC_WaitAck();
  74. }
  75. IIC_Stop();
  76. pos = pos + speed;
  77. //if(pos>ground_length) pos=0;
  78. }
  79. // 绘制云朵
  80. void OLED_DrawCloud()
  81. {
  82. static int pos = 128;
  83. static char height=0;
  84. char speed = 3;
  85. unsigned int i=0;
  86. int x;
  87. int start_x = 0;
  88. int length = sizeof(CLOUD);
  89. unsigned char byte;
  90. //if (pos + length <= -speed) pos = 128;
  91. if (pos + length <= -speed)
  92. {
  93. pos = 128;
  94. height = rand()%3;
  95. }
  96. if(pos < 0)
  97. {
  98. start_x = -pos;
  99. OLED_SetPos(0, 1+height);
  100. }
  101. else
  102. {
  103. OLED_SetPos(pos, 1+height);
  104. }
  105. IIC_Start();
  106. IIC_WriteByte(0x78);
  107. IIC_WaitAck();
  108. IIC_WriteByte(0x40);
  109. IIC_WaitAck();
  110. for (x = start_x; x < length + speed; x++)
  111. {
  112. if (pos + x > 127) break;
  113. if (x < length) byte = CLOUD[x];
  114. else byte = 0x0;
  115. IIC_WriteByte(byte);
  116. IIC_WaitAck();
  117. }
  118. IIC_Stop();
  119. pos = pos - speed;
  120. }
  121. // 绘制小恐龙
  122. void OLED_DrawDino()
  123. {
  124. static unsigned char dino_dir = 0;
  125. unsigned int j=0;
  126. unsigned char x, y;
  127. unsigned char byte;
  128. dino_dir++;
  129. dino_dir = dino_dir%2;
  130. for(y=0; y<2; y++)
  131. {
  132. OLED_SetPos(16, 6+y);
  133. IIC_Start();
  134. IIC_WriteByte(0x78);
  135. IIC_WaitAck();
  136. IIC_WriteByte(0x40);
  137. IIC_WaitAck();
  138. for (x = 0; x < 16; x++)
  139. {
  140. j = y*16 + x;
  141. byte = DINO[dino_dir][j];
  142. IIC_WriteByte(byte);
  143. IIC_WaitAck();
  144. }
  145. IIC_Stop();
  146. }
  147. }
  148. // 绘制仙人掌障碍物
  149. void OLED_DrawCactus()
  150. {
  151. char speed = 5;
  152. static int pos = 128;
  153. int start_x = 0;
  154. int length = sizeof(CACTUS_2)/2;
  155. unsigned int j=0;
  156. unsigned char x, y;
  157. unsigned char byte;
  158. if (pos + length <= 0)
  159. {
  160. oled_drawbmp_block_clear(0, 6, speed);
  161. pos = 128;
  162. }
  163. for(y=0; y<2; y++)
  164. {
  165. if(pos < 0)
  166. {
  167. start_x = -pos;
  168. OLED_SetPos(0, 6+y);
  169. }
  170. else
  171. {
  172. OLED_SetPos(pos, 6+y);
  173. }
  174. IIC_Start();
  175. IIC_WriteByte(0x78);
  176. IIC_WaitAck();
  177. IIC_WriteByte(0x40);
  178. IIC_WaitAck();
  179. for (x = start_x; x < length; x++)
  180. {
  181. if (pos + x > 127) break;
  182. j = y*length + x;
  183. byte = CACTUS_2[j];
  184. IIC_WriteByte(byte);
  185. IIC_WaitAck();
  186. }
  187. IIC_Stop();
  188. }
  189. oled_drawbmp_block_clear(pos + length, 6, speed); // 清除残影
  190. pos = pos - speed;
  191. }
  192. // 绘制随机出现的仙人掌障碍物
  193. int OLED_DrawCactusRandom(unsigned char ver, unsigned char reset)
  194. {
  195. char speed = 5;
  196. static int pos = 128;
  197. int start_x = 0;
  198. int length = 0;
  199. unsigned int i=0, j=0;
  200. unsigned char x, y;
  201. unsigned char byte;
  202. if (reset == 1)
  203. {
  204. pos = 128;
  205. oled_drawbmp_block_clear(0, 6, speed);
  206. return 128;
  207. }
  208. if (ver == 0) length = 8; //sizeof(CACTUS_1) / 2;
  209. else if (ver == 1) length = 16; //sizeof(CACTUS_2) / 2;
  210. else if (ver == 2 || ver == 3) length = 24;
  211. for(y=0; y<2; y++)
  212. {
  213. if(pos < 0)
  214. {
  215. start_x = -pos;
  216. OLED_SetPos(0, 6+y);
  217. }
  218. else
  219. {
  220. OLED_SetPos(pos, 6+y);
  221. }
  222. IIC_Start();
  223. IIC_WriteByte(0x78);
  224. IIC_WaitAck();
  225. IIC_WriteByte(0x40);
  226. IIC_WaitAck();
  227. for (x = start_x; x < length; x++)
  228. {
  229. if (pos + x > 127) break;
  230. j = y*length + x;
  231. if (ver == 0) byte = CACTUS_1[j];
  232. else if (ver == 1) byte = CACTUS_2[j];
  233. else if(ver == 2) byte = CACTUS_3[j];
  234. else byte = CACTUS_4[j];
  235. IIC_WriteByte(byte);
  236. IIC_WaitAck();
  237. }
  238. IIC_Stop();
  239. }
  240. oled_drawbmp_block_clear(pos + length, 6, speed);
  241. pos = pos - speed;
  242. return pos + speed;
  243. }
  244. // 绘制跳跃小恐龙
  245. int OLED_DrawDinoJump(char reset)
  246. {
  247. char speed_arr[] = {1, 1, 3, 3, 4, 4, 5, 6, 7};
  248. static char speed_idx = sizeof(speed_arr)-1;
  249. static int height = 0;
  250. static char dir = 0;
  251. //char speed = 4;
  252. unsigned int j=0;
  253. unsigned char x, y;
  254. char offset = 0;
  255. unsigned char byte;
  256. if(reset == 1)
  257. {
  258. height = 0;
  259. dir = 0;
  260. speed_idx = sizeof(speed_arr)-1;
  261. return 0;
  262. }
  263. if (dir==0)
  264. {
  265. height += speed_arr[speed_idx];
  266. speed_idx --;
  267. if (speed_idx<0) speed_idx = 0;
  268. }
  269. if (dir==1)
  270. {
  271. height -= speed_arr[speed_idx];
  272. speed_idx ++;
  273. if (speed_idx>sizeof(speed_arr)-1) speed_idx = sizeof(speed_arr)-1;
  274. }
  275. if(height >= 31)
  276. {
  277. dir = 1;
  278. height = 31;
  279. }
  280. if(height <= 0)
  281. {
  282. dir = 0;
  283. height = 0;
  284. }
  285. if(height <= 7) offset = 0;
  286. else if(height <= 15) offset = 1;
  287. else if(height <= 23) offset = 2;
  288. else if(height <= 31) offset = 3;
  289. else offset = 4;
  290. for(y=0; y<3; y++) // 4
  291. {
  292. OLED_SetPos(16, 5- offset + y);
  293. IIC_Start();
  294. IIC_WriteByte(0x78);
  295. IIC_WaitAck();
  296. IIC_WriteByte(0x40);
  297. IIC_WaitAck();
  298. for (x = 0; x < 16; x++) // 32
  299. {
  300. j = y*16 + x; // 32
  301. byte = DINO_JUMP[height%8][j];
  302. IIC_WriteByte(byte);
  303. IIC_WaitAck();
  304. }
  305. IIC_Stop();
  306. }
  307. if (dir == 0) oled_drawbmp_block_clear(16, 8- offset, 16);
  308. if (dir == 1) oled_drawbmp_block_clear(16, 4- offset, 16);
  309. return height;
  310. }
  311. // 绘制重启
  312. void OLED_DrawRestart()
  313. {
  314. unsigned int j=0;
  315. unsigned char x, y;
  316. unsigned char byte;
  317. //OLED_SetPos(0, 0);
  318. for (y = 2; y < 5; y++)
  319. {
  320. OLED_SetPos(52, y);
  321. IIC_Start();
  322. IIC_WriteByte(0x78);
  323. IIC_WaitAck();
  324. IIC_WriteByte(0x40);
  325. IIC_WaitAck();
  326. for (x = 0; x < 24; x++)
  327. {
  328. byte = RESTART[j++];
  329. IIC_WriteByte(byte);
  330. IIC_WaitAck();
  331. }
  332. IIC_Stop();
  333. }
  334. OLED_ShowString(10, 3, "GAME", 16);
  335. OLED_ShowString(86, 3, "OVER", 16);
  336. }
  337. // 绘制封面
  338. void OLED_DrawCover()
  339. {
  340. OLED_DrawBMPFast(COVER);
  341. }

        此部分函数主要是实现快速绘制出游戏所需要的模型组件模型包括:游戏初始化封面,游戏结束封面,小恐龙(跳跃的小恐龙),沙漠地面,随机出现的仙人掌障碍物(1,2,3个),云朵等。

注意:此部分绘制的属于动态化图片绘制,所绘制的图片会自右向左移动。

        关于游戏模型基础组件,采用Img2Lcd2.9软件对图片进行取模,注意考虑到0.96寸的OLED屏幕大小有限,取模图片尽可能小一点。

例子:

        取模小恐龙模组:

         Img2Lcd2.9软件如下操作取模:

        其余,游戏图片模组依此法进行取模,注意图片取得的大小。

游戏图片取模库oledfont.h:

  1. #ifndef __OLEDFONT_H
  2. #define __OLEDFONT_H
  3. //该文件主要为DinoGame的图像库
  4. /************************************6*8???************************************/
  5. const unsigned char GROUND[] =
  6. {
  7. 0xc8, 0xc8, 0xc8, 0x28, 0x28, 0x28, 0x8, 0xc8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x8, 0x8, 0xc8, 0xc8, 0xc8, 0x8, 0x38, 0x38, 0x8,
  8. 0x8, 0x8, 0x8, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x8, 0x48, 0x48, 0x48, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xc8, 0x8,
  9. 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x38, 0x38, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x8, 0x28, 0x28, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x8, 0x8, 0x8, 0x8, 0x38, 0x38, 0x8, 0x68, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x8, 0x8, 0x8, 0x8,
  10. 0x8, 0x8, 0x8, 0x48, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x68, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xc8, 0xc8, 0x8, 0x9, 0x8, 0x8, 0x8, 0x8, 0x8, 0x38, 0x38, 0x8, 0x8, 0x28, 0x8, 0x9, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x8, 0x8, 0x9, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x68, 0x68, 0x8, 0xc9, 0xc8, 0xc8, 0x8, 0x8, 0x8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x29, 0x8, 0x8, 0x8, 0x8,
  11. 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x49, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x68, 0x68, 0x8, 0x8, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x68, 0x68, 0x8, 0x8, 0xc8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x28, 0x8, 0x8, 0x48, 0x8, 0x38,
  12. 0x38, 0x8, 0x8, 0x8, 0x8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xc8, 0xc8, 0xc8, 0x28, 0x28, 0x28, 0x8, 0xc8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x48, 0x8, 0x8, 0xc8, 0xc8, 0xc8, 0x8, 0x38, 0x38, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x48, 0x48, 0x48, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0xc8, 0x8, 0x8, 0x8, 0xc, 0x6, 0x2, 0x42, 0x42, 0x6, 0xc, 0x8, 0x8, 0x8, 0x8, 0x38, 0x38, 0x8, 0x18, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x18, 0x8, 0x48, 0x8, 0x28, 0x28, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0x38, 0x38, 0x68, 0x68, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x48, 0x48, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x68, 0x68, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0xc8, 0xc8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x38, 0x38, 0x8, 0x8, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x68, 0x68, 0x8, 0xc8, 0xc8, 0xc8, 0x8, 0x8, 0x8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0xc, 0x4, 0x6, 0x2, 0x2, 0x6, 0xc, 0x4c, 0x48, 0x8, 0x8, 0x8, 0xc, 0x4, 0x6, 0x2, 0x2, 0x6, 0xc, 0xc, 0x68, 0x68, 0x8, 0x28, 0x28, 0x28, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x68, 0x68, 0x68, 0x8, 0x8, 0xc8, 0xc8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x28, 0x28, 0x28, 0x28, 0x8, 0x8, 0x8,
  13. 0x8, 0x8, 0x28, 0x28, 0x28, 0x8, 0x8, 0x48, 0x28, 0x38, 0x38, 0x8, 0x8, 0x8, 0x8, 0xc8, 0x8, 0x8,
  14. };
  15. const unsigned char CLOUD[] =
  16. {
  17. 0x80, 0xc0, 0xe0, 0x70, 0xb0, 0xb0, 0xb0, 0x98, 0x88, 0x8e, 0x83, 0x83, 0x83, 0x81, 0x81, 0x93, 0x8e, 0x8c, 0x88, 0x88, 0x98, 0xb0, 0xf0, 0xc0
  18. };
  19. const unsigned char DINO[2][32] =
  20. {
  21. 0xe0, 0x80, 0x0, 0x0, 0x0, 0x80, 0xc0, 0xe0, 0xfe, 0xff, 0xfd, 0xbf, 0xaf, 0x2f, 0x2f, 0xe, 0x3, 0x7, 0xf, 0x1e, 0xff, 0xbf, 0x1f, 0x1f, 0x3f, 0x2f, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0,
  22. 0xe0, 0x80, 0x0, 0x0, 0x0, 0x80, 0xc0, 0xe0, 0xfe, 0xff, 0xfd, 0xbf, 0xaf, 0x2f, 0x2f, 0xe, 0x3, 0x7, 0xf, 0x1e, 0x3f, 0x7f, 0x5f, 0x3f, 0xff, 0x8f, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0
  23. };
  24. const unsigned char DINO_JUMP[8][48] = //
  25. {
  26. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x80, 0x0, 0x0, 0x0, 0x80, 0xc0, 0xc0, 0xfe, 0xff, 0xfd, 0xbf, 0xaf, 0x2f, 0x2f, 0xe, 0x3, 0x7, 0xf, 0x1f, 0xff, 0xbf, 0x1f, 0x3f, 0xff, 0x8f, 0x7, 0x0, 0x1, 0x0, 0x0, 0x0,
  27. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0, 0xf0, 0xc0, 0x80, 0x80, 0x80, 0xc0, 0xe0, 0xe0, 0xff, 0xff, 0xfe, 0x5f, 0xd7, 0x17, 0x17, 0x7, 0x1, 0x3, 0x7, 0xf, 0x7f, 0x5f, 0xf, 0x1f, 0x7f, 0x47, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0,
  28. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xc0, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0xf8, 0xe0, 0xc0, 0xc0, 0xc0, 0xe0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0x2f, 0x6b, 0xb, 0xb, 0x3, 0x0, 0x1, 0x3, 0x7, 0x3f, 0x2f, 0x7, 0xf, 0x3f, 0x23, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
  29. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xe0, 0xa0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0x7c, 0xf0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8, 0xff, 0xff, 0xff, 0x17, 0x35, 0x5, 0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0x1f, 0x17, 0x3, 0x7, 0x1f, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  30. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xf0, 0xd0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0x3e, 0x78, 0xf0, 0xf0, 0xf0, 0xf8, 0xfc, 0xfc, 0xff, 0xff, 0x7f, 0xb, 0x1a, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf, 0xb, 0x1, 0x3, 0xf, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  31. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xf8, 0xe8, 0xf8, 0x78, 0x78, 0x78, 0x70, 0x1f, 0x3c, 0x78, 0xf8, 0xf8, 0xfc, 0xfe, 0xfe, 0xff, 0x7f, 0x3f, 0x5, 0xd, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
  32. 0x5, 0x0, 0x1, 0x7, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  33. 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf8, 0xfc, 0xf4, 0xfc, 0xbc, 0xbc, 0xbc, 0x38, 0xf, 0x1e, 0x3c, 0x7c, 0xfc, 0xfe, 0x7f, 0xff, 0xff, 0x3f, 0x1f, 0x2, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
  34. 0x2, 0x0, 0x0, 0x3, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  35. 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0xfc, 0xfe, 0xfa, 0x7e, 0x5e, 0x5e, 0x5e, 0x1c, 0x7, 0xf, 0x1e, 0x3e, 0xfe, 0x7f, 0x3f, 0x7f, 0xff, 0x1f, 0xf, 0x1, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
  36. 0x1, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  37. };
  38. const unsigned char CACTUS_1[] = {
  39. 0xf0, 0xf0, 0x0, 0xff, 0xff, 0x0, 0xf0, 0xf0, 0x3, 0x7, 0x86, 0xff, 0xff, 0x6, 0x3, 0x1
  40. };
  41. const unsigned char CACTUS_2[] = {
  42. 0xf0, 0xe0, 0x0, 0xff, 0xfe, 0x80, 0xfc, 0x0, 0x0, 0x7c, 0xc0, 0xfe, 0xff, 0x0, 0x80, 0xfc,
  43. 0x3, 0x7, 0x6, 0xff, 0xff, 0x1, 0x10, 0x90, 0x90, 0x90, 0x0, 0xff, 0xff, 0x3, 0x3, 0x1
  44. };
  45. const unsigned char CACTUS_3[] = {
  46. 0xf0, 0xe0, 0x0, 0xff, 0xfe, 0x80, 0xfc, 0x0, 0xfc, 0xfe, 0x0, 0xff, 0xff, 0x0, 0xf8, 0xf0,
  47. 0x0, 0xfe, 0x80, 0xfe, 0xff, 0xfe, 0x78, 0xfc, 0x13, 0x17, 0x6, 0xff, 0xff, 0x1, 0x10, 0x10,
  48. 0x13, 0x37, 0x4, 0xff, 0xff, 0x8, 0xf, 0x17, 0x10, 0x10, 0x1, 0xff, 0xff, 0x3, 0x13, 0x11
  49. };
  50. const unsigned char CACTUS_4[] = {
  51. 0xf0, 0xe0, 0x0, 0xff, 0xfe, 0x0, 0xf0, 0x0, 0xc0, 0x0, 0xff, 0xfe, 0x60, 0x3c, 0x80, 0x0,
  52. 0x0, 0x7c, 0xc0, 0xfe, 0xff, 0x0, 0xf0, 0xf8, 0x43, 0x47, 0x86, 0xff, 0xff, 0x26, 0xa3,
  53. 0xa0, 0x27, 0x4, 0xff, 0xff, 0x0, 0x8, 0xff, 0x88, 0x2f, 0x0, 0x0, 0xff, 0xff, 0x6, 0x23, 0x21
  54. };
  55. const unsigned char RESTART[] =
  56. {
  57. 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0x3f, 0xf, 0x1f, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
  58. 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x7e, 0x7e, 0x7e, 0x78, 0x7c, 0x7e, 0x7f, 0x7f, 0x7f, 0x7e, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff,
  59. 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
  60. };
  61. const unsigned char COVER[] = {
  62. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0xf0, 0xf0, 0xc0, 0xc0, 0xf0, 0xf0, 0x0, 0x0, 0xf0, 0xf0, 0xb0, 0xb0, 0x70, 0x60, 0x0, 0x0, 0xe0, 0xf0, 0x30, 0x30, 0xf0, 0xe0, 0x0, 0x0, 0xf0, 0xf0, 0x30, 0xf0, 0xf0, 0x30, 0xf0, 0xe0, 0x0, 0xe0, 0xe0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  63. 0x0,
  64. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf3, 0xf7, 0x36, 0x36, 0xf6, 0xe6, 0x0, 0xf0, 0xf7, 0x7, 0xc1, 0xc1, 0x37, 0x37, 0xf0, 0xc0, 0x7, 0xc7, 0xe0, 0x30, 0x37, 0x37,
  65. 0xe0, 0xc0, 0x3, 0x7, 0x6, 0xf6, 0xf7, 0xb3, 0xb0, 0xb0, 0xf7, 0xe7, 0x0, 0xf7, 0xf7, 0x0, 0x7, 0xf7, 0xf0, 0x3, 0xe3, 0xf4, 0x34, 0x34, 0xf4, 0xe4, 0x0, 0x0, 0x0, 0x0,
  66. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x10, 0xc, 0x4, 0x14, 0x14, 0x12, 0x11, 0x11, 0x11, 0x10, 0x11, 0x12, 0x12, 0x12, 0x14, 0x1c, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  67. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf, 0xc, 0xc, 0xf, 0x7, 0x0, 0xf, 0xf, 0x0, 0xf, 0xf, 0x0, 0x0, 0xf, 0xf, 0x0, 0x3, 0x7, 0xc, 0xc, 0xc, 0x7, 0x3, 0x0, 0x0, 0x0, 0xf, 0xf, 0x1, 0x1, 0x1, 0xe, 0xe, 0x0, 0x7, 0xf, 0xc, 0xc, 0x7, 0x7, 0x0, 0xf, 0xf, 0x0, 0x0, 0xf, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xc0, 0x60, 0xa0, 0xa0, 0xa0, 0x90, 0x88, 0x88, 0x8c, 0x88, 0x90, 0x90, 0xb0, 0xa0, 0xc0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  68. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0, 0x0, 0xf0, 0xfc, 0xfc, 0x9c, 0x9c, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf0, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  69. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  70. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x80, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0xf, 0xf, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0xfe, 0xfe, 0x0, 0x0, 0xf0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0xf8, 0xf0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x80, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  71. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf8, 0xf8, 0xe0, 0xe0, 0x80, 0x80, 0x80, 0xc0, 0xe0, 0xf8, 0xf8, 0xf8, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x18, 0x8, 0x38, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x1, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0xfc, 0xfe, 0x4, 0x0, 0xff, 0xff, 0xff, 0xc, 0xc, 0x8f, 0x83, 0x0, 0xf0, 0xf0, 0x0, 0x80, 0x9f, 0x3f, 0x7f, 0x70, 0x70, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
  72. 0x0, 0x0, 0x0, 0x0,
  73. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x7, 0xf, 0x1f, 0x1f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x1f, 0x17, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0x7, 0x7, 0xff, 0xff, 0xff, 0xff, 0x3, 0x3, 0x1, 0x0, 0x0, 0x3, 0x7, 0xe, 0xc, 0xff, 0xff, 0xff,
  74. 0x0, 0x0, 0x1f, 0x3f, 0x20, 0xff, 0xff, 0x20, 0x1f, 0xf, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x3, 0x3, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  75. 0x82, 0x82, 0x82, 0x2, 0x2, 0x22, 0x22, 0x22, 0x22, 0x2, 0x2, 0x2, 0x82, 0x82, 0x0, 0x0, 0x0, 0x1, 0xff, 0x9f, 0x9f, 0x7, 0x7, 0x1, 0x1, 0x7, 0x7, 0xff, 0x80, 0x80, 0x0, 0x0, 0x2, 0x2, 0x2, 0x2, 0xc2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x82, 0x82, 0x82, 0x82, 0x2, 0x2, 0x32, 0x32, 0x32, 0x22, 0x2, 0x2, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x42, 0x42, 0x2, 0x2, 0x2, 0x2, 0x2, 0x0, 0xf, 0xf, 0xf, 0xf, 0x0, 0x1, 0x1, 0x1, 0x11, 0x11, 0x1, 0x1, 0x0, 0xf, 0xf, 0xf, 0x0, 0x1, 0x31, 0x11, 0x0, 0xf, 0xf, 0x0, 0xd, 0xd, 0x1, 0x11, 0x11, 0x10, 0x1f, 0x1f, 0x1f, 0x1f, 0x10, 0x0, 0xd, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xd, 0xd, 0x1, 0x0, 0x0,
  76. };
  77. #endif

5.3 游戏运行代码

        游戏运行代码,主要包含两个部分:(1)按键代码;(2)游戏运行判定代码

按键代码key:

  1. int get_key_val()
  2. {
  3. if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4)==0)
  4. {
  5. HAL_Delay(10); //消抖
  6. if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4)==0)
  7. {
  8. return 2;
  9. }
  10. }
  11. if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3)==0)
  12. {
  13. HAL_Delay(10); //消抖
  14. if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3)==0)
  15. {
  16. return 1;
  17. }
  18. }
  19. return 0;
  20. }

游戏运行判定代码running:

  1. if (failed == 1)
  2. {
  3. OLED_DrawRestart();
  4. key_num = get_key_val();
  5. if (key_num == 2)
  6. {
  7. if(score > highest_score) highest_score = score;
  8. score = 0;
  9. failed = 0;
  10. height = 0;
  11. reset = 1;
  12. OLED_DrawDinoJump(reset);
  13. OLED_DrawCactusRandom(cactus_category, reset);
  14. OLED_Clear();
  15. }
  16. continue;
  17. }
  18. score ++;
  19. if (height <= 0) key_num = get_key_val();
  20. OLED_DrawGround();
  21. OLED_DrawCloud();
  22. if (height>0 || key_num == 1) height = OLED_DrawDinoJump(reset);
  23. else OLED_DrawDino();
  24. cactus_pos = OLED_DrawCactusRandom(cactus_category, reset);
  25. if(cactus_category == 0) cactus_length = 8;
  26. else if(cactus_category == 1) cactus_length = 16;
  27. else cactus_length = 24;
  28. if (cactus_pos + cactus_length < 0)
  29. {
  30. cactus_category = rand()%4;
  31. OLED_DrawCactusRandom(cactus_category, 1);
  32. }
  33. if ((height < 16) && ( (cactus_pos>=16 && cactus_pos <=32) || (cactus_pos + cactus_length>=16 && cactus_pos + cactus_length <=32)))
  34. {
  35. failed = 1;
  36. }
  37. OLED_ShowString(35, 0, "HI:", 12);
  38. OLED_ShowNum(58, 0, highest_score, 5, 12);
  39. OLED_ShowNum(98, 0, score, 5, 12);
  40. reset = 0;
  41. cur_speed = score/20;
  42. if (cur_speed > 29) cur_speed = 29;
  43. HAL_Delay(30 - cur_speed);
  44. // HAL_Delay(500);
  45. key_num = 0;
  46. /* USER CODE BEGIN 3 */
  47. }

        这里简单给大家说明一下,代码原理:根据按键的读取的数值去控制小恐龙的运动状态,同时,屏幕上不断移动和随机生成仙人掌障碍物,得分随着游戏进行增加。花一点时间去读一下程序,还是很好理解的。(为了复现出原版谷歌小恐龙随时间增加,速度越来越快的特性,这里根据用户得分情况,使用减小延迟函数时间去加快游戏速度提高难度

六、游戏效果

        笔者是一只手拍摄,一只手玩这个游戏,再加上KEY按键靠得太近,按得不方便,所以反复GG。(小声:好吧,笔者太菜!)实在话,感觉小恐龙跑得太快的话,可以把得分延迟函数基础数值加大一点。

代码开源

链接:https://pan.baidu.com/s/1RHHZ8P3axWi5HQR8MHhagw 提取码:b7uy

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发