STM32之俄罗斯方块
STM32之俄罗斯方块
1.硬件平台
- STM32开发板
- 3.5寸LCD屏(16位并口8080时序)
- 字库存储W25Q64(SPI)
- 4个按键
2.示例效果
3.软件设计
3.1 绘制单个方块函数
/*************绘制单个方块**************/void Lcd_DrawDiamond(u16 x,u16 y,u16 c){ u16 i; LcdWriteReg(0x2A);//设置x坐标 LcdWriteData((x>>8)&0xff);//x坐标高8位 LcdWriteData(x&0xff);//x坐标低8位 LcdWriteData(((x+8)>>8)&0xff);//x坐标高8位 LcdWriteData((x+8)&0xff);//x坐标低8位 LcdWriteReg(0x2B);//设置Y坐标 LcdWriteData((y>>8)&0xff);//Y坐标高8位 LcdWriteData(y&0xff);//Y坐标低8位 LcdWriteData(((y+8)>>8)&0xff);//Y坐标高8位 LcdWriteData((y+8)&0xff);//Y坐标低8位 LcdWriteReg(0x2C);//设置x坐标 for(i=0;i<9*9;i++)LcdWriteData(c);}
3.2 清空一行显示
/******************消除一行*******************/void Lcd_ClearOneLineDisplay(u16 y,u16 c){ u16 i=0; for(i=2;i<LCD_WIDTH-98;i+=10) { Lcd_DrawDiamond(i,y,c); }}
3.3 定义屏幕大小数组,保存方块图形掉落位置状态信息,显示区域宽度为220,高度为480
u8 shape_place_stat[49][24]={ {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//第一行y=0的状态信息 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//第二行y=10的状态信息 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=20 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=30 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=40 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=50 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=200 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=300 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=400 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=460 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},//y=470 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},//最后一行为状态 };
3.4 更新当前状态到二维数组中
/*更新一个状态到二维数组中*/void Lcd_Refreshbuff(u16 x,u16 y,u8 stat){ shape_place_stat[y/10][x/10+1]=(stat&0x01);}
3.5 设置每个方块种类颜色,绘制各个方块
/*每一个种类的颜色*//*1 -- DARKBLUE --Drawshape_color[0]2,3 -- BRRED --Drawshape_color[1]4,5,6,7 -- BLUE --Drawshape_color[2]8,9,10,11,12,13,14,15 -- GRAY --Drawshape_color[3]16,17,18,19 --BLACK -- Drawshape_color[4]*/const u16 Drawshape_color[]={DARKBLUE,BRRED,BLUE,GRAY,BLACK};/*******************绘制一个俄罗斯方块*****************************形参:x,y -- 要显示的位置**what --要绘制的方块序号(1~19)** c --方块颜色**stat --更新到二维数组中的状态(0表示清除,1表示写入状态)*******************************************************************/void Lcd_Drawshape(u16 x,u16 y,u8 what,u16 c,u8 stat){switch (what){case 1:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y+10,stat);}break;case 2:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+20,y,c); Lcd_DrawDiamond(x+30,y,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+20,y,stat); Lcd_Refreshbuff(x+30,y,stat);}break;case 3:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x,y+20,c); Lcd_DrawDiamond(x,y+30,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x,y+20,stat); Lcd_Refreshbuff(x,y+30,stat);}break;case 4:{ Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+20,y+10,c); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+20,y+10,stat);}break;case 5:{ Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x,y+20,c); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x,y+20,stat);}break;case 6:{ Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+10,y+20,c); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+10,y+20,stat);}break;case 7:{ Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+20,y,c); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+20,y,stat); }break;case 8:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x,y+20,c); Lcd_DrawDiamond(x+10,y+20,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x,y+20,stat); Lcd_Refreshbuff(x+10,y+20,stat);}break;case 9:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+20,y,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+20,y,stat);}break;case 10:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+10,y+20,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+10,y+20,stat);}break;case 11:{ Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+20,y+10,c); Lcd_DrawDiamond(x+20,y,c); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+20,y+10,stat); Lcd_Refreshbuff(x+20,y,stat);}break;case 12:{ Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+10,y+20,c); Lcd_DrawDiamond(x,y+20,c); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+10,y+20,stat); Lcd_Refreshbuff(x,y+20,stat);}break;case 13:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+20,y,c); Lcd_DrawDiamond(x+20,y+10,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+20,y,stat); Lcd_Refreshbuff(x+20,y+10,stat);}break;case 14:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x,y+20,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x,y+20,stat);}break;case 15:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+20,y+10,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+20,y+10,stat);}break;case 16:{ Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x,y+20,c); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x,y+20,stat);}break;case 17:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+20,y+10,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+20,y+10,stat);}break;case 18:{ Lcd_DrawDiamond(x,y,c); Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+10,y+20,c); Lcd_Refreshbuff(x,y,stat); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+10,y+20,stat);}break;case 19:{ Lcd_DrawDiamond(x,y+10,c); Lcd_DrawDiamond(x+10,y+10,c); Lcd_DrawDiamond(x+10,y,c); Lcd_DrawDiamond(x+20,y,c); Lcd_Refreshbuff(x,y+10,stat); Lcd_Refreshbuff(x+10,y+10,stat); Lcd_Refreshbuff(x+10,y,stat); Lcd_Refreshbuff(x+20,y,stat);}break;}}
3.6 方块移动和切换方向
/******************向下移动*****************/int Lcd_DownMove(u16 x,u16 y,u16 what,u16 c){ Lcd_Drawshape(x,y,what,WHITE,0); Lcd_Drawshape(x,y+10,what,c,1); return y+10;}/***************向左移动*********************/int Lcd_LeftMove(u16 x,u16 y,u16 what,u16 c){ Lcd_Drawshape(x,y,what,WHITE,0); Lcd_Drawshape(x-10,y,what,c,1); return x-10;}/****************向右移动********************/int Lcd_RightMove(u16 x,u16 y,u16 what,u16 c){ Lcd_Drawshape(x,y,what,WHITE,0); Lcd_Drawshape(x+10,y,what,c,1); return x+10;}/**************************改变图形***************/u8 Lcd_Changshape(u16 x,u16 y,u16 what,u16 c){ u8 stat;switch(what){case 1:stat=1;break;case 2:{if(shape_place_stat[(y+40)/10][x/10] || shape_place_stat[(y+30)/10][x/10] || shape_place_stat[(y+20)/10][x/10] || shape_place_stat[(y+10)/10][x/10]){stat=2;break;}Lcd_Drawshape(x,y,2,WHITE,0);Lcd_Drawshape(x,y,3,c,1);stat=3;break;} case 3:{if(shape_place_stat[(y+40)/10][(x+40)/10]){stat=3;break;}Lcd_Drawshape(x,y,3,WHITE,0);Lcd_Drawshape(x,y,2,c,1);stat=2;break;} case 4:{Lcd_Drawshape(x,y,4,WHITE,0);Lcd_Drawshape(x,y,5,c,1);stat=5;break;} case 5:{Lcd_Drawshape(x,y,5,WHITE,0);Lcd_Drawshape(x,y,6,c,1);stat=6;break;} case 6:{if(shape_place_stat[y/10][(x+30)/10]){stat=6;break;}Lcd_Drawshape(x,y,6,WHITE,0);Lcd_Drawshape(x,y,7,c,1);stat=7;break;} case 7:Lcd_Drawshape(x,y,7,WHITE,0);Lcd_Drawshape(x,y,4,c,1);stat=4;break; case 8:{if(shape_place_stat[y/10][(x+30)/10]){stat=8;break;}Lcd_Drawshape(x,y,8,WHITE,0);Lcd_Drawshape(x,y,9,c,1);stat=9;break;} case 9:{if(shape_place_stat[(y+30)/10][x/10]){stat=9;break;}Lcd_Drawshape(x,y,9,WHITE,0);Lcd_Drawshape(x,y,10,c,1);stat=10;break;} case 10:{if(shape_place_stat[y/10][(x+30)/10]){stat=10;break;}Lcd_Drawshape(x,y,10,WHITE,0);Lcd_Drawshape(x,y,11,c,1);stat=11;break;} case 11:{if(shape_place_stat[(y+30)/10][x/10]){stat=11;break;}Lcd_Drawshape(x,y,11,WHITE,0);Lcd_Drawshape(x,y,8,c,1);stat=8;break;} case 12:{if(shape_place_stat[(y)/10][(x+30)/10] || shape_place_stat[(y+20)/10][x/10] || shape_place_stat[(y+20)/10][(x+30)/10]){stat=12;break;}Lcd_Drawshape(x,y,12,WHITE,0);Lcd_Drawshape(x,y,13,c,1);stat=13;break;} case 13:{if(shape_place_stat[(y+30)/10][x/10]){stat=13;break;}Lcd_Drawshape(x,y,13,WHITE,0);Lcd_Drawshape(x,y,14,c,1);stat=14;break;} case 14:{if(shape_place_stat[y/10][(x+30)/10]){stat=14;break;}Lcd_Drawshape(x,y,14,WHITE,0);Lcd_Drawshape(x,y,15,c,1);stat=15;break;} case 15:{if(shape_place_stat[(y+30)/10][x/10]){stat=15;break;}Lcd_Drawshape(x,y,15,WHITE,0);Lcd_Drawshape(x,y,12,c,1);stat=12;break;} case 16:{if(shape_place_stat[y/10][(x+30)/10]){stat=16;break;}Lcd_Drawshape(x,y,16,WHITE,0);Lcd_Drawshape(x,y,17,c,1);stat=17;break;} case 17:{Lcd_Drawshape(x,y,17,WHITE,0);Lcd_Drawshape(x,y,16,c,1);stat=16;break;} case 18:{if(shape_place_stat[y/10][(x+30)/10]){stat=18;break;}Lcd_Drawshape(x,y,18,WHITE,0);Lcd_Drawshape(x,y,19,c,1);stat=19;break;} case 19:{Lcd_Drawshape(x,y,19,WHITE,0);Lcd_Drawshape(x,y,18,c,1);stat=18;break;}} return stat;}
3.7 判断是否到达边界
/*判断状态*/u8 Lcd_Shape_GetStat(u16 x,u16 y){//printf("x=%d,y=%d\r\n",x,y);//printf("stat=%d\r\n",shape_place_stat[y/10][x/10+1]); if(shape_place_stat[y/10][x/10+1])return 1; else return 0; }//每个方块高度 //1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9const u8 shape_high[19]={2,1,4,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2};//保存每个方块宽度 //1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9const u8 shape_widht[19]={2,4,1,3,2,2,3,2,3,2,3,2,3,2,3,2,3,2,3};/****************判断是否到到达下边界***************/u8 Lcd_Shape_GetLowerBoundary(u16 x,u16 y,u8 cnt){ switch (cnt){ case 1: { if(shape_place_stat[(y+20)/10][x/10+1])return 1; else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; } break; case 2: { if(shape_place_stat[(y+10)/10][x/10+1])return 1; else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3; else if(shape_place_stat[(y+10)/10][(x+30)/10+1])return 4; } break; case 3: { if(shape_place_stat[(y+40)/10][x/10+1])return 1; } break; case 4: { if(shape_place_stat[(y+20)/10][x/10+1])return 1; else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3; } break; case 5: { if(shape_place_stat[(y+30)/10][x/10+1])return 1; else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; } break; case 6: { if(shape_place_stat[(y+20)/10][x/10+1])return 1; else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2; } break;case 7:{ if(shape_place_stat[(y+10)/10][x/10+1])return 1; else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2;else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3;}break; case 8: { if(shape_place_stat[(y+30)/10][x/10+1])return 1; if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 1; } break; case 9: { if(shape_place_stat[(y+20)/10][x/10+1])return 1; else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3; } break; case 10: { if(shape_place_stat[(y+10)/10][x/10+1])return 1; else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2; } break; case 11: {if(shape_place_stat[(y+20)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3; } break; case 12: { if(shape_place_stat[(y+30)/10][x/10+1])return 1; else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2;} break; case 13: { if(shape_place_stat[(y+10)/10][x/10+1])return 1; else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3; } break; case 14: { if(shape_place_stat[(y+30)/10][x/10+1])return 1; else if(shape_place_stat[(y+10)/10][(x+10)/10+1])return 2;} break; case 15: {if(shape_place_stat[(y+20)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 3; } break; case 16: {if(shape_place_stat[(y+30)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; } break; case 17: {if(shape_place_stat[(y+10)/10][x/10+1])return 1;else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+20)/10][(x+20)/10+1])return 2; } break; case 18: { if(shape_place_stat[(y+20)/10][x/10+1])return 1; else if(shape_place_stat[(y+30)/10][(x+10)/10+1])return 2; } break; case 19: { if(shape_place_stat[(y+20)/10][x/10+1])return 1; else if(shape_place_stat[(y+20)/10][(x+10)/10+1])return 2; else if(shape_place_stat[(y+10)/10][(x+20)/10+1])return 3; } break;} return 0; }
3.8 将上一行方块放到当前行
/******************将上一行方块放到当前行************************/static void Lcd_ClearOneLine(u8 line){ u8 i=1; for(i=1;i<23;i++) { if(shape_place_stat[line][i])Lcd_DrawDiamond((i-1)*10+2,line*10,BLACK);else Lcd_DrawDiamond((i-1)*10+2,line*10,WHITE);//shape_place_stat[line][i]=shape_place_stat[line-1][i]; }}
3.9 判断得分,消行,清除方块在二维数组状态
/***********得分判断*********************/u8 Lcd_GetMark(u8 *buff){ int i,j,k; u8 cnt=0;//保存要消除的行数 int line=0; /*判断当前最高位置*/ for(i=47;i>=0;i--)//高度 { for(j=1;j<23;j++)//每一行的方格数 { if(shape_place_stat[i][j])break; } if(j==23) { line=i;//记录当前方块有多少行 break; } }//printf("line=%d\r\n",line);if(line<=1)return 0xff;//游戏结束 for(i=47;i>line;i--) { for(j=0;j<24;j++) { if(shape_place_stat[i][j]==0)break; } if(j==24)buff[cnt++]=i;//记录哪一行需要消除 } /*得分,消行*/ if(cnt) { for(i=0;i<cnt;i++) { Lcd_ClearOneLineDisplay(buff[i]*10,RED);/*清除一行*/ } Delay_Ms(500); for(i=0;i<cnt;i++) { Lcd_ClearOneLineDisplay(buff[i]*10,WHITE);/*清除一行*/ } /*将方块往下移动*/for(k=cnt-1;k>=0;k--){for(j=buff[k];j>=line;j--){for(i=0;i<24;i++){shape_place_stat[j][i]=shape_place_stat[j-1][i];}}line--;} for(i=buff[0];i>=line;i--) { Lcd_ClearOneLine(i); } }if(cnt==0)cnt=0;else if(cnt==1)cnt=1;//消除1行得1分else if(cnt==2)cnt=4;//消除2行得4分else if(cnt==3)cnt=8;else if(cnt==4)cnt=16; return cnt; }/*清空图形掉落位置状态信息*/void Lcd_Clearshape(void){int i,j;for(i=0;i<48;i++){for(j=1;j<23;j++){shape_place_stat[i][j]=0;}}}
3.10 窗口绘制
/*******************************绘制显示窗口**************************/void Lcd_TetrisShowWind(void){ LCD_DrawLine(LCD_WIDTH-97, 0, LCD_WIDTH-97, LCD_HIGHT,BLACK);//画直线 LCD_DrawLine(LCD_WIDTH-96, 0, LCD_WIDTH-96, LCD_HIGHT,BLACK);//画直线LCD_DrawLine(LCD_WIDTH-96, 170, LCD_WIDTH-1, 170,BLACK);LCD_DrawLine(LCD_WIDTH-96, 171, LCD_WIDTH-1, 171,BLACK); LCD_Display_Str(LCD_WIDTH-96+25,30,24,(u8 *)"NEXT",DARKBLUE);//显示字符串 LCD_Display_Str(LCD_WIDTH-96+25,200,16,(u8 *)"得 分",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+96/2-12,200+30,24,(u8 *)"0",RED);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,320,16,(u8 *)"旋转 KEYUP ",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,360,16,(u8 *)"暂停 KEY1",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,400,16,(u8 *)"左 KEY2 ",DARKBLUE);//显示字符串LCD_Display_Str(LCD_WIDTH-96+10,440,16,(u8 *)"右 KEY0",DARKBLUE);//显示字符串}
4.主函数
#include "stm32f10x.h"#include "beep.h"#include "led.h"#include "key.h"#include "delay.h"#include "usart.h"#include "w25q64.h"#include "timer.h"#include #include "nt35310.h"#include "tetris_game.h"#include int main(){ u8 buff[49]; u8 stat=1; int x0=112,y0=0; u16 cnt=1,cnt2=0; u8 key;u16 mark=0,res,mark2=0;u16 color;//方块颜色 u16 i=200; Beep_Init(); Led_Init(); Key_Init();//按键初始化TIMx_Init(TIM4,7200,65535); Usartx_Init(USART1,115200,72); printf("串口初始化完成\r\n"); W25Q64_Init(); LCD_Init();AA:LCD_Clear(WHITE);//清屏函数 Lcd_TetrisShowWind(); cnt=rand()%20; if(cnt==0)cnt=1;cnt2=rand()%20;if(cnt2==0)cnt2=1;Lcd_Drawshape(LCD_WIDTH-96+35,80,cnt2,BLACK,0);/*俄罗斯方块示例图*/// for(i=1;i<=19;i++)// {//if(i==1)color=Drawshape_color[0];//else if(i>=2 && i<=3)color=Drawshape_color[1];//else if(i>=4 && i<=7)color=Drawshape_color[2];//else if(i>=8 && i<=15)color=Drawshape_color[3];//else if(i>=16 && i<=19)color=Drawshape_color[4];// Lcd_Drawshape(x0,y0,i,color,0);//绘制图形// x0+=50;// if(x0>=260)// {// x0=50;// y0+=50;// }// } while(1) { key=Key_Getval(); if(key==3)//暂停 { stat=!stat; }else if((key==1) && stat)//切换方向 { i=0;if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4]; cnt=Lcd_Changshape(x0,y0,cnt,color); } else if((key==2) && stat)//右 { if(Lcd_Shape_GetStat(x0+shape_widht[cnt-1]*10,y0)==0) {if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4]; x0=Lcd_RightMove(x0,y0,cnt,color); } } else if((key==4) && stat)//左 { if(x0>=10) { if(Lcd_Shape_GetStat(x0-10,y0)==0){if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4]; x0=Lcd_LeftMove(x0,y0,cnt,color);} } } if(i>=100 && stat) { i=0;if(cnt==1)color=Drawshape_color[0];else if(cnt>=2 && cnt<=3)color=Drawshape_color[1];else if(cnt>=4 && cnt<=7)color=Drawshape_color[2];else if(cnt>=8 && cnt<=15)color=Drawshape_color[3];else if(cnt>=16 && cnt<=19)color=Drawshape_color[4]; y0=Lcd_DownMove(x0,y0,cnt,color);//向下 if(Lcd_Shape_GetLowerBoundary(x0,y0,cnt))// {res=Lcd_GetMark(buff);if(res==0xff){mark=0;res=0;LCD_Display_Str(LCD_WIDTH/2-9*12,230,24,(u8 *)"GAME OVER",RED);LCD_Display_Str(LCD_WIDTH/2-9*12-20,265,16,(u8 *)"请按任意键重新开始!",RED);while(1){key=Key_Getval();if(key){Lcd_Clearshape();goto AA;}}}mark+=res;if(mark2!=mark){mark2=mark;snprintf((char *)buff,sizeof(buff),"%02d",mark2);LCD_Display_Str(LCD_WIDTH-94,230,24,(u8 *)"",WHITE);//显示字符串LCD_Display_Str(LCD_WIDTH-94+96/2-strlen((char *)buff)*12,230,24,buff,RED);//显示字符串}// printf("得分:%d\r\n",mark); x0=112,y0=0;Lcd_Drawshape(LCD_WIDTH-96+35,80,cnt2,WHITE,0);cnt=cnt2;cnt2=rand()%20;if(cnt2==0)cnt2=1;Lcd_Drawshape(LCD_WIDTH-96+35,80,cnt2,BLACK,0); } } Delay_Ms(1); i++; }}
5.完整工程
完整工程示例:https://download.csdn.net/download/weixin_44453694/84079602