STM32实现2048游戏(二) 移植到STM32
0赞之前,用c实现了2048,虽然有点小bug,关于这个bug,我的解决方法是,先将数据进行移位,保证非零的数据都在一边,这样,再合并数据就没有之前出现的那个bug了。
移植到SMT32也比较容易的,因为是用c代码写的,所以直接将代码移植过来就好了。然后封装一个函数,接收输入,对二位数组进行操作。封装这个函数,方便main函数调用。另外一个要注意的地方,在产生随机数字的时候,用到了srand(time(0)),在STM32中,是没有time(0)这个函数的。所以在产生随机种子的这个地方要更改下。
在程序中,我是使用数组的值来作为参数,产生随机种子的。而且产生随机数字,不像用上一次那样只用一个函数来实现了,是用4个函数来实现,每个函数使用的不同的数组的值作为参数。
u8 gennew_right() { u8 i; u8 j; u8 k=0; srand(pane[2][2]+pane[0][2]+pane[1][3]); while(1) { i=rand()%4; j=rand()%4; if(pane[i][j] == 0) { pane[i][j] = 2; break; } k++; if(k>200) break; } return 0; } u8 gennew_left() { u8 i; u8 j; u8 k=0; srand(pane[1][2]+pane[3][2]+pane[3][3]); while(1) { i=rand()%4; j=rand()%4; if(pane[i][j] == 0) { pane[i][j] = 2; break; } k++; if(k>200) break; } return 0; } u8 gennew_up() { u8 i; u8 j; int k=0; srand(pane[0][1]+pane[1][2]+pane[2][3]); while(1) { i=rand()%4; j=rand()%4; if(pane[i][j] == 0) { pane[i][j] = 2; break; } k++; if(k>200) break; } return 0; } u8 gennew_down() { u8 i; u8 j; u8 k=0; srand(pane[3][2]+pane[3][0]+pane[0][3]); while(1) { i=rand()%4; j=rand()%4; if(pane[i][j] == 0) { pane[i][j] = 2; break; } k++; if(k>200) break; } return 0; }
这个也是比较好理解的。对于封装的函数:
u8 game_process(u8 up, u8 down, u8 right, u8 left) { if( left ) { zuoyi(pane[0]); zuoyi(pane[1]); zuoyi(pane[2]); zuoyi(pane[3]); gennew_left(); return 1; } else if( right) { youyi(pane[0]); youyi(pane[1]); youyi(pane[2]); youyi(pane[3]); gennew_right(); return 1; } else if( up) { shangyi(0); shangyi(1); shangyi(2); shangyi(3); gennew_up(); return 1; } else if( down) { xiayi(0); xiayi(1); xiayi(2); xiayi(3); gennew_down(); return 1; } else { return 0; } }
其实就是根据输入的参数,来执行不同的操作,实际上就是改变数组的值。
最后一个关键的就是怎么在TFT上显示游戏画面。之前实现了在TFT上显示一副图片,利用这个,只要在不同的地方显示需要的图片,不就实现2048界面了。
首先是在网上找2048各个数值的图片,然后使用软件将图片的内容转换为数组。那接下来的工作就简单了,将数组的值发送给TFT,就显示画面了。
如下,就是图片数组的一部分。
总的来说,2048界面分为16个部分,每个部分是各个数值的图片。如0对应数值0的图片,64对应数值64的图片。因此要显示界面,就把每个部分的图片显示了,界面就有了。
来回顾下TFT显示数据,TFT显示数据,首先指定显示的窗口大小,再指定起始坐标,然后不断的发显示数据,那么数据就会依次的显示在TFT上了,这就实现了显示图片的效果了。
那么数据从什么地方来,当然就是从之前保存的数组中来了,但是数组是保存了所有图片的数据,所以显示的时候,要指定图片在数组中的起始位置。那么显示一个部分的程序就如下了:
void GUI_Dis2048Picture(u8 x, u16 y, u8 length, u16 high,u16 data) { u16 temp=0,tmp=0,num=0; u32 address=0; u16 i=data; switch(i) { case 0: address = 0; break; case 2: address = 1680; break; case 4: address = 1680*2; break; case 8: address = 1680*3; break; case 16: address = 1680*4; break; case 32: address = 1680*5; break; case 64: address = 1680*6; break; case 128: address = 1680*7; break; case 256: address = 1680*8; break; default: address = 0; } LCD_setwindow(x,y,x+length-1,y+high-1); num=length*high*2; do { //temp=pic[tmp]|( pic[tmp+1]<<8); temp=gImage[address+tmp+1]; temp=temp<<8; temp=temp|gImage[address+tmp]; LCD_WR_DATA(temp);//ÖðµãÏÔʾ tmp+=2; }while(tmp<num); }
首先通过判断显示的值是什么,得到数组的起始地址。然后根据输入的坐标以及图片的宽度和高度,设定窗口大小以及显示的坐标位置。然后就不断的输入值就好了。
还有一个东西要实现,就是按键的程序,因为要控制游戏,就需要输入,最简单的方式,就是通过按键输入。这部分程序,太简单,就不再说明了。
在主函数中,先判断按键是否输入,然后对输入进行处理,最后再显示界面。核心代码就是以下:
while(1) { while(1){ KEY_Scan(); ischange = game_process(up, down, right, left); left = 0; right =0; up =0; down =0; if(ischange) for(i=0; i<4; i++) for(j=0; j<4; j++) { GUI_Dis2048Picture(j*30, i*30, 30, 30,pane[i][j]); } ischange=0; if(isfailure()) { LCD_Clear(BLACK );//ÇåÆÁ for(i=0; i<4; i++) LCD_ShowBigNum4(30,30,0);//ÏÔʾËĸö30*60´óСµÄ×ÖÌå break; } if(iswin()) { LCD_Clear(BLACK );//ÇåÆÁ LCD_ShowBigNum4(30,30,2048);//ÏÔʾËĸö30*60´óСµÄ×ÖÌå break; } } }
当然,在程序开头,要定义数组,并赋初值。然后再定义几个全局变量。
u16 pane[4][4] = {2,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; u8 up=0,down=0,left=0,right=0;
总体来说,在STM32上实现2048不复杂。
以下是游戏的截图。