基于stm32、0.96寸OLED实现的贪吃蛇小游戏(详细源码注释)

发布者:BlissfulCharm最新更新时间:2019-08-20 来源: eefocus关键字:stm32  96寸OLED  贪吃蛇小游戏 手机看文章 扫描二维码
随时随地手机看文章

简介:本实验基于stm32最小系统、0.96寸OLED(68*128)和摇杆实现一个经典的贪吃蛇小游戏。


硬件设计:

普通摇杆,0.96寸OLED 单色屏幕(SPI协议通讯),stc32f103c8t6最小系统开发板,如下所示。

器件齐全后,用杜邦线将摇杆和oled正确地连接到stm32开发板上,注意各个器件的电源需要接到同一电压,下图是接线说明:


 接好线之后,将源码编译下载,进入调试,正常运行如下图所示,如果屏幕出现花屏,那么将res引脚接到GND进行复位,再重新进行调试或单片机复位:


接着按下摇杆的中键就可以进入游戏:


屏幕的上方显示得分,通过摇杆控制蛇的运动方向。


游戏失败后可按下摇杆中键重新开始游戏。


代码设计: 

源代码下载解压后,利用keil4工具打开工程可看到:


上面已表明各个文件的作用, 可重点看Snake.c游戏设计文件。如果代码里面的注释是乱码,点击Edit->Configuration->Editor->Encoding->选择Chinese GB2312。下面面只列举部分代码说明。


main函数


int main(void)

{

  RCC_PCLK1Config(RCC_HCLK_Div4);

  USART1_Configuration(); //初始化串口

  TIME_Configuration(); //初始化定时器

  ADC_Configuration(); //初始化摇杆的ad采集

  OLED_Init(); //oled初始化默认参数

      GameReady(); //进入游戏准备界面

 

  Tick_Updata(&sysms);

      while (1){

  event=JoyState(); //获取摇杆的状态

  ret=Game_InputHandle(event);//蛇移动

  if(ret){ //ret=1 表示屏幕需刷新

GameMapToLcdCache(); //将像素从游戏图像gamemap位图经过放大后写进LcdCache显存

OLED_Updata();//将LcdCache[8][128]显存的数据发送到屏幕进行显示

sprintf(str,"Score=%d",GameScore);

OLED_DispString(0,0,str); //屏幕上方显示分数

  }

     }

}

main函数并不复杂,while循环里面不断获取摇杆状态,将状态传进Game_InputHandle函数进行游戏操作。


实现原理:


运用链表的特性,蛇的每一个节点就是链表的节点,节点的内容是该点的x,y坐标,如上图所示。遍历链表逐个读取蛇身的每个节点里面的x,y坐标,根据该坐标在屏幕上描点,即可描绘出蛇的形状来。


蛇的运动的原理是从蛇尾节点开始,其x,y坐标等于前一个节点的坐标,直至到头节点,头节点的新x,y坐标跟蛇运动的方向有关。每当蛇迟到食物时,尾部追加节点。


void GAME_NewSnake(SNAKELIST* SnakeList) //初始化链表,初始化蛇长度,4+1节

{

int x=4,y=15,i;//蛇的初始位置

SnakeList->x=x;

SnakeList->y=y++;

SnakeList->prev=SnakeList;

SnakeList->next=SnakeList;

for(i=0;i<4;i++){

GAME_SnakeListAddNode(SnakeList,x,y+i);

}

GAME_SnakeFillInGameMap(gamemap,SnakeList);

}

GAME_NewSnake游戏开始前,给蛇初始化5个节点,头节点在x=4,y=15处,其余4个节点在其下方。通过GAME_SnakeFillInGameMap函数将蛇在gamemap上描画出来。gamemap再放大映射到LCDcache显存里面去,再通过spi把整个屏幕的像素发送到屏幕进行显示。


void GAME_NewFood(unsigned char (*gamemap)[WIDTH]) //在地图上随机产生新的食物

{

unsigned int seed1,seed2;

int x,y;

while(1){

Tick_Updata(&seed1);

Tick_Updata(&seed2);

x=seed1%WIDTH;

y=seed2%HEIGHT;

if(gamemap[y][x]==0){

gamemap[y][x]=2;

break;

}

}

}

GAME_NewFood在地图上随机生成一个食物,当然这里的随机数,利用不断变化的时钟进行求余,得到的随机坐标后,先判断该左边是否可用,若是已经存在东西(蛇身或者边框)则继续获取随机数,如此反复直到得到一个空的的随机坐标。所以,当游戏玩到最后,蛇身很长的时候(界面没有多少空白点),产生食物的时间会长很多。


unsigned char Game_InputHandle(unsigned char event)//对输入按键事件的处理

{

unsigned char ret=0;

if(GameStatus==GAMEPAUSE&&event!=RESTART_EV){ //游戏状态未运行时,除非按下restart,否则不进入

return 0;

}

if(event==5-Snokedirection){//按下蛇前进的相反方向时,忽略

event=NON; 

}

switch(event){

case NON:

speed_max=200;

if(If_TimeOut(&speed_move,SPPED_MOVE)){ //自动前进

Tick_Updata(&speed_move);

    event=Snokedirection;

    }else{

break;

}

case TURN_LEFT_EV: //蛇向左移动

case TURN_RIGHT_EV://蛇向右移动

case TURN_DOWN_EV: //蛇向下移动

case TURN_UP_EV: //蛇向上移动

if(If_TimeOut(&speed_turn,speed_max)){

Tick_Updata(&speed_turn);

speed_max=150;

Snokedirection=event;

ret=GAME_SnakeMove(gamemap,&SnokeHeadNode,event,&GameScore);

printf("event=%drn",event);

}

break;

case RESTART_EV://游戏复位

if(If_TimeOut(&speed_restart,SPPED_RESTART_MAX)){

Tick_Updata(&speed_restart);

GameStatus=GAMERUNING;

GameScore=0;

    Snokedirection=TURN_UP_EV;

GAME_BackgroundInit(gamemap);

GAME_NewSnake(&SnokeHeadNode);

GAME_NewFood(gamemap);

ret=1;

printf("event=%drn",event);

}

  break;

default:

//error

break;

}

return ret;

}

Game_InputHandle函数在main函数里被调用,SPPED_MOVE这个宏是控制蛇自动移动的速度的,所设置的值越低则运动的越快。speed_max的值是控制手动移动的速度,当摇杆状态被持续维持为一个方向时,就会按照该速度进行前进。

关键字:stm32  96寸OLED  贪吃蛇小游戏 引用地址:基于stm32、0.96寸OLED实现的贪吃蛇小游戏(详细源码注释)

上一篇:stm32之电源管理(实现低功耗)
下一篇:基于stm32、0.96寸OLED实现的俄罗斯方块小游戏(详细源码注释

推荐阅读最新更新时间:2024-11-07 17:20

STM32-自学笔记(16.窗口看门狗,程序用到的库函数介绍)
1.RCC_APB1PeriphClockCmd 函数原型:void RCC_APB1PeriphClockCmd (u32 RCC_APB1Periph,FunctionalState NewState) 功能:使能或者失能APB1外设时钟 参数: RCC_APB1Periph:APB1的外设时钟 NewState:指定外设时钟的新状态,这个参数可以取ENABLE或者DISABLE 返回值:无 参数RCC_APB1Periph RCC_APB1Periph_TIM2 TIM2时钟 RCC_APB1Periph_I2C1 I2C1时钟 RCC_APB1Periph_TIM3 T
[单片机]
STM32破解的过程中常见的几个问题
STM32系列单片机都有全球唯一的ID号,很多设计开发者,在开发的过程中,会嵌入ID绑定验证代码,也就是所说的软加密。 STM32系列逆向分析 STM32系列单片机在破解的过程中常见的几个问题。 1通常我们在破解STM32过程中,如果原开发者没有嵌入软加密,那我们只需对芯片进行开片,去除加密锁,然后通过编程器直接读取,读取的BIN文件或HEX文件,完全可以正常使用。 2在去除加密锁后,提取的程序代码无法工作,存在软加密,很多软加密是通过烧录器选项来绑定ID的,这样的软加密比较简单,通常很快就能搞定。 3程序内部复杂的软加密,这样的情况也是很常见的,解密完后,检查没有发现ID绑定想象,但烧录新的单片机是无法工作的,这样的
[单片机]
STM32的Code/RO/RW/ZI区、Flash/Ram的占用情况、堆栈大小的设置
以cortex-M3为例,例如STM32F103 这篇文章要讲2个问题: 1、编译出的程序(指令)、变量的存放位置、大小? 2、在代码和keil中,“堆、栈”两者的大小如何设置? keil编译完成后,会有提示,形如: Program Size: Code=1148 RO-data=424 RW-data=20 ZI-data=1636 其中: ① Code为代码,本质上就是一大堆ARM指令; ② RO为只读的数据,例如,char *name = TOM ;//TOM三个字符就存放在ROM中作为RO-DATA;又如,为了减小sin的计算量,把sin的各个值直接制作成表,const float sinVal =
[单片机]
<font color='red'>STM32</font>的Code/RO/RW/ZI区、Flash/Ram的占用情况、堆栈大小的设置
STM32 | 一种简单、实用的测量程序运行时间的方法
前言 平时我们可能很少去关注程序运行的时间,但是在一些情况下可能需要对程序进行一个整体的复盘、优化。 那么,程序运行的时间就是一个可以考虑的方面,可以测一下某些代码块、函数、算法的运行时间,然后整体考虑看看有没有必要进行优化。 之前在某工控类项目中,我就有接到一个任务去测试程序中关键代码的执行时间,并输出报告。当时是使用一个GPIO+示波器进行测试的,也可以使用逻辑分析仪来测。 当时测量的方法很简单: 在要测试的代码块/函数之前设置该GPIO的电平为高电平,在要测试的代码块/函数之后设置该GPIO为低电平,使用示波器测高电平的时间,就知道了这一代码块/函数的运行时间。 下面就通过实例来介绍一下这种简单而有效的方法。
[单片机]
<font color='red'>STM32</font> | 一种简单、实用的测量程序运行时间的方法
STM32数模转换器的说明
使用STM32 micros的 模拟数字转换器(ADC) 后,接下来要处理的明显内部硬件模块是 数字到模拟转换器(DAC) 。顾名思义,该模块仅具有ADC的补充功能。它将数字二进制值转换为模拟电压输出。 DAC模块具有多种用途,包括音频生成,波形生成等。通常在大多数8位微控制器中,该模块不可用,并且 脉冲宽度调制(PWM)可以稍微满足其需求。 》 块。部分原因是由于它们的硬件资源和运行速度相对较低。所有STM32单片机都具有PWM模块,但大容量STM32也具有DAC模块。 STM32 DAC模块不是很复杂,并且在工作原理方面与ADC模块相似。下面的简化框图显示了STM32 DAC模块的主要组件。 再次请注意低密度STM32微处
[单片机]
<font color='red'>STM32</font>数模转换器的说明
readelf 命令读取 STM32 编译生成的 ELF 和 AXF 文件
1、概述 readelf 命令,一般用于查看 ELF 格式的文件信息,常见的文件如在Linux上的可执行文件,动态库(*.so)或者静态库(*.a) 等包含ELF格式的文件。 可以在 windows 命令行或 Git bash 上查看。 2、readelf 常用命令 语法:readelf (选项)(参数:文件),除了-v和-H之外,其它的选项必须有一个被指定参数。 Usage: readelf option(s) elf-file(s) Display information about the contents of ELF format files Options are: -a --all
[单片机]
STM32媒体分享会:业绩承压下,如何利用四大战略支柱撑起中国市场
日前,意法半导体(ST)公布了2024年一季度财报,其中MCU同比下降34.4%,环比下降25.3%,成为下降最多的部门。但正如ST CEO Jean-Marc Chery所说,其对未来充满信心,尤其是中国依然是一个关键的市场。“中国的市场状况其实并不复杂。虽然中国不再是一个飞速增长的市场,但仍然保持着强劲的增长势头。在这个市场中,ST面临的竞争非常激烈,不仅有来自本土企业的挑战,同样还有来自美国和日本的强劲对手。尽管如此,ST的核心竞争优势始终未变,那就是确保产品具备优秀的功能、出色的性能、可靠的质量以及合理的价格。” 就在财报发布前,ST在全球召开了STM32 Summit全球在线大会,并在中国召开了STM32媒体分享会,
[单片机]
<font color='red'>STM32</font>媒体分享会:业绩承压下,如何利用四大战略支柱撑起中国市场
STM32 CAN 波特率的确定
先看两份资料: (1),STM32 得到500Kb/s的波特率 CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; CAN_InitStructure.CAN_BS2=CAN_BS2_7tq; CAN_InitStructure.CAN_Prescaler=1; 每一位的Tq数目 = 1 (固定SYNC_SEG) + 8 (BS1) + 7 (BS2) = 16 如果CAN时钟是 8 MHz : (8M / 1 ) / 16 = 500K 其中: 1 为分频系数 16 为每一位的Tq数目 为了设置为 100K,
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved