STM32F446+OLED12864做贪吃蛇游戏

2023-11-06

上面是我的微信和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

收藏

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F446+OLED12864做贪吃蛇游戏 的相关文章

  • 处理器指令周期执行时间

    我的猜测是 no operation 内在 ARM 指令应花费 1 168 MHz 来执行 前提是每个NOP在一个时钟周期内执行 我想通过文档验证这一点 有关处理器指令周期执行时间的信息是否有标准位置 我试图确定 STM32f407IGh6
  • 初始化 ST-Link 设备时出错 - 无法连接到设备

    我目前正在使用 ST Link 调试器对我的 STM32F3 Discovery 板进行编程 我使用的IDE是Atollic TrueStudio 5 5 2 现在我面临一个非常奇怪的问题 那就是我不断收到消息 初始化 ST Link 设备
  • 在地址“0xXXXXXX”处中断,没有可用的调试信息,或在程序代码之外

    配置 使用 Nucleo L476RG 使用 GNU ARM Eclipse 我从 STM32CubeMX 生成了一个极简代码 我已经在我的板载 ST Link 中刷新了 J link 驱动程序 一直在尝试为我的代码运行调试器 但我的程序计
  • 优化 ARM Cortex M3 代码

    我有一个 C 函数 它尝试将帧缓冲区复制到 FSMC RAM 这些函数将游戏循环的帧速率降低至 10FPS 我想知道如何分析反汇编的函数 我应该计算每个指令周期吗 我想知道CPU把时间花在哪里 在哪个部分 我确信该算法也是一个问题 因为它的
  • 137-基于stm32单片机智能保温杯控制装置Proteus仿真+源程序

    资料编号 137 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DS18B20传感器 电机 制作一个基于stm32单片机智能保温杯控制装置Proteus仿真 2 通过DS18b20传感器检测当前保温杯水的温度 并且
  • Push_back() 导致程序在进入 main() 之前停止

    我正在为我的 STM32F3 Discovery 板使用 C 进行开发 并使用 std deque 作为队列 在尝试调试我的代码 直接在带有 ST link 的设备上或在模拟器中 后 代码最终在 main 中输入我的代码之前在断点处停止 然
  • 匹配 STM32F0 和 zlib 中的 CRC32

    我正在研究运行 Linux 的计算机和 STM32F0 之间的通信链路 我想对我的数据包使用某种错误检测 并且由于 STM32F0 有 CRC32 硬件 并且我在 Linux 上有带有 CRC32 的 zlib 所以我认为在我的项目中使用
  • STM32超声波——HC_SR04

    文章目录 一 超声波图片 二 时序图 三 超声波流程 四 单位换算 五 取余计算 六 换算距离 七 超声波代码 一 超声波图片 测量距离 2cm 400cm 二 时序图 1 以下时序图要先提供一个至少10us的脉冲触发信号 告诉单片机我准备
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • 硬件基础-电容

    电容 本质 电容两端电压不能激变 所以可以起到稳定电压作用 充放电 电容量的大小 想使电容容量大 使用介电常数高的介质 增大极板间的面积 减小极板间的距离 品牌 国外 村田 muRata 松下 PANASONIC 三星 SAMSUNG 太诱
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 在 Atollic TrueStudio、STM32CubeMX 中导入 C 库

    我目前正在开发 STM32F767ZI Nucleo 板和一个小安全芯片 microchip atecc508a 通过 i2c 连接进行连接 该芯片有一个可用的库加密验证库 https github com MicrochipTech cr
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • Cortex-M3与M4权威指南

    处理器类型 所有的ARM Cortex M 处理器是32位的精简指令集处理器 它们有 32位寄存器 32位内部数据路径 32位总线接口 除了32位数据 Cortex M处理器也可以有效地处理器8位和16位数据以及支持许多涉及64位数据的操作
  • STM32 上的 ADC 单次转换

    我正在研究 STM32 F103x 上的 ADC 编程 并从最简单的情况 单次转换开始 测量内部温度传感器 连接到 ADC1 的值 并使用 USART 将其发送到 COM 端口 目标似乎很明确 但是当我尝试将源代码下载到闪存时 它不会向 C
  • 当端点和 PMA 地址均更改时,CubeMX 生成的 USB HID 设备发送错误数据

    我正在调试我正在创建的复合设备的问题 并在新生成的仅 CubeMX 代码中重新创建了该问题 以使其更容易解决 我添加了少量代码main 让我发送 USB HID 鼠标点击 并在按下蓝色按钮时使 LED 闪烁 uint8 t click re
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能

随机推荐

  • 论文笔记之ST-GCN

    通过将图卷积网络扩展到时空图模型 设计了一种 用于动作识别的骨架序列 的通用表示 AAAI 2018 录用 论文地址 https arxiv org abs 1801 07455 1 摘要 动态人体骨架模型带有进行动作识别的重要信息 传统的
  • git clone项目报错,The requested URL returned error: 500

    git clone项目报错 The requested URL returned error 500 如何解决 试试修改电脑中存储的账号密码 有项目权限 至少在网页上能通过链接访问当前Git内容 曾在当前电脑登录过git账号 满足以上两种情
  • flutter 保存列表状态和控制列表状态

    class DiscoverActivePageState extends State
  • vue中列表渲染相关知识(v-for)

    普通的列表使用ul包含多个li实现 这样往往不够灵活 在原生js中能够动态渲染列表具体实现如下 ul ul 我们再看看vue中如何实现列表渲染的 b b
  • 微信小程序获取当前位置 地图定位导航-详细代码

    小程序获取当前位置 回到当前位置 地图定位 导航 效果 因为小程序更新了获取地理位置API接口 需要先在app json中配置一下permission字段 不然会报微信小程序getLocation 需要在app json中声明permiss
  • 扩展欧几里得算法

    扩展欧几里得算法是啥 那就要先知道什么是欧几里得算法 欧几里得算法 扩展欧几里得算法是欧几里得算法的推广 利用欧几里得算法的思想和递归求得贝祖等式a x b y gcd a b 不定方程中的一组x和y的解 原理如下 设a gt b 当b 0
  • Coqui TTS 安装与测试

    前言 本篇记录一下 Coqui TTS 的安装 Coqui TTS 的主要作者是德国人 这个库似乎之前和 Mozilla 的 TTS https github com mozilla TTS 有千丝万缕的关系 但是现在后者的 TTS 已经停
  • 2021年江苏省职业院校技能大赛中职 “网络信息安全”赛项(超详细)

    2021年中职组 网络空间安全 赛项 一 江苏省竞赛任务书 二 任务书解析 三 不懂的可以私信博主 一 江苏省竞赛任务书 一 竞赛时间 8 00 11 00 共计3小时 二 竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第 阶段
  • [附源码]计算机毕业设计Python课程在线测评系统(程序+源码+LW文档)

    该项目含有源码 文档 程序 数据库 配套开发软件 软件安装教程 项目运行 环境配置 Pychram社区版 python3 7 7 Mysql5 7 HBuilderX list pip Navicat11 Django nodejs 项目技
  • 一文理解pytorch张量概念和tensor的三种创建方式!

    1 张量是什么 张量是一个多维数组 它是标量 向量 矩阵的高维拓展 1 1 Variable Variable是 torch autograd中的数据类型 主要用于封装 Tensor 进行自动求导 data 被包装的Tensor grad
  • 超实用的IDEA插件推荐,百万级下载量

    超实用的30多款idea插件 有百万级下载量的优秀插件 你值得拥有 好的工具助你事半功倍 快速协助敲出更漂亮更有效率的代码 搬运工这里收集了很不错的IDEA插件 相信你一定会喜欢的 必备插件列表 Grep Console 自定义控制台输出格
  • C#常用代码

    最近学习用C 写了几个程序 记录一下常用的几个操作 方便以后Copy 文件操作 FileStream fs null try byte buf FileStream fs new FileStream strSampleFileName F
  • Ubuntu16.04下opencv2与ROSkinetic中自带opencv3不兼容问题总结

    1 背景 从ROSindigo换到ROSkinetic ROSkinetic中自带的opencv3 与原来indigo中opencv2不一样 所以原来的涉及opencv的程序都出了问题 最近这两天就一直在改兼容性 清明节最后一天了 总结一下
  • WebStorm2016.2 注册码及激活,2018.6.14亲测有效

    License server激活 这可能是最简单的了 在激活框 选择 License server 输入 http idea iteblog com key php 2018 6 14可用
  • table自定义表格的封装

    前言 对原生的table进行封装 让他满足我们一行显示不同个的需求 实现效果 如图所示 一行显示不同数量的内容 实现代码 1 封装的组件 custom table vue 源码看下面 1 一行显示几个td 2 表头数据 表格数据 3 js封
  • 深度学习python图像标记工具labelTool

    深度学习训练需要标记图像位置和类别 之前用的时候是叫做BBox Label Tool master 遇到大图像就显示不完整了 没有自适应缩放 这是改进后的Python脚本 目录结构 图片目录名images 标签目录名labels 图像目录下
  • JDK 新特性篇:JDK 8 新特性详解

    Java8新特性简介 Java 8 又称为 JDK 1 8 是 Java 语言开发的一个主要版本 Java 8 是 Oracle 公司于 2014 年 3 月发布 可以看成是自 Java 5 以来最具革命性的版本 Java 8 为 Java
  • 函数重载和缺省参数

    函数重载 C 允许在同一作用域类声明几个功能类似的同名函数 但是这些同名函数的形式参数 指参数的个数 类型或者顺序 必须不同 也就是说用同一个运算符完成不同的运算功能 函数重载必须是参数的个数或者类型不同 与返回值无关 在C语言当中是不支持
  • 李宏毅机器学习——梯度下降详细讲解

    文章目录 梯度下降 1 学习率 1 1自适应学习率 1 2 Adagrad算法 2 随机梯度下降 3 特征缩放 3 1 特征缩放原因 3 2 特征缩放方法 4 梯度下降的限制 梯度下降 梯度下降是为了解决回归方程中参数的最优化问题 即表现为
  • STM32F446+OLED12864做贪吃蛇游戏

    上面是我的微信和QQ群 欢迎新朋友的加入 闲暇之余发现看了下OLED12864的数据手册 发现他的显示在Y轴上只有页写 也就是一次写8个点 突然想到 如果自己程序需要精准定位到某个点 那这不是会很艹蛋么 去网上搜索 基本上都是页写的代码 也