STM32F446+OLED12864做贪吃蛇游戏

二维码是我创建的QQ群,欢迎新朋友加入。

闲暇之余发现看了下OLED12864的数据手册,发现他的显示在Y轴上只有页写,也就是一次写8个点。

突然想到,如果自己程序需要精准定位到某个点,那这不是会很艹蛋么?去网上搜索,基本上都是页写的代码,也就是在Y轴上的定位只能是0~7.

于是花了点时间,做了个贪吃蛇的游戏,写了段程序。

程序硬件支持:
STM32F446R+OLED12864+按键

软件结构:
1.DMA跑SPI刷屏
2.贪吃蛇游戏算法
3.重新定义OLED显示方式

底层驱动就不说,DMA配置,跑SPI数据。

我先做了个二位数组,存放64*128个点,初始值为0;
uint8_t OLED_Display_Data[8][128]

之后开个定时器,每隔一段时间跑一次屏幕
                if(HardwareParamter.TimingOLED>=Refresh_Time && !HardwareParamter.OLEDFlash_flag)
                {
                        HardwareParamter.TimingOLED = 0;
                        Display_Process(OLED_Display_Data);        
                }


基本想法就是,不停的跑这个数组,数组就是屏幕的每个点。

贪吃蛇算法做的简单:
首先是一个结构体,存放相关参数

typedef struct {
        uint8_t food_x;      //食物横坐标
        uint8_t food_y;      //食物纵坐标

        uint8_t gameEsc;     //游戏开始暂停
        uint8_t gameSpeed;   //游戏速度
        uint8_t gameLevel;   //游戏难度
        
        uint8_t x[39];
        uint8_t y[39];
        uint8_t node;        //蛇的节数
        uint8_t direction;   //蛇头方向
}GameParamter_t;


两个核心函数:移动和创建食物
食物依赖于随机数生成函数
//    需要出现新食物
uint8_t createNewFood(void)
{
        uint8_t i;
        uint8_t size = GameParamter.node;
        uint8_t flag = TRUE;                         //    标记创建的新事物与贪吃蛇的身体冲突
        srand(HardwareParamter.TimingVal);
        GameParamter.food_x = rand() % MAP_H;
        GameParamter.food_y = rand() % MAP_L;
        
        //    食物的坐标必须为3的倍数才会在显示屏先被显示
        for (; GameParamter.food_x % DOT_H != 0; ++GameParamter.food_x) {      
                        ;
        }
        
        for (; GameParamter.food_y % DOT_L != 0; ++GameParamter.food_y) {       
                        ;
        }
        
        for (i = 0; i < size; ++i) {
                        if (GameParamter.food_x == GameParamter.x[i] && GameParamter.food_y == GameParamter.y[i]) {
                                        flag = FALSE;
                                        break;
                        }
        }    

        return flag;
}


移动就是简单的数据加减
//    贪吃蛇移动
void move(void)
{
        uint8_t i;

        if(GameParamter.gameEsc)
        {
                //    将蛇从最后个节点向前一个节点移动
                for(i = GameParamter.node - 1; i > 0; i--) {                    
                                GameParamter.x[i] = GameParamter.x[i - 1];
                                GameParamter.y[i] = GameParamter.y[i - 1];
                }
                
                //    根据此时贪吃蛇的方向,设置蛇头的位置            
                switch(GameParamter.direction)    
                {                  
                        case RIGHT: 
                                        GameParamter.x[0] += DOT_H;
                                        break;
                        case LEFT: 
                                        GameParamter.x[0] -= DOT_H;
                                        break;
                        case UP: 
                                        GameParamter.y[0] -= DOT_L;
                                        break;
                        case DOWN: 
                                        GameParamter.y[0] += DOT_L;
                                        break;
                }
        }
}

显示部分随时更新
uint8_t temp;
        
        switch(State_Flag)
        {
                case Snake_Move:
                        //清除蛇尾部
                        for(temp = 0;temp < GameParamter.node;temp++)
                                Oled_Dot(GameParamter.x[temp],GameParamter.y[temp],0);
                        
                        //移动蛇
                        move();
                        
                        //显示蛇的位置
                        for(temp = 0;temp < GameParamter.node;temp++)
                                Oled_Dot(GameParamter.x[temp],GameParamter.y[temp],1);
                        
                        //吃到食物,创建新的食物
                        if(GameParamter.food_x == GameParamter.x[0] && GameParamter.food_y == GameParamter.y[0])
                                Oled_food();
                        
                        if(GameParamter.x[0] >= MAP_H || GameParamter.y[0] >= MAP_L)
            {
                                OLEDClear();
                                OLED_ShowString(((128 - ((strlen("GAME")*10)))>>1),2,"GAME");
                                OLED_ShowString(((128 - ((strlen("OVER")*10)))>>1),5,"OVER");
                                State_Flag = Game_Over;
                                HardwareParamter.OLEDFlash_flag = 1;
                        }
                break;
                case Game_Over:

                break;
                default:
                        OLEDClear();
                        State_Flag = Snake_Move;
                  HardwareParamter.OLEDFlash_flag = 0;
                break;
        }


外带一个按键处理,解决方向和暂停重置问题。

1.png (110.68 KB, 下载次数: 0)

1.png

N$TC_KA52ICSCU3@IQJ~OBQ.png (77.09 KB, 下载次数: 0)

N$TC_KA52ICSCU3@IQJ~OBQ.png
收藏

猜你喜欢

转载自blog.csdn.net/jun626/article/details/79279591