|
闲暇之余发现看了下OLED12864的数据手册,发现他的显示在Y轴上只有页写,也就是一次写8个点。 突然想到,如果自己程序需要精准定位到某个点,那这不是会很艹蛋么?去网上搜索,基本上都是页写的代码,也就是在Y轴上的定位只能是0~7. 于是花了点时间,做了个贪吃蛇的游戏,写了段程序。 ( m y7 R+ M0 O4 p% K1 U 程序硬件支持: STM32F446R+OLED12864+按键 软件结构: 1.DMA跑SPI刷屏2 F9 T7 r9 e, ^; U 2.贪吃蛇游戏算法 3.重新定义OLED显示方式 9 G9 t! z/ h! E 底层驱动就不说,DMA配置,跑SPI数据。 我先做了个二位数组,存放64*128个点,初始值为0;4 |2 U" |+ |& G# c+ V, w- U uint8_t OLED_Display_Data[8][128]+ s0 D! W1 F5 p( y4 f 之后开个定时器,每隔一段时间跑一次屏幕 if(HardwareParamter.TimingOLED>=Refresh_Time && !HardwareParamter.OLEDFlash_flag)- I0 |* } L6 X9 h5 P- j { HardwareParamter.TimingOLED = 0;# J; m0 i% k5 b+ ^- M' ? Display_Process(OLED_Display_Data); & D a6 _: p- H } 基本想法就是,不停的跑这个数组,数组就是屏幕的每个点。 贪吃蛇算法做的简单:- _- _8 ?9 Y9 n) H o 首先是一个结构体,存放相关参数 typedef struct {! {. |" E+ s! k3 X uint8_t food_x; //食物横坐标 uint8_t food_y; //食物纵坐标# ^4 F6 {7 {1 d6 I z+ D : H$ k: o2 o* C7 u. F$ r uint8_t gameEsc; //游戏开始暂停 uint8_t gameSpeed; //游戏速度" T6 ]' l# T# f6 R. e( j% b3 p uint8_t gameLevel; //游戏难度, \! N8 b* y$ ?, ?. E 5 B( n' [9 U) }+ T* b uint8_t x[39];4 Q8 Y! W# \3 f! @; }/ E uint8_t y[39]; uint8_t node; //蛇的节数 uint8_t direction; //蛇头方向- w- D/ a1 A/ V5 J! T. [/ f }GameParamter_t; 3 H# [& y. s* M- _( g 两个核心函数:移动和创建食物 食物依赖于随机数生成函数! A1 W# L) y1 ]) R# b) { // 需要出现新食物 uint8_t createNewFood(void)3 A" {9 Z/ P v {3 {. c( f8 h3 B% R5 y uint8_t i; uint8_t size = GameParamter.node; uint8_t flag = TRUE; // 标记创建的新事物与贪吃蛇的身体冲突 srand(HardwareParamter.TimingVal);$ l" S" t; e5 A6 P; S A, w# i% ^ GameParamter.food_x = rand() % MAP_H;9 \! U1 k% ^0 A+ l O& G( z, P8 K GameParamter.food_y = rand() % MAP_L;) f- z7 ~6 I* s. N" V$ ]$ ~7 @ ! s8 G U' R9 n t% d# G // 食物的坐标必须为3的倍数才会在显示屏先被显示! a' M6 m* M* k: @$ g1 I% ? for (; GameParamter.food_x % DOT_H != 0; ++GameParamter.food_x) { ; }- d, A# s& M$ u; z2 e 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;/ C3 B6 E; w# l! \8 T2 Z break; } } ) V7 [2 g7 c" v return flag; }, X" z+ |2 j6 c6 ]) r 移动就是简单的数据加减; j; b0 b% s, ^' Z( U3 M2 |4 g // 贪吃蛇移动 void move(void) {$ J# Q$ }1 T s9 ` U7 b' c% [2 N2 m uint8_t i; if(GameParamter.gameEsc) { // 将蛇从最后个节点向前一个节点移动. L- X/ o/ B0 Q* b; d for(i = GameParamter.node - 1; i > 0; i--) { GameParamter.x[i] = GameParamter.x[i - 1]; GameParamter.y[i] = GameParamter.y[i - 1]; }' B# t) |& s0 F+ v) r3 K3 W // 根据此时贪吃蛇的方向,设置蛇头的位置 8 y# [' \# _5 a4 O, n switch(GameParamter.direction) { 1 N% R, v9 P! q: K4 D, P0 W case RIGHT: GameParamter.x[0] += DOT_H; break; case LEFT: GameParamter.x[0] -= DOT_H;" C- M/ S6 v' F3 A7 ?: v- h1 ? break;: }- x3 h( I2 ` case UP: GameParamter.y[0] -= DOT_L;* ]4 Z* ^2 w- s' d) b& h2 R2 k7 Y# \ break;3 G; t/ i5 q1 y$ P; Y- a case DOWN: GameParamter.y[0] += DOT_L; break; }6 X2 L7 h3 h8 I& q: _+ j: w' N } } * r7 k6 L+ G8 [ K# O/ K' |. F 显示部分随时更新: {/ R( i! p" D/ k& E3 } uint8_t temp; # s0 ~/ e" j8 D6 h2 n! t5 T switch(State_Flag) {$ T, _5 S: O5 y: Q" B& u* j case Snake_Move: //清除蛇尾部 n+ y6 C& l b" P$ f; `; n; }! g: y for(temp = 0;temp < GameParamter.node;temp++) Oled_Dot(GameParamter.x[temp],GameParamter.y[temp],0); " @9 ]! u4 d6 w, b% ]9 o; U$ \/ h //移动蛇 move(); + ~5 @3 E4 d. O/ p$ T: n( r //显示蛇的位置 for(temp = 0;temp < GameParamter.node;temp++)6 ^7 e/ B* S1 O. | Oled_Dot(GameParamter.x[temp],GameParamter.y[temp],1);" v6 n7 P1 N6 B; \- ^% |2 q4 J9 K //吃到食物,创建新的食物 if(GameParamter.food_x == GameParamter.x[0] && GameParamter.food_y == GameParamter.y[0]) Oled_food();' S) o9 K. R, [* t: o if(GameParamter.x[0] >= MAP_H || GameParamter.y[0] >= MAP_L) {$ b, `7 {2 t, T9 U/ V OLEDClear(); OLED_ShowString(((128 - ((strlen("GAME")*10)))>>1),2,"GAME");( }# e3 p& N# |% I' g* B) x1 e/ V } W1 } OLED_ShowString(((128 - ((strlen("OVER")*10)))>>1),5,"OVER");& Q+ c! [5 G' h+ H+ l State_Flag = Game_Over; HardwareParamter.OLEDFlash_flag = 1;! f4 Y' A- e, P' I& b1 B2 ] }" T6 a* H Q9 c" r" y8 Y( o break;1 }) o. I u# d. p case Game_Over: break;" m9 Q$ j& e& P default:' K4 D; H! m! w v OLEDClear(); State_Flag = Snake_Move; HardwareParamter.OLEDFlash_flag = 0; break; } 4 x2 ^/ S9 e7 F6 G) T$ g9 j8 s% n8 J 外带一个按键处理,解决方向和暂停重置问题。5 I' I+ Z$ y7 J' I. G 9 E& n: U- y. R9 E |
说起贪吃蛇,以前在大学的时候,学完数据结构,然后就在dos下面写了一个极其简陋的!!!![]() ![]() |
可以试试 |
| 有点意思。楼主有时间放个视频上来看看。 |
| 感谢分享,已汇总到2月技术原创 https://www.stmcu.org.cn/module/forum/thread-614799-1-1.html |
| 程序下载链接木有? |
| 楼主,想知道蛇头方向改变蛇身呈L或者类似矩形方波这些不规则的情况下蛇的移动部分的代码 |
最近正在捣鼓446,等手头的事情告一段落也想试着搞一个 |
【福利三:雨露均沾·逢7狂欢】之四:用一个定时器同步另外两个定时器输出PWM
【逢7发帖赢大礼】STM32开发之WIFI实时时钟
【逢7发帖赢大礼】STM32开发之指纹识别!
【逢7发帖赢大礼】STM32开发之环境空气质量监测
【逢7发帖赢大礼】STM32开发之人体实时运动信息监测!
【逢7发帖赢大礼】STM32开发之IC门禁卡UID读取方法!
【逢7发帖赢大礼】全网最简单的Arduino_STM32开发环境搭建教程!
STM32F4中文用户手册
STM32F400、STM32F402 Cortex-M4超值单片机
SPI 高温读错最后一位?STM32F42xx 官方根治方案
微信公众号
手机版