【STM32单片机】小恐龙游戏设计


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED模块等。
主要功能:
系统运行后,OLED液晶显示游戏初始界面,按下K4键开始,K1键跳跃;
在初始界面状态下,按下K3键进入设置界面,K1用于选择,K4确定,K3返回;
游戏界面左上角为最高得分,右上角为本次游戏得分。


二、软件设计

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

*/


void Buzzer_Init()//蜂鸣器初始化
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void Buzzer(uint8_t SW)//蜂鸣器控制
{
	if(SW)
	{
	GPIO_SetBits(GPIOB,GPIO_Pin_0);
	}
	else
	{
	GPIO_ResetBits(GPIOB,GPIO_Pin_0);	
	}
}
void bostacle_refresh(void)//随机障碍
{
	obstacle_pos=obstacle(obstacle_ran,0);
	if(obstacle_pos+obstacle_length<=0)
	{
	obstacle_ran=rand()%4;
	obstacle_pos=obstacle(obstacle_ran,1);	
	}

	switch (obstacle_ran)//随机三种不同宽度障碍
	{
		case 0: obstacle_length=8;break;
		case 1: obstacle_length=16;break;
		default: obstacle_length=24;break;
	}			
}

void Show_other(void)//显示云、地面、分数
{	
	OLED_ShowString(1,14,"SC:",1,0);
	OLED_ShowString(1,0,"HS:",1,0);
	score++;
	if(score%100==0)Buzzer(1);
	else Buzzer(0);
	OLED_ShowDainamic8x128(7,roll);
	OLED_ShowCloud();
	OLED_ShowNum(1,17,score,5,1);
	OLED_ShowNum(1,4,Hs,5,1);
}
void loop_dead(void)//检测恐龙是否撞到障碍
{
	if((height<=16) && ((obstacle_pos>=16&&obstacle_pos<=32)||(obstacle_pos+obstacle_length>=16 && obstacle_pos+obstacle_length<=32)))deadflag=1;
	if(height<=0)KeyNum=Key();
	if(KeyNum==1 || height>0)
	{
		height=dinojump(0);
	}
	else dinorun();
}

const uint8_t close[]=
{
	3,2,1,1,1,1,2,3
};

void OLED_DeadAnimation(uint8_t newbest)//结算动画页面
{
	uint8_t i,j;
	if(Key()==4)reset=4;
	if(t==0)
	{	if(!Settlement)
		{
			for(i=0;i<8;i++)
			{
				OLED_SetCursor(i,0);
				for(j=0;j<128;j++)
				{
					OLED_Write_Data(0xFF);
					Delay_ms(close[i]);
				}
			}			
		}
		OLED_Clear();
		if(newbest==0)
		{
		OLED_ShowChinese(2,1,2,0);
		OLED_ShowChinese(2,2,3,0);
		OLED_ShowChinese(2,3,4,0);
		OLED_ShowString(2,7,"...",3,0);		
		}
		else 
		{
		OLED_ShowChinese(2,1,7,0);
		OLED_ShowChinese(2,2,8,0);
		OLED_ShowChinese(2,3,9,0);
		OLED_ShowString(2,7,"!!!",3,0);			
		}

		OLED_ShowString(7,2,"SC:",1,0);
		OLED_ShowNum(7,5,score,5,1);
		OLED_ShowDino(0,70);
		t++;
	}
}
void live(void)//游戏页面
{
	bostacle_refresh();
	loop_dead();
	Show_other();
	Speed=(score/30)+beingspeed;
	if(Speed>=speedmax)Speed=speedmax;
	Delay_ms(37-Speed);	
}
void die(void)//碰撞障碍后
{	
	uint8_t nowbest=0;
	if(score>Hs)nowbest=1;
	else nowbest=0;
	OLED_DeadAnimation(nowbest);	
	if(reset==4)
	{
		deadflag=0;
		height=0;
		obstacle(obstacle_ran,1);
		height=dinojump(1);
		t=0;
		reset=0;
		OLED_Clear();
		if(nowbest)Hs=score;
		score=0;
	}	
}

void Menu1(void)//返回游戏
{
	if(KeyNum==4)
		{
		mode=7;
		playflag=0;
		bmpflag=0;
		MenuShow=0;
		MenuSelect=0;
		menuclear=0;	
		OLED_Clear();
		}
}
void Menu2(void)//设置初始速度
{	
	OLED_ShowMenuChinese(1,1,4,0);OLED_ShowMenuChinese(1,2,5,0);OLED_ShowMenuChinese(1,3,6,0);OLED_ShowMenuChinese(1,4,7,0);//初始速度
	OLED_ShowNum(3,8,begingtemp,1,3);
	if(KeyNum==1){begingtemp++;begingtemp%=10;beingspeed=begingtemp*3;};
	if(KeyNum==4){Key4++;if(Key4>1){mode=7;Key4=0;}OLED_Clear();}
}
void Menu3(void)//设置速度上限
{
	OLED_ShowMenuChinese(1,1,8,0);OLED_ShowMenuChinese(1,2,9,0);OLED_ShowMenuChinese(1,3,10,0);OLED_ShowMenuChinese(1,4,11,0);
	OLED_ShowNum(3,8,speedtep,1,3);
	if(KeyNum==1){speedtep--;if(speedtep<=1)speedtep=1;speedmax=speedtep*4;}
	if(KeyNum==4){Key4++;if(Key4>1){mode=7;Key4=0;}OLED_Clear();}	
}
void Menu4(void)//蜂鸣器开关
{
	OLED_ShowMenuChinese(1,1,12,0);OLED_ShowMenuChinese(1,2,13,0);OLED_ShowMenuChinese(1,3,14,0);OLED_ShowMenuChinese(1,4,15,0);OLED_ShowMenuChinese(1,5,16,0);
	if(FMQswitch==0)
	{
		OLED_ShowString(3,7,"ON ",3,0);
	}
	else 
	OLED_ShowString(3,7,"OFF ",3,0);
	if(KeyNum==1){FMQswitch++;FMQswitch%=2;}
	if(KeyNum==4){Key4++;if(Key4>1){mode=7;Key4=0;}OLED_Clear();}	
}
void Menu5(void)//结算动画开关
{
	OLED_ShowMenuChinese(1,1,17,0);OLED_ShowMenuChinese(1,2,18,0);OLED_ShowMenuChinese(1,3,19,0);OLED_ShowMenuChinese(1,4,20,0);OLED_ShowMenuChinese(1,5,21,0);OLED_ShowMenuChinese(1,6,22,0);
	if(FMQswitch==0)
	{
		OLED_ShowString(3,7,"ON ",3,0);
	}
	else 
	{
	OLED_ShowString(3,7,"OFF",3,0);
	Settlement=~Settlement;
	}
	if(KeyNum==1){FMQswitch++;FMQswitch%=2;}
	if(KeyNum==4){Key4++;if(Key4>1){mode=7;Key4=0;}OLED_Clear();}	
}
void Menu6(void)//关机
{
	OLED_OFF();
}

void Menu(void)//菜单
{
	KeyNum=Key();
	if(KeyNum==2)
	{
		playflag=0;
		bmpflag=0;
	}
	if(menuclear==0)
	{
	OLED_Clear();menuclear++;
	}
	
	if(!MenuShow)
	{
		if(KeyNum==1)
		{	
			MenuSelect++;
			MenuSelect%=6;
			OLED_Clear();
		}
		OLED_ShowChinese(1,4,0,0);
		OLED_ShowChinese(1,5,1,0);
		switch(MenuSelect)
		{
		case 0:if(MenuSelect==0){
								OLED_ShowString(2,1,"1.",3,1);OLED_ShowMenuChinese(2,2,0,1);OLED_ShowMenuChinese(2,3,1,1);OLED_ShowMenuChinese(2,4,2,1);OLED_ShowMenuChinese(2,5,3,1);//返回游戏
								OLED_ShowString(3,1,"2.",3,0);OLED_ShowMenuChinese(3,2,4,0);OLED_ShowMenuChinese(3,3,5,0);OLED_ShowMenuChinese(3,4,6,0);OLED_ShowMenuChinese(3,5,7,0);//初始速度
								OLED_ShowString(4,1,"3.",3,0);OLED_ShowMenuChinese(4,2,8,0);OLED_ShowMenuChinese(4,3,9,0);OLED_ShowMenuChinese(4,4,10,0);OLED_ShowMenuChinese(4,5,11,0);//速度上限
								}
				else {OLED_ShowString(2,1,"1.",3,0);OLED_ShowMenuChinese(2,2,0,0);OLED_ShowMenuChinese(2,3,1,0);OLED_ShowMenuChinese(2,4,2,0);OLED_ShowMenuChinese(2,5,3,0);}break;//返回游戏}
		case 1:if(MenuSelect==1){
								OLED_ShowString(2,1,"1.",3,0);OLED_ShowMenuChinese(2,2,0,0);OLED_ShowMenuChinese(2,3,1,0);OLED_ShowMenuChinese(2,4,2,0);OLED_ShowMenuChinese(2,5,3,0);//返回游戏
								OLED_ShowString(3,1,"2.",3,1);OLED_ShowMenuChinese(3,2,4,1);OLED_ShowMenuChinese(3,3,5,1);OLED_ShowMenuChinese(3,4,6,1);OLED_ShowMenuChinese(3,5,7,1);//初始速度
								OLED_ShowString(4,1,"3.",3,0);OLED_ShowMenuChinese(4,2,8,0);OLED_ShowMenuChinese(4,3,9,0);OLED_ShowMenuChinese(4,4,10,0);OLED_ShowMenuChinese(4,5,11,0);//速度上限
								}
				else {OLED_ShowString(3,1,"2.",3,0);OLED_ShowMenuChinese(3,2,4,0);OLED_ShowMenuChinese(3,3,5,0);OLED_ShowMenuChinese(3,4,6,0);OLED_ShowMenuChinese(3,5,7,0);}break;//返回游戏}
		case 2:if(MenuSelect==2){
								OLED_ShowString(2,1,"1.",3,0);OLED_ShowMenuChinese(2,2,0,0);OLED_ShowMenuChinese(2,3,1,0);OLED_ShowMenuChinese(2,4,2,0);OLED_ShowMenuChinese(2,5,3,0);//返回游戏
								OLED_ShowString(3,1,"2.",3,0);OLED_ShowMenuChinese(3,2,4,0);OLED_ShowMenuChinese(3,3,5,0);OLED_ShowMenuChinese(3,4,6,0);OLED_ShowMenuChinese(3,5,7,0);//初始速度
								OLED_ShowString(4,1,"3.",3,1);OLED_ShowMenuChinese(4,2,8,1);OLED_ShowMenuChinese(4,3,9,1);OLED_ShowMenuChinese(4,4,10,1);OLED_ShowMenuChinese(4,5,11,1);//速度上限
								}
				else {OLED_ShowString(4,1,"3.",3,0);OLED_ShowMenuChinese(4,2,8,0);OLED_ShowMenuChinese(4,3,9,0);OLED_ShowMenuChinese(4,4,10,0);OLED_ShowMenuChinese(4,5,11,0);};break;//返回游戏}
		case 3:if(MenuSelect==3){
								OLED_ShowString(2,1,"4.",3,1);OLED_ShowMenuChinese(2,2,12,1);OLED_ShowMenuChinese(2,3,13,1);OLED_ShowMenuChinese(2,4,14,1);OLED_ShowMenuChinese(2,5,15,1);OLED_ShowMenuChinese(2,6,16,1);//蜂鸣器开关
								OLED_ShowString(3,1,"5.",3,0);OLED_ShowMenuChinese(3,2,17,0);OLED_ShowMenuChinese(3,3,18,0);OLED_ShowMenuChinese(3,4,19,0);OLED_ShowMenuChinese(3,5,20,0);OLED_ShowMenuChinese(3,6,21,0);OLED_ShowMenuChinese(3,7,22,0);//结算动画开关
								OLED_ShowString(4,1,"6.",3,0);OLED_ShowMenuChinese(4,2,23,0);OLED_ShowMenuChinese(4,3,24,0);//关机
								}
				else {OLED_ShowString(2,1,"4.",3,0);OLED_ShowMenuChinese(2,2,12,0);OLED_ShowMenuChinese(2,3,13,0);OLED_ShowMenuChinese(2,2,14,0);OLED_ShowMenuChinese(2,3,15,1);OLED_ShowMenuChinese(2,3,16,0);}break;
		case 4:if(MenuSelect==4){
								OLED_ShowString(2,1,"4.",3,0);OLED_ShowMenuChinese(2,2,12,0);OLED_ShowMenuChinese(2,3,13,0);OLED_ShowMenuChinese(2,4,14,0);OLED_ShowMenuChinese(2,5,15,0);OLED_ShowMenuChinese(2,6,16,0);//蜂鸣器开关
								OLED_ShowString(3,1,"5.",3,1);OLED_ShowMenuChinese(3,2,17,1);OLED_ShowMenuChinese(3,3,18,1);OLED_ShowMenuChinese(3,4,19,1);OLED_ShowMenuChinese(3,5,20,1);OLED_ShowMenuChinese(3,6,21,1);OLED_ShowMenuChinese(3,7,22,1);//结算动画开关
								OLED_ShowString(4,1,"6.",3,0);OLED_ShowMenuChinese(4,2,23,0);OLED_ShowMenuChinese(4,3,24,0);//关机
								}
				else {OLED_ShowString(3,1,"5.",3,0);OLED_ShowMenuChinese(3,2,17,0);OLED_ShowMenuChinese(3,3,18,0);OLED_ShowMenuChinese(3,4,19,0);OLED_ShowMenuChinese(3,5,20,0);OLED_ShowMenuChinese(3,6,21,0);OLED_ShowMenuChinese(3,7,22,0);}break;//结算动画开关
		case 5:if(MenuSelect==5){
								OLED_ShowString(2,1,"4.",3,0);OLED_ShowMenuChinese(2,2,12,0);OLED_ShowMenuChinese(2,3,13,0);OLED_ShowMenuChinese(2,4,14,0);OLED_ShowMenuChinese(2,5,15,0);OLED_ShowMenuChinese(2,6,16,0);//蜂鸣器开关
								OLED_ShowString(3,1,"5.",3,0);OLED_ShowMenuChinese(3,2,17,0);OLED_ShowMenuChinese(3,3,18,0);OLED_ShowMenuChinese(3,4,19,0);OLED_ShowMenuChinese(3,5,20,0);OLED_ShowMenuChinese(3,6,21,0);OLED_ShowMenuChinese(3,7,22,0);//结算动画开关
								OLED_ShowString(4,1,"6.",3,1);OLED_ShowMenuChinese(4,2,23,1);OLED_ShowMenuChinese(4,3,24,1);//关机
								}
				else {OLED_ShowString(4,1,"6.",3,0);OLED_ShowMenuChinese(4,2,23,0);OLED_ShowMenuChinese(4,3,24,0);}break;//关机
		}
	}
		if(KeyNum==4)
		{	
			if(ClearF==0)
			{
				ClearF++;
				OLED_Clear();
			}
			switch(MenuSelect)
			{
				case 0:mode=1;break;
				case 1:mode=2;break;
				case 2:mode=3;break;
				case 3:mode=4;break;
				case 4:mode=5;break;
				case 5:mode=6;break;
			}
		}		
				switch(mode)
			{
				case 1:Menu1();MenuShow=1;break;
				case 2:Menu2();MenuShow=1;break;
				case 3:Menu3();MenuShow=1;break;
				case 4:Menu4();MenuShow=1;break;
				case 5:Menu5();MenuShow=1;break;
				case 6:Menu6();MenuShow=1;break;
				case 7:MenuShow=0;break;
				default :break;
			}
}
int main(void)
{	
	Key_Init();
	OLED_Init();
	Buzzer_Init();
	end:
	while(1)
	{	
		if(playflag==0)
		{	
			if(bmpflag==0)
			{
			OLED_ShowBMP();
			bmpflag++;			
			}
			KeyNum=Key();
			if(KeyNum==4)
			{
				playflag=1;
				OLED_Clear();
			}
			if(KeyNum==2)
			{
				playflag=2;
			}
		}
		else if(playflag==1)
		{
			if(!deadflag){live();}else{die();goto end;}

		}
		else if(playflag==2)
		{
			Menu();
		}
	}
}



三、实验现象

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

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


联系作者

专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值