【STM32单片机】贪吃蛇游戏设计


一、主要功能

系统运行后,TFTLCD触摸屏显示游戏界面,通过按键任意键进入游戏界面, 然后通过按键KEY_UP、KEY1、KEY2和KEY0键控住上下左右方向。 每当蛇吃到3个食物,速度就会提升一个等级,并且显示得分和等级,最高位5级。当游戏结束后可按任意键重新回到主界面开始。


二、硬件资源

1.硬件准备

项目所需要的硬件资源如下:
①STM32F103或STM32F407开发板1个
②TFTLCD液晶模块1个
③USB线1条(用于供电和程序下载)
④杜邦线若干

2.硬件连接

	TFTLCD触摸屏模块-->单片机IO
	  
	  按键模块-->单片机IO
	  KEY_UP-->PA0
	  KEY0-->PE4
	  KEY1-->PE3
	  KEY2-->PE2

四、软件设计

1.软件结构

在这里插入图片描述

2.主要代码

主要代码如下:

/*
作者:嗨小易(QQ:3443792007)
*/


//游戏初始化
void GameInit()
{
	u16 color=FRONT_COLOR;
	
	LCD_ShowPicture(0,(tftlcd_data.height-240)/2,320,240,(u8 *)gImage_picture);
	LCD_ShowFontHZ((tftlcd_data.width-7*32)/2,20,"贪吃蛇游戏设计");
	while(1)
	{
		//如果有键按下则退出,重新开始
		if(KEY_Scan(0)!=0)
		{
			LCD_Clear(BACK_COLOR);
			break;
		}
	}
	
	//绘制窗口
	window.color=BLACK;
	window.x=(tftlcd_data.width-WIN_WIDTH)/2;
	window.y=(tftlcd_data.height-WIN_HEIGHT)/2-30;
	
	//初始化蛇
	snake.num=3;
	snake.dir=RIGHT;
	snake.score=0;
	snake.size=10;
	snake.level=1;
	snake.coor[2].x=window.x+snake.size;snake.coor[2].y=window.y+snake.size;
	snake.coor[1].x=window.x+snake.size+snake.size;snake.coor[1].y=window.y+snake.size;
	snake.coor[0].x=window.x+snake.size+2*snake.size;snake.coor[0].y=window.y+snake.size;
	
	//初始化食物
	food.fd.x=window.x+rand()%(WIN_WIDTH/snake.size)*snake.size;
	food.fd.y=window.y+rand()%(WIN_HEIGHT/snake.size)*snake.size;
	food.flag=1;
	food.color=RED;
	
	//得分显示
	FRONT_COLOR=BLACK;
	LCD_ShowFontHZ((tftlcd_data.width-7*32)/2,20,"贪吃蛇游戏设计");
	FRONT_COLOR=color;
	LCD_ShowString(window.x,window.y+WIN_HEIGHT+10,tftlcd_data.width,30,24,"Score:");
	LCD_ShowString(window.x,window.y+WIN_HEIGHT+50,tftlcd_data.width,30,24,"Level:");
	

	//初始化速度
	gspeed=SNAKE_SPEED;
	gcnt=0;
}

//游戏绘图
void GameDraw()
{
	u16 i=0;
	//绘制窗口
	LCD_DrawRectangle_Color(window.x,window.y,window.x+WIN_WIDTH,window.y+WIN_HEIGHT,window.color);
	
	//画蛇
	for(i=0;i<snake.num;i++)
	{
		LCD_Fill(snake.coor[i].x,snake.coor[i].y,snake.coor[i].x+snake.size,snake.coor[i].y+snake.size,YELLOW);
		LCD_DrawRectangle_Color(snake.coor[i].x,snake.coor[i].y,snake.coor[i].x+snake.size,snake.coor[i].y+snake.size,BLACK);
	}
	
	//画食物
	if(food.flag==1)
	{
		LCD_Fill(food.fd.x,food.fd.y,food.fd.x+snake.size,food.fd.y+snake.size,food.color);
	}
	
	//显示分数
	LCD_ShowxNum(window.x+6*12,window.y+WIN_HEIGHT+10,snake.score,5,24,0);
	//显示等级
	LCD_ShowxNum(window.x+6*12,window.y+WIN_HEIGHT+50,snake.level,1,24,0);
}

//蛇身移动
void SnakeMove()
{
	u16 i=0;
	
	//清除上次的蛇身末尾节
	LCD_Fill(snake.coor[snake.num-1].x,snake.coor[snake.num-1].y,snake.coor[snake.num-1].x+snake.size,snake.coor[snake.num-1].y+snake.size,BACK_COLOR);
		
	//重新获取蛇身移动一步位置
	for(i=snake.num-1;i>0;i--)
	{
		snake.coor[i].x=snake.coor[i-1].x;
		snake.coor[i].y=snake.coor[i-1].y;
	}
	switch(snake.dir)
	{
		case UP:
			snake.coor[0].y-=snake.size;
			break;
		case DOWN:
			snake.coor[0].y+=snake.size;
			break;
		case LEFT:
			snake.coor[0].x-=snake.size;
			break;
		case RIGHT:
			snake.coor[0].x+=snake.size;
			break;
	}
}

//蜂鸣器提示
void beep_alarm(void)
{
	BEEP=1;
	delay_ms(50);
	BEEP=0;
}

//游戏结束
void game_over()
{
	beep_alarm();
	//游戏结束显示
	LCD_ShowFontHZ((tftlcd_data.width-32*4)/2,(tftlcd_data.height-29)/2,"游戏结束");
	LCD_ShowString((tftlcd_data.width-8*20)/2,(tftlcd_data.height-29)/2+30,tftlcd_data.width,tftlcd_data.height,16,"Press KEY ReStart...");
	while(1)
	{
		//如果有键按下则退出,重新开始
		if(KEY_Scan(0)!=0)
		{
			LCD_Clear(BACK_COLOR);
			GameInit();
			break;
		}
	}
}

//游戏结束判断
void DontEatSelf()
{
	u16 i=0;
	//判断是否碰撞到身体,前提是蛇身要超过3节
	for(i=4;i<snake.num;i++)
	{
		if(snake.coor[0].x==snake.coor[i].x && snake.coor[0].y==snake.coor[i].y) 
		{
			game_over();//游戏结束
		}
	}
	//判断是否碰撞到边界区
	if(snake.coor[0].x>=window.x+WIN_WIDTH || snake.coor[0].x<=window.x-snake.size ||
		snake.coor[0].y>=window.y+WIN_HEIGHT || snake.coor[0].y<=window.y-snake.size)
	{
		game_over();//游戏结束
	}
}

//应用程序
void app_demo(void)
{
	BEEP_Init();
	KEY_Init();
	LED_Init();
	My_EXTI_Init();
	TFTLCD_Init();
	TP_Init();
	
	GameInit();//游戏参数初始化
	
	while(1)
	{
		SnakeMove();//方向控制
		GameDraw();//游戏绘制
		EatFood();//蛇吃食物
		DontEatSelf();//检测是否碰撞
		delay_ms(gspeed);//蛇移动速度
		//速度控制,当每吃到3个食物,速度增加
		if(gcnt>=3)
		{
			gcnt=0;
			snake.level++;
			gspeed-=100;
			if(gspeed<100)
			{
				gspeed=50;
				snake.level=5;
			}	
		}
	}
}




五、实验现象

B站演示视频:https://space.bilibili.com/444388619

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

联系作者

作者B站链接:https://space.bilibili.com/444388619
可提供手把手教学服务,资料获取请联系作者QQ:3443792007
专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。