使用51单片机驱动1.54英寸墨水屏做一个简洁的贪吃蛇游戏

  • 1.硬件信息
  • 2.界面设计
  • 3.程序流程
    • 3.1 游戏初始化
    • 3.2 生成食物坐标
    • 3.3 获取前进方向
    • 3.4 蛇的坐标更新
    • 3.5 碰撞检测
    • 3.6 输出界面
    • 3.7 主函数
  • 4 结果展示

1.硬件信息

本文使用的是STC15W408AS型号的51单片机,自己做的一个带按键的小系统,显示屏使用的是某宝上买的1.54英寸的墨水屏,一共有200 * 200个像素点。所以整个游戏界面的坐标按照200 * 200进行设计。

2.界面设计

既然是简洁版的贪吃蛇,那么显示界面就一切从简了,如下图所示。只要搞懂了基本的设计思路在此基础上还是可以搞复杂的。(0_0)

首先是游戏场地,在四周是宽度为8个像素的墙壁,如果蛇头碰撞到墙壁那么游戏结束,也就是说蛇头的坐标超出规定范围就游戏结束。
为方便计算,在原本200 * 200像素的基础上,我把8 * 8作为一个游戏像素,也就是映射为25 * 25个像素。把8 * 8像素的左上角作为坐标的话,蛇的活动范围就在(1,1)到(23,23)。

3.程序流程

贪吃蛇游戏涉及到蛇的移动、食物生成、碰撞检测、方向控制和界面输出。所以整个程序的设计可以按照以下步骤:

1.游戏初始化
2.生成食物坐标
3.获取前进方向
4.蛇的坐标更新
5.碰撞检测(墙壁,蛇身和实物)
6.输出界面

大致的程序流程:

3.1 游戏初始化

游戏一开始我设计的是蛇的长度为3,初始方向向右。由于51单片机不好实现链表,这里直接用数值存储蛇的每个游戏像素坐标。本文设计最大长度为20,超过20游戏结束。以下是相关的变量初始化。

u8 snake_len=3; //蛇的长度
u8 snake_xy[20][2]={{5,3},{4,3},{3,3}};    //初始蛇坐标
u8 sanke_tempxy[2]={5,3};      //保存尾坐标
char direction_xy[2]={1,0};        //前进方向
u8 food_xy[2]={4,5};       //食物坐标
u8 gemeover=0; //0位继续 1死亡结束 2通过结束
bit eat=0;     //是否吃到食物

其中前进方向用在后面的蛇头坐标计算中。

3.2 生成食物坐标

使用rand()函数生成1到23的随机数作为食物的生成坐标,且生成的坐标不能和蛇身重合。
需要包含头文件 #include <stdlib.h>

void Food_GetXY(void)
{u8 ture=0; //生成的值不能和蛇身坐标重合u8 i=0;if(eat){while(!ture){ture = 1;food_xy[0] = (rand()%22)+1;        //1-23for(i=0;i<snake_len;i++)if(food_xy[0] == snake_xy[i][0])ture = 0;}ture = 0;while(!ture){ture = 1;food_xy[1] = (rand()%22)+1;     //1-23for(i=0;i<snake_len;i++)if(food_xy[1] == snake_xy[i][1])ture = 0;}eat = 0;}
}

3.3 获取前进方向

在主函数中一直循环获取按键键值,更新前进方向:

key_get = Key_Scan2();
if(key_get)
{switch(key_get){case 1:{direction_xy[0] = 0;direction_xy[1] = 1;break;}case 2:{direction_xy[0] = 1;direction_xy[1] = 0;break;}case 4:{direction_xy[0] = -1;direction_xy[1] = 0;break;}case 8:{direction_xy[0] = 0;direction_xy[1] = -1;break;}}key_get = 0;
}

其中的按键获取函数是无去抖等待的,需要的可以参考:
STM32定时器实现不加延时的三种独立按键获取函数——返回1次,多次和长短按键

3.4 蛇的坐标更新

先保存下蛇尾的坐标,后面碰撞检测的时候如果吃到食物需要用于增加蛇身长度。
然后,从后往前更新蛇身坐标。
最后,按照前进方向更新蛇头坐标。

void Snake_UpdateXY(void)
{u8 i=0;sanke_tempxy[0] = snake_xy[snake_len-1][0];       //保存尾坐标sanke_tempxy[1] = snake_xy[snake_len-1][1];for(i=snake_len;i>0;i--)                     //从后往前更新蛇身坐标{snake_xy[i][0] = snake_xy[i-1][0];snake_xy[i][1] = snake_xy[i-1][1];}snake_xy[0][0] += direction_xy[0];                //按照前进方向更新蛇头坐标snake_xy[0][1] += direction_xy[1];}

3.5 碰撞检测

超出游戏界面范围的话游戏结束,蛇身超过20游戏通过。

void Snake_Crash(void)                       //碰撞判断
{u8 i=0;if((snake_xy[0][0]>23 || snake_xy[0][0]<1)||(snake_xy[0][1]>23 || snake_xy[0][1]<1))   //蛇头碰到边框gemeover = 1;//    for(i=1;i<snake_len;i++)
//      if((snake_xy[0][0]==snake_xy[i][0]) && (snake_xy[0][1]==snake_xy[i][1]))    //蛇头碰撞蛇身
//          gemeover = 1;if(snake_xy[0][0]==food_xy[0] && snake_xy[0][1]==food_xy[1])          //吃到食物{eat = 1;snake_len++;snake_xy[snake_len-1][0] = sanke_tempxy[0];      //尾巴增加snake_xy[snake_len-1][1] = sanke_tempxy[1];if(snake_len==20)gemeover = 2;                         //通关}
}

3.6 输出界面

通过游戏坐标,这边调用的是墨水屏的显示函数,游戏用在其他地方的话可以忽略这节。

void Show_Updaet(void)
{u8 i=0;EPD_Dis_Part(0,0,gImage_main_1,200,8,OFF);             //边框EPD_Dis_Part(192,8,gImage_main_1,8,192,OFF); EPD_Dis_Part(0,8,gImage_main_1,8,192,OFF); EPD_Dis_Part(8,192,gImage_main_1,184,8,OFF); if(gemeover==1){EPD_Dis_Part(110,72,gImage_num[4],35,56,NEG);    //失败界面EPD_Dis_Part(150,72,gImage_num[4],35,56,NEG); }else if(gemeover==2){EPD_Dis_Part(110,72,gImage_num[6],35,56,NEG);   //通关界面EPD_Dis_Part(150,72,gImage_num[6],35,56,NEG); }       else{for(i=0;i<snake_len;i++)                         //显示蛇身EPD_Dis_Part(snake_xy[i][0]*8,snake_xy[i][1]*8,gImage_main_1,8,8,OFF); EPD_Dis_Part(food_xy[0]*8,food_xy[1]*8,gImage_main_1,8,8,OFF);     //显示食物}EPD_Part_Update();
}

3.7 主函数

int main()
{//  uchar i;u8 key_get=0;system_init();while(1){if(gemeover)   //游戏结束{return 0;}key_get = Key_Scan2();    //获取按键if(key_get){switch(key_get){          //获取前进方向case 1:{direction_xy[0] = 0;direction_xy[1] = 1;break;}case 2:{direction_xy[0] = 1;direction_xy[1] = 0;break;}case 4:{direction_xy[0] = -1;direction_xy[1] = 0;break;}case 8:{direction_xy[0] = 0;direction_xy[1] = -1;break;}}key_get = 0;}if(system_ctr&0x01 && !isEPD_W21_BUSY) //每隔500ms进一次进行游戏更新{Show_clear_snake();  //清屏Food_GetXY();   //生成食物坐标Snake_UpdateXY();//蛇的坐标更新Snake_Crash(); //碰撞检测Show_Updaet();    //输出界面system_ctr &= ~0x01;}}return 0;
}

4 结果展示

最后来看下效果吧,这个墨水屏更新显示太慢了,导致游戏不能快点刷新,体验极差(0-0),显示的动图这是快了4倍的速度。本文如果对你有帮助的话就点个赞吧

【使用51单片机驱动1.54英寸墨水屏做一个简洁的贪吃蛇游戏】相关推荐

  1. 基于51单片机和OLED屏幕的贪吃蛇游戏

    本文章在于利用51单片机和OLED屏幕实现一个简易的贪吃蛇游戏 所用的51单片机为普中51系列,OLED屏幕属中景园电子,具体实物均可以在某宝购买 OLED模块: 关于OLED模块的相关函数及其.h和 ...

  2. c语言编程TLC2543AD采集,51单片机驱动12位AD转换TLC2543电路图+程序

    51单片机驱动12位AD转换TLC2543电路图+程序 2015-06-18 16:51:15   来源:51hei void resultvolt() { volt=volt*5000.0/4334 ...

  3. 51单片机驱动——LCD1602

    51单片机驱动--LCD1602 1.描述 51单片机控制LCD1602屏幕显示测量数据.固定字符串等,大家复制过去可以直接使用,相关注释我已标明. 2.子文件 LCD1602.c #include ...

  4. 用51单片机驱动蜂鸣器

    用51单片机驱动蜂鸣器 #include<reg51.h>//头文件 sbit BEEP=P1^5;//位定义P1的第五个端口为蜂鸣器 void delay() //延时函数 {unsig ...

  5. 51单片机驱动DS18B20温度传感器测量温度

    51单片机驱动DS18B20温度传感器测量温度 1.DS18B20温度传感器介绍: 2.51单片机驱动DS18B20测量温度 1.DS18B20温度传感器介绍: ①引脚定义 引脚 符号 说明 1 GN ...

  6. 使用51单片机驱动YM12232B型液晶显示屏

    这是一个使用51单片机驱动YM12232B 液晶显示器的例子,本人水平有限,仅供参考. 本实例中将使用51单片机控制YM12232B LCD分别在主窗口和副窗口中显示"科"和&qu ...

  7. 基于51单片机驱动A4988实现步进电机逆时针转动

    基于51单片机驱动A4988实现步进电机逆时针转动 一.简介 二.接线 典型接线图 实际接线 三.部分代码 引脚定义 定时器初始化 主函数 四.实验现象 五.注意事项 一.简介 A4988 是一款完全 ...

  8. 基于51单片机驱动HC-SR04超声波模块(LCD1602显示)

    基于51单片机驱动HC-SR04超声波模块(LCD1602显示) 一.基本参数 二.通信时序 三.部分代码展示 四.实际效果 总结 一.基本参数 点击图片购买 HC- SR04+是一款宽电压工作的超声 ...

  9. 51单片机驱动HMI串口屏,串口屏的下载方式

    51单片机驱动HMI串口屏,串口屏的下载方式 串口屏 串口屏的程序下载 51程序 总结 串口屏 串口屏是一个集成了单片机的屏幕模块,采用的是TTL串口协议,可以直接通过对应指令控制屏幕, 本文采用的串 ...

  10. 基于51单片机驱动ADXL346 (LCD1602显示)

    基于51单片机驱动ADXL346 (LCD1602显示) 一.ADXL346传感器介绍 1.实物图 2.产品说明 3.电气参数 4.通信协议 二.驱动代码 1.引脚定义 2.初始化函数 3.主函数 三 ...

最新文章

  1. Python实现信息自动配对爬虫排版程序(附下载)
  2. 数据库常用的基本操作
  3. [编译原理学习]词法分析
  4. 单片机小白学步系列(七) 准备实验板——萝卜青菜,各有所爱
  5. 蓝桥杯2015初赛-星系炸弹-日期计算
  6. Linux进程之间通信 信号
  7. 金山云服务器内网带宽,金山云-文档中心-配置弹性网卡
  8. TensorFlow2.0实战: 入门到进阶深度学习
  9. 在Word中如何实现后退?
  10. 高德联手饿了么:外卖小哥跑出偏远地区活地图
  11. jquery的img的动态title换行
  12. mysql 主从复制延迟_什么情况会导致MySQL主从复制延迟?
  13. [引]构造文法时表达式中算符优先级的问题
  14. HTML5 Canvas 车架号第十位是L,汽车生产日期字母对照
  15. u盘被写保护了无法格式化怎么办?
  16. 浙江大学计算机学院 翁恺,“中文MOOC第一人”浙江大学教师翁恺获得百万大奖...
  17. Spark 报错 Failed to delete: C:\Users\lvacz\AppData\Local\Temp\spark-*
  18. 实现字符和Unicode码互换 (Java经典编程案例)
  19. 【034】翼辉信息获得“核高基”重大专项支持
  20. 2023春节祝福系列第一弹(上)(放飞祈福孔明灯,祝福大家身体健康)(附完整源代码及资源免费下载)

热门文章

  1. 单片机学习心得体会_经验总结
  2. 2020神舟几号发射_2020广东事业单位考试:神舟飞船小知识的考点提炼
  3. 实现elementUI多语言切换
  4. 卡片游戏 基础c语言试题
  5. 苹果 ios mdm服务器搭建
  6. 基于51单片机超声波红外避障语音导盲仪设计(全套资料)
  7. matlab模糊聚类分析画树状图,Matlab笔记模糊聚类分析原理及实现
  8. font-family字体-常用字体中英文对照表
  9. Android Scheme协议与应用全解析
  10. 如何实现pdf转换成cad呢?