【STM32单片机】打砖块游戏设计


一、主要功能

1、TFTLCD显示游戏
2、按键控制板子移动方向
3、得分关卡显示
4、游戏结束,一键重启


二、使用步骤

系统运行后,TFTLCD触摸屏显示游戏界面,通过按键KEY2和KEY0控住左右方向。当小球打到砖块且接住小球时,分数加10。当游戏结束后可按任意键重新回到游戏主界面。

三、硬件资源

1.硬件准备

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

2.硬件连接

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

四、软件设计

1.软件结构

在这里插入图片描述

2.主要代码

主要代码如下:

//游戏界面行列数
#define START_X		10
#define START_Y		50

//砖块宽
#define ZK_WIDTH	30
//砖块高
#define ZK_HEIGHT	20

//板子宽
#define BZ_WIDTH	100
//板子高
#define BZ_HEIGHT	5

//横着的砖块数
#define COLS	10
//竖着的砖块数
#define ROWS	5

//窗口宽
#define WINDOW_WIDTH	(ZK_WIDTH*COLS)
//窗口高
#define WINDOW_HEIGHT	320

//球半径
#define RADIUS	5

//球移动像素
#define SPACE 	5

//板子移动像素
#define BZ_SPACE 	10


//砖块类型
struct ZK
{
	//左上角点坐标
	int x,y;
	//砖块宽高
	int w,h;
	u16 color;
	
	u8 isLive;//是否存在
};

//板子类型
struct BZ
{
	//左上角点坐标
	int x,y;
	//板子宽高
	int w,h;
	u16 color;
};

//球类型
struct Ball
{
	//圆心坐标
	int x,y;
	//半径
	int radius;
	u16 color;
	
	int xfx,yfx;//移动数据
	//xfx为正往右  为负往左
	//yfx为正往下  为负往上
};

//描述砖块的数组
struct ZK zk[ROWS][COLS];

struct BZ bz;

struct Ball ball;

u8 isContinue=1;

//游戏参数
u8 glevel=1;//游戏关卡
u32 gscore=0;//游戏得分



//随机数种子
u32 gtime_cnt=0;

//不同数字的颜色
u16 gcolor[12]={BLACK,BLUE,BRED,GRED,GBLUE,RED,MAGENTA,GREEN,CYAN,YELLOW,
			  BROWN,BRRED,};


//初始化球
void initBall()
{
	ball.radius=RADIUS;
	ball.x=WINDOW_WIDTH/2+START_X;
	ball.y=WINDOW_HEIGHT-BZ_HEIGHT-RADIUS+START_Y;
	ball.color=BLUE;
	
	ball.xfx=SPACE;
	ball.yfx=-SPACE;
	
}

//板子初始化
void initBz()
{
	bz.w=BZ_WIDTH;
	bz.h=BZ_HEIGHT;
	bz.color=RED;
	bz.x=(WINDOW_WIDTH-BZ_WIDTH)/2+START_X;
	bz.y=WINDOW_HEIGHT-BZ_HEIGHT+START_Y;
}

//初始化砖块
void initZk()
{
	int i,j;
	for(i=0;i<ROWS;i++)
	{
		for(j=0;j<COLS;j++)
		{
			zk[i][j].x=j*ZK_WIDTH+START_X;
			zk[i][j].y=i*ZK_HEIGHT+START_Y;
			
			zk[i][j].w=ZK_WIDTH;
			zk[i][j].h=ZK_HEIGHT;
			
			zk[i][j].color=gcolor[rand()%12];
			zk[i][j].isLive=1;//砖块存活
		}
	}
}

//初始化游戏,所有在开始时候执行一次的
void initGame()
{
	srand(gtime_cnt);//设置随机算子
	//1、做窗口
	LCD_DrawRectangle_Color(START_X,START_Y,START_X+WINDOW_WIDTH,START_Y+WINDOW_HEIGHT,WHITE);
	initZk();
	initBz();
	initBall();
	isContinue=1;
	
	drawAllZk();
	drawBz();
	drawBall();
}

//所有界面显示相关
void showGame()
{
	LCD_DrawRectangle_Color(START_X,START_Y,START_X+WINDOW_WIDTH,START_Y+WINDOW_HEIGHT,WHITE);
	drawBz();
	drawBall();
	LCD_ShowxNum(START_X+32*3,WINDOW_HEIGHT+START_Y+60,gscore,5,32,0);
}

//所有游戏控制相关
void ctolGame()
{
	ball_move();
	check();
	keyCtol();
}


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

//打砖块游戏设计
void app_demo(void)
{
	u8 key=0;
	
	BEEP_Init();
	KEY_Init();
	LED_Init();
	TIM4_Init(500-1,7200-1);  //定时50ms
//	My_EXTI_Init();
	TFTLCD_Init();
	TP_Init();
START:
	gscore=0;
	LCD_Clear(BACK_COLOR);
	LCD_ShowPicture(0,(tftlcd_data.height-240)/2,320,240,(u8 *)gImage_picture);
	LCD_ShowFontHZ((tftlcd_data.width-32*5)/2,10,"打砖块游戏");
	while(1)
	{
		key=KEY_Scan(0);
		if(key!=0)break;
	}
	LCD_Clear(BACK_COLOR);
	LCD_ShowFontHZ((tftlcd_data.width-32*5)/2,10,"打砖块游戏");
	LCD_ShowFontHZ(START_X,WINDOW_HEIGHT+START_Y+20,"关卡:");
	LCD_ShowNum(START_X+32*3,WINDOW_HEIGHT+START_Y+20,glevel,1,32);
	LCD_ShowFontHZ(START_X,WINDOW_HEIGHT+START_Y+60,"得分:");
	LCD_ShowNum(START_X+32*3,WINDOW_HEIGHT+START_Y+60,gscore,5,32);
	
	initGame();
	
	while(isContinue)
	{
		showGame();
		ctolGame();
	}
	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)
	{
		key=KEY_Scan(0);
		if(key!=0)goto START;
	}
}


五、实验现象

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

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

联系作者

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

TC编写 main() { int mode=VGAHI,driver=VGA; char ch; unsigned int l; int i,gi,gj,j,flag=1;/*i,j是循环变量,flag是标记变量,-1:向x负半轴移动,+1:向x正半轴移动*/ double qx,qy,k,b=0.0,speech=0.4,x,y; double r=2.0,bx=60.0,byy=270.0; double pianx=100.0,piany=100.0,tx=20.0,ty=10.0,jx=2.0,jy=2.0; int mx=0,my=0,mb,sum;/*sum纪录砖块的数目*/ FILE * p; if((p = fopen("record.dat", "r")) == NULL) { p=fopen("record.dat","w"); fprintf(p,"0 0 0 0 0\n"); rewind(p); } fclose(p); initgraph(&driver,&mode,"C:\\tc"); setbkcolor(BLUE); Msinit(); Setmouse((int)(pianx+1+bx/2),(int)((tx+jx)*8+pianx-1-bx/2),(int)byy+piany,(int)byy+piany); star: cleardevice();/*程序重载的介入点*/ setcolor(RED); outtextxy(30,20,"^_^ Welcome to Play Hitting Brick Game! ^_^"); sum=0; qx=100.0+pianx-10;qy=180.0+pianx-10;k=0.33; setcolor(7); rectangle((int)(pianx-2),(int)(piany-2),(int)((tx+jx)*8+2+pianx),302+piany); setcolor(1); rectangle((int)(pianx-1),(int)(piany-1),(int)((tx+jx)*8+1+pianx),301+piany); /*读取盘面情况*/ p=fopen("record.dat", "r"); for(i=0;i<5;i++) fscanf(p,"%x ",&zhuan[i]); fclose(p); /*画砖块*/ for(i=0;i<5;i++) { l=1; for(j=0;j<16;j++) { if((zhuan[i]&l)==0) { Draw((int)((jx+tx)*((16*i+j)%8)+pianx+jx),(int)((jy+ty)*((int)((16*i+j)/8))+piany+jy),(int)tx,(int)ty); sum+=1; } l=l*2; } } gotoxy(5,4); printf("Press any key to start game...Q key to quit..."); ch=getch(); if(ch=='q'||ch=='Q') quitgame(); else { gotoxy(5,4); printf(" "); } for(;;) { setfillstyle(1, 0); bar(mx-bx/2,my,mx+bx/2,my+5); Msread(&mx, &my, &mb); Draw(mx-bx/2,my,bx,5); setcolor(0); mycircle(qx,qy,r,0); /*判断求是否反弹*/ if(qx-r<=pianx+1 || qx+r>=(tx+jx)*8+pianx-1) { flag=-flag; k=-k; } if(qy-r<=piany+1) k=-k; for(gi=0;gi<5;gi++) { l=1; for(gj=0;gj<16;gj++) { if((zhuan[gi]&l)==0) { j=(16*gi+gj)/8; i=(16*gi+gj)%8; x=(jx+tx)*i+jx+tx/2+pianx; y=(jy+ty)*j+jy+ty/2+piany; /*边判断1*/ if(qy>=y-ty/2 && qy<=y+ty/2 &&(pow(qx+r-x+tx/2,2)<1 || pow(qx-r-x-tx/2,2)<1)) { flag=-flag; k=-k; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } else /*边判断2*/ if(qx>=x-tx/2 && qx<=x+tx/2 &&(pow(qy+r-y+ty/2,2)<1 || pow(qy-r-y-ty/2,2)<1)) { k=-k; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } else /*角判断*/ if(pow(qx-x+tx/2,2)+pow(qy-y+ty/2,2)<=r*r || pow(qx-x-tx/2,2)+pow(qy-y+ty/2,2)<=r*r || pow(qx-x+tx/2,2)+pow(qy-y-ty/2,2)<=r*r || pow(qx-x-tx/2,2)+pow(qy-y-ty/2,2)<=r*r) { flag=-flag; zhuan[gi]=zhuan[gi]|l; sum-=1; if(sum==0) wingame(); setfillstyle(1, 0); bar((jx+tx)*i+pianx+jx,(jy+ty)*j+piany+jy,(jx+tx)*i+pianx+jx+tx,(jy+ty)*j+piany+jy+ty); } } l=l*2; } } /*棍棒的反弹*/ if(qx<=mx+bx/2 && qx>=mx-bx/2 && pow(qy+r-my,2)<1) { k=-(k/pow(k*k,0.5))*(0.3*bx/(pow(pow(qx-mx,2),0.5)+0.000001)); } if((int)(qy+r)>my+0.5) { gotoxy(5,5); printf("You have lost the game!Press any key to restart..."); getch(); goto star; } b=qy-qx*k; if(flag==1) qx=qx+speech/pow(1.0+k*k,0.5); if(flag==-1) qx=qx-speech/pow(1.0+k*k,0.5); qy=qx*k+b;/*计算球心坐标*/ setcolor(14); mycircle((int)qx,(int)qy,r,14); delay(1); if(mb==1) { gotoxy(5,5); printf("You have lost the game!Press any key to restart..."); getch(); goto star; } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值