weiqi7777

STM32实现2048游戏(二) 移植到STM32

0
阅读(5673)

    之前,用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,就显示画面了。  

           如下,就是图片数组的一部分。  

clip_image002  

           总的来说,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不复杂。  

           以下是游戏的截图。  

clip_image003  

clip_image004