二维码是我创建的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; }
外带一个按键处理,解决方向和暂停重置问题。
|
|