找回密码
 立即注册
查看: 1759|回复: 12

PWM硬件移相测试卡教程(二)贪吃蛇@STC8H2K12U系列

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

冲哥视频教程和各种开源资料QQ交流群884047237,可群

积分
8058
QQ
发表于 2024-4-7 22:29:54 | 显示全部楼层 |阅读模式
话不多说,先上测试视频:



这一章节用的硬件是PWM移相测试卡+OLED12864 ( SSD1306_IIC)
截图202404071937393649.jpg

序言、
    最近刷抖音看到了个贪吃蛇,这不一下就激起了童年的回忆,准备小试牛刀做个贪吃蛇耍耍。既然也做出来了个初版,那就给广大网友一起耍耍了,想自己借鉴或者升级的也可以仔细看下文章,想玩的直接群文件下载代码即可。这个帖子的代码用的最最好理解的方法写的,适合新手练习,老鸟略过哈哈。
截图202404071940526265.jpg

一、知识储备
1.去下面这个帖子学习IIC的知识:https://www.stcaimcu.com/forum.php?mod=viewthread&tid=236
2.去下面这个帖子学习OLED显示汉字的知识:https://www.stcaimcu.com/forum.php?mod=viewthread&tid=30
3.去下面的帖子学习单片机驱动G驱动OLED12864,I2C方式:https://www.stcaimcu.com/forum.php?mod=viewthread&tid=2592
4.去下面的帖子学习菜单:https://www.stcaimcu.com/forum.php?mod=viewthread&tid=44

二、效果分析
按键,oled初始化什么的比较简单就略过了,有需要的可以去看上面的帖子。这里主要讲绘图和蛇的动作。
1.界面功能切换的结构体
typedef struct Menu
{
    uint8_t Sub;
    //进入下一级
    uint8_t Enter;
    //返回上一级
    uint8_t Back;
    // 对应的函数指针
    void (*Current_Operation)(void);
} Menu_Table;
程序里基于这个结构体定义了一个结构体数组,

Menu_Table Table[3]= {   /* 菜单及界面 */
    /*SUB E  B  F */
    {2, 1, 0, Menu},
    {0, 1, 0, Game},
    {0, 0, 0, GameMode}
};
这个结构体数组讲用到的三个界面都做进去了,分别是主菜单界面(Menu),游戏界面(Game),游戏模式设置界面(GameMode)。

2.界面和功能切换的函数指针
在代码里定义了一个 void (*Operation)(void); 的函数指针,Operation指向要执行的函数。Operation=Table[Cur].Current_Operation指向当前界面的函数,然后再主循环里不断的循环执行这个函数。这部分不懂得可以去参考上面的菜单的帖子。

3.主菜单界面(Menu)介绍
(1)如果切换过界面,先清除当前界面的显示
(2)初始化所有的运行变量
(3)显示汉字
(4)判断当前的模式并在指定位置显示 *
具体的实现代码如下:
  1. void Menu(void)
  2. {
  3.     if(modeFlag)
  4.     {
  5.         OLED_Clear();
  6.     }
  7.     /* 不在游戏中 */
  8.     playing = 0;
  9.     modeFlag = 0;
  10.     replay = 1;
  11.     Get_Command();
  12.     /* 关闭定时器 */
  13.     TR0 = 0;
  14.     /* 显示贪吃蛇 */
  15.     OLED_ShowCHinese(44,0,0);
  16.     OLED_ShowCHinese(60,0,1);
  17.     OLED_ShowCHinese(76,0,2);
  18.     /* 开始游戏 */
  19.     OLED_ShowCHinese(34,3,3);
  20.     OLED_ShowCHinese(50,3,4);
  21.     OLED_ShowCHinese(66,3,5);
  22.     OLED_ShowCHinese(82,3,6);
  23.     /* 难度选择 */
  24.     OLED_ShowCHinese(34,5,7);
  25.     OLED_ShowCHinese(50,5,8);
  26.     OLED_ShowCHinese(66,5,9);
  27.     OLED_ShowCHinese(82,5,10);
  28.     /* 菜单选择 */
  29.     switch(menuSelect)
  30.     {
  31.     case MAINMENU:
  32.         OLED_ShowChar(14,3,'*',16);
  33.         OLED_ShowChar(14,5,' ',16);
  34.         break;
  35.     case GAMEMODE:
  36.         OLED_ShowChar(14,5,'*',16);
  37.         OLED_ShowChar(14,3,' ',16);
  38.         break;
  39.     }
  40. }
复制代码
显示效果图如下图所示:
截图202404072135272594.jpg

4.游戏模式设置界面(GameMode)
(1)如果切换过界面,先清除当前界面的显示
(2)初始化所有的运行变量
(3)显示汉字
(4)判断当前的模式并在指定位置显示 * ,表示当前选中

具体的实现代码如下:
  1. void GameMode(void)
  2. {
  3.     if(!modeFlag)
  4.     {
  5.         OLED_Clear();
  6.     }
  7.     Get_Command();
  8.     playing = 0;
  9.     modeFlag = 1;
  10.     OLED_ShowCHinese(34,1,15);
  11.     OLED_ShowCHinese(50,1,16);
  12.     OLED_ShowCHinese(34,4,17);
  13.     OLED_ShowCHinese(50,4,18);
  14.     switch(CuMode)
  15.     {
  16.     case 0:
  17.         OLED_ShowChar(14,1,'*',16);
  18.         OLED_ShowChar(14,4,' ',16);
  19.         break;
  20.     case 1:
  21.         OLED_ShowChar(14,1,' ',16);
  22.         OLED_ShowChar(14,4,'*',16);
  23.         break;
  24.     }
  25. }
复制代码
显示效果图如下图所示:
截图202404072136251055.jpg

5.游戏界面(Game)
(1)是否重新开界面,先清除当前界面的显示和之前的游戏记录
(2)定时时间到了蛇移动,如果移动后吃到了食物在重新生成,画新的蛇
(3)如果游戏结束了展示成绩
具体的实现代码如下:
  1. void Game(void)
  2. {
  3.     /* 重开游戏 */
  4.     if(replay)
  5.     {
  6.         /* 贪吃蛇初始化 */
  7.         clearSnake();
  8.         GUI_Init();
  9.         replay = 0;
  10.     }
  11.     /* 正在游戏中 */
  12.     playing = 1;
  13.     /* 开启定时器 */
  14.     TR0 = 1;
  15.     if(timerFlag)
  16.     {
  17.         Move();
  18.         Eat_Food();
  19.         drawSnake();
  20.         timerFlag = 0;
  21.     }
  22.     //定时器0开始计时
  23.     Get_Command();
  24.     GUI_Refresh(map);
  25.     if(GameOver())
  26.     {
  27.         OLED_Clear();
  28.         /* 展示成绩 */
  29.         Show_Score();
  30.         Delay2000ms();
  31.         OLED_Clear();
  32.         Cur = Table[Cur].Back;
  33.     }
  34. }
复制代码
显示效果图如下图所示:
截图202404072210238020.jpg

截图202404072213116116.jpg

三、蛇体部分分析
1.如何实现游戏界面的显示:
本项目使用的OLED屏是0.96寸的,像素为128*64。贪吃蛇少不了蛇,如果采用一个像素点来画蛇的身体,那这个蛇小到离谱,不够明显。
所以本项目使用的4*4像素的正方形(只点亮外框像素)来绘制蛇的身体。实现的思路大致如下:
使用map [32][16]放大四倍变为128*64。
截图202404072222269218.jpg
map [32][16] : 对应的是上图中的左边。用于存储数据,然后调用GUI_Refresh判断相应的值,做出对应的操作,然后放大四倍成为上图中的右边,最后再调用OLED里面的相关代码,就会把数据写入OLED_GRAM[128][8]。
例如:
  1. void Paint_Body(uint8_t x,uint8_t y )//绘制身体
  2. {
  3.     uint8_t i,j;
  4.     for(i=4*y; i<4*y+4; i++)
  5.     {
  6.         for(j=4*x; j<4*x+4; j++)
  7.         {
  8.             if(i==4*y||i==4*y+3)
  9.             {
  10.                 OLED_DrawPoint(j,i);
  11.             }
  12.             if(j==4*x||j==4*x+3)
  13.             {
  14.                 OLED_DrawPoint(j,i);
  15.             }
  16.         }
  17.     }
  18. }
  19. void Paint
复制代码
这里OLED_GRAM[128][8]:作为OLED的显存数组,通过这个数据就可以让OLED上对应的像素亮起来。• snake_Grid[32][2]: 用来存储蛇的坐标,后面会有讲解。其他的代码也可以这样实现,比如画外框,食物等。之后就只需要操作map数组,就可以完成我们的贪吃蛇啦。

2.游戏规则设计
上面有提到snake_Grid[32][2]是用于存储蛇的坐标的,同时snake_Grid[0][0]和snake_Grid[0][1]是来存储蛇头的坐标,我们只需要判断蛇的其他坐标是不是等于蛇头的坐标,相等说明吃到自己了,结束游戏;另一个规则是撞到墙游戏结束,只需要判断蛇头的坐标是不是等于0xfe(0xfe对应的是边框值)。
  1. // 撞到墙结束游戏
  2.         if(map[snake_Grid[0][0]][snake_Grid[0][1]] == 0xfe && GameDifficulty==1)
  3.         {
  4.                 // crashWall
  5.                 crashWall = 1;
  6.         }
复制代码
  1. bit GameOver(void)
  2. {
  3.     //蛇头坐标
  4.     uint8_t sx=snake_Grid[0][0],sy=snake_Grid[0][1],i;
  5.     //判断有没有吃到自己
  6.     for(i=1; i<length; i++)
  7.     {
  8.         if(snake_Grid[i][0]==sx && snake_Grid[i][1]==sy)
  9.             return 1;
  10.     }
  11.         //如果撞到墙
  12.         if(crashWall==1 && GameDifficulty==1)
  13.         {
  14.                 crashWall = 0;
  15.                 return 1;
  16.         }
  17.     return 0;
  18. }
复制代码

具体的代码都在上面讲解了,有需要源码的小伙伴可以在群文件下载,有任何问题可以在下面留言!

回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

冲哥视频教程和各种开源资料QQ交流群884047237,可群

积分
8058
QQ
发表于 2024-4-7 22:37:06 | 显示全部楼层
有奖征集,谁能第一个把这个代码里的显示屏的显示改为字库索引的方式的话
(附上修改好的代码,并展示用STC-ISP软件实现汉字取模的过程方为有效),
免费送一套这个文中的硬件!注意:只有在本文下方第一个发布的才有效!!
截图202404072235005166.jpg


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:512
  • 最近打卡:2025-05-01 09:14:27

21

主题

564

回帖

2674

积分

金牌会员

积分
2674
发表于 2024-4-8 08:26:01 | 显示全部楼层
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:347
  • 最近打卡:2025-05-01 08:57:33
已绑定手机

30

主题

111

回帖

1659

积分

荣誉版主

Rbowlystar

积分
1659
发表于 2024-4-9 18:45:39 | 显示全部楼层
本帖最后由 四汐 于 2024-4-9 18:48 编辑

修改前:
  1. //显示汉字
  2. void OLED_ShowCHinese(u8 x,u8 y,u8 no)
  3. {
  4.     u8 t,adder=0;
  5.     OLED_Set_Pos(x,y);
  6.     for(t=0; t<16; t++)
  7.     {
  8.         OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
  9.         adder+=1;
  10.     }
  11.     OLED_Set_Pos(x,y+1);
  12.     for(t=0; t<16; t++)
  13.     {
  14.         OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
  15.         adder+=1;
  16.     }
  17. }
复制代码


修改后:
截图202404091847229349.jpg

取模设置:
截图202404091839505801.jpg


字库:
截图202404091841313604.jpg 截图202404091842103248.jpg


点评

附上改完之后的代码压缩包即可领取哈  详情 回复 发表于 2024-4-9 21:27
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

冲哥视频教程和各种开源资料QQ交流群884047237,可群

积分
8058
QQ
发表于 2024-4-9 21:27:26 | 显示全部楼层

附上改完之后的代码压缩包即可领取哈
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-01 09:54:52
已绑定手机

19

主题

3190

回帖

4866

积分

论坛元老

积分
4866
发表于 2024-4-9 21:51:33 | 显示全部楼层
没入群就没源码下了?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:347
  • 最近打卡:2025-05-01 08:57:33
已绑定手机

30

主题

111

回帖

1659

积分

荣誉版主

Rbowlystar

积分
1659
发表于 2024-4-11 01:13:56 | 显示全部楼层
电子DI*** 发表于 2024-4-9 21:27
附上改完之后的代码压缩包即可领取哈

2.贪吃蛇.zip (343.49 KB, 下载次数: 150)

点评

q群里私聊下群主领取奖励  详情 回复 发表于 2024-4-11 08:06
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

冲哥视频教程和各种开源资料QQ交流群884047237,可群

积分
8058
QQ
发表于 2024-4-11 08:06:42 | 显示全部楼层

{:5_272:}q群里私聊下群主领取奖励
回复 支持 2 反对 0

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15611
发表于 2024-4-11 08:19:33 | 显示全部楼层
还是放个附件,完整程序,供大家方便下载,
体现我们纯技术论坛的博大精深

点评

上面有群友放了升级版的代码  详情 回复 发表于 2024-4-11 15:56
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:135
  • 最近打卡:2024-12-25 10:15:05

47

主题

1350

回帖

8058

积分

荣誉版主

冲哥视频教程和各种开源资料QQ交流群884047237,可群

积分
8058
QQ
发表于 2024-4-11 15:56:40 | 显示全部楼层
神*** 发表于 2024-4-11 08:19
还是放个附件,完整程序,供大家方便下载,
体现我们纯技术论坛的博大精深
...

上面有群友放了升级版的代码{:5_332:}
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 21:55 , Processed in 0.489566 second(s), 116 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表