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

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下面写了一个极其简陋的!!!
zts329547875 回答时间: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
程序下载链接木有?
疯狂的土豆 回答时间:2018-10-10 16:55:48
楼主,想知道蛇头方向改变蛇身呈L或者类似矩形方波这些不规则的情况下蛇的移动部分的代码
Litthins 回答时间:2019-4-17 21:57:54
最近正在捣鼓446,等手头的事情告一段落也想试着搞一个

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版