你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F446+OLED12864跑贪吃蛇游戏

[复制链接]
不吃肉的羊 发布时间:2018-2-7 14:16
闲暇之余发现看了下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
N$TC_KA52ICSCU3@IQJ~OBQ.png
收藏 1 评论7 发布时间:2018-2-7 14:16

举报

7个回答
MrJiu 回答时间:2018-2-7 15:17:28
说起贪吃蛇,以前在大学的时候,学完数据结构,然后就在dos下面写了一个极其简陋的!!!
西点钟灵毓秀 回答时间:2018-2-7 22:21:36
可以试试
hello_bug 回答时间:2018-2-8 08:14:23
有点意思。楼主有时间放个视频上来看看。
zero99 回答时间:2018-2-12 14:17:18
感谢分享,已汇总到2月技术原创  https://www.stmcu.org.cn/module/forum/thread-614799-1-1.html
gdyn2 回答时间:2018-8-21 16:22:06
程序下载链接木有?
xuetudou 回答时间:2018-10-10 16:55:48
楼主,想知道蛇头方向改变蛇身呈L或者类似矩形方波这些不规则的情况下蛇的移动部分的代码
Litthins 回答时间:2019-4-17 21:57:54
最近正在捣鼓446,等手头的事情告一段落也想试着搞一个
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版