当前位置: 首页>編程日記>正文

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

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

使用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倍的速度。本文如果对你有帮助的话就点个赞吧👍。
请添加图片描述


https://www.fengoutiyan.com/post/15375.html

相关文章:

  • 墨水屏如何驱动
  • 单片机小精灵使用方法
  • fpga 贪吃蛇
  • python 51单片机开发
  • arduino 贪吃蛇
  • 51单片机驱动液晶屏
  • 驱动触摸屏比较好用的单片机
  • 单片机驱动的液晶屏接口类型
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機