用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验

使用了STM32CubeMX及Keil(HAL库)
材料:stm32开发板、0.96寸OLED模块(ssd1306 12864 SPI)、4×4矩阵键盘、杜邦线、st-link


实验原理:

1、 OLED通过SPI2显示游戏画面(使用了某商家驱动,包括oled.c、oled.h、oledfont.h)

2、 矩阵键盘实现按键事件判断(只用矩阵键盘行2、行3)
S11(上:w) S12( 下:s) S8( 左:a) S16( 右:d) S4( 确认:o)

3、贪吃蛇游戏的原理是普通的贪吃蛇游戏的算法

实验设计:


PA4 PA5 PA6 PA7输出低电平 
PC4 PC5为下降沿触发外部中断,并且设置为上拉   
一行中有按键按下则触发中断,进行消抖,然后把一行中4个按键对应的PA依次置为高电平,检测4个按键中哪个按键被按下

具体按图连接
用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第1张图片

OLED按照下图连

用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第2张图片








关于游戏:

蛇的最大长度为36个方块


关于贪吃蛇游戏画面:
1、 标题界面(实现在play和help之间循环选择)
左边64×64部分为标题,右边64×64部分为菜单
2、 帮助界面
提供帮助信息
3、 游戏界面
左边64×64部分为游戏显示,右边64×64部分为分数显示
左边64×64部分留了宽度为4像素的空白,以及宽度为4像素的围墙

蛇由方块(8×8像素,填充部分为6×6像素)组成,撑满围墙内需要36块食物为一个方块(8×8像素,填充部分为2×2像素)


关于这个的贪吃蛇游戏的规则:

初始长度为3,方向为右
每秒移动1个长度单位(匀速)
通过按键,方向可以改变为蛇前进方向的左边或右边(有bug,在往新方向移动之前)
随机生成食物
吃到食物长度+1
碰到墙壁或身体结束游戏(失败)
【长度达到最长长度结束游戏(成功?)


实验过程:
1、测试OLED基本功能

商家给的驱动没有图片显示,于是写了个简单粗暴的图片显示函数,定义在oled.c里,顺便在oled.h中声明(图片取模后就存在一个数组里。。。我放在了oledfont.h里)

//画图

void OLED_PIC1616(const unsigned char pic[][16]){
	int i,j,k,temp;
	for(i=0;i<64;i++){
		for(j=0;j<16;j++){
			temp=pic[i][j];
			for(k=0;k<8;k++){
				OLED_DrawPoint(j*8+k,i,temp&0x80); //写好的设置单个像素是否填充的函数
				temp=temp<<1;

			}
		}
	}
	
}


图片取模方式如下(至于阴码、阳码,根据具体的效果来选):

用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第3张图片


原图(阳码):


显示效果:

用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第4张图片
2、测试矩阵键盘的功能
出现了按键时的抖动、释放可能多次触发了中断的问题

3、写代码测试

修复了一些bug







STM32CubeMX中的设置:

用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第5张图片

用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第6张图片

用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第7张图片




主要代码(以下只有USER CODE BEGIN里的代码):
/* USER CODE BEGIN Includes */
#include "oled.h"
#include 
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
extern const unsigned char pic1[][16]; //title图片
extern const unsigned char pic2[][16]; //lose图片
extern const unsigned char pic3[][16]; //win图片
const uint16_t gpio[]={GPIO_PIN_4,GPIO_PIN_5,GPIO_PIN_6,GPIO_PIN_7};
const char key5[]={'d','s','a','o'}; //d:right a:left w:up s:down o:ok
uint8_t scene=0; //0:title 1:help 2:game
uint8_t select=0; //0:run game 1:run help
uint8_t length=3; //蛇的长度
//以下坐标都是方块左上角坐标
uint8_t head_x=32; //头部方块x坐标
uint8_t head_y=24; //头部方块y坐标
uint8_t snake_x[36]={32,24,16}; //身体方块x坐标
uint8_t snake_y[36]={24,24,24}; //身体方块y坐标
uint8_t direction='d'; //方向
uint8_t food=1;//判断食物存在
uint8_t food_x;//食物x坐标
uint8_t food_y;//食物y坐标
char score[3];//分数(长度)【用于打印】
/* USER CODE END PV */

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
void draw_food(void);
void draw_score(void);
void generateFood(void);
void snake_init(void);
uint8_t game(void);
void init_title(void);
/* USER CODE END PFP */

 /* USER CODE BEGIN 2 */
	__HAL_SPI_ENABLE(&hspi2);
	OLED_Init();//初始化OLED      
	srand(1);
	init_title();
  /* USER CODE END 2 */

/* USER CODE BEGIN 3 */
		
 if(scene==2){
	uint8_t flag;
	 snake_init();
	 while(1){            //游戏循环
		 HAL_Delay(1000);
		 flag=game();
		 if(flag==0){
			 OLED_PIC1616(pic2);
			 HAL_Delay(5000);
			 init_title();
			 scene=0;
			 break;
		 }
			else if(flag==2){
				OLED_PIC1616(pic3);
				HAL_Delay(5000);
				init_title();
				scene=0;
				break;
			 }
		 
		 
	 }
 }
  }
  /* USER CODE END 3 */

/* USER CODE BEGIN 4 */
//画出标题界面
void init_title(void){  
	OLED_Clear();
	OLED_PIC1616(pic1);
	OLED_ShowString(64,4,"play",16);
	OLED_ShowString(64,24,"help",16);
	OLED_ShowString(104,20*select+4,"<-",16);
}



//画食物
void draw_food(void){
	
	OLED_Fill(food_x+3,food_y+3,food_x+5,food_y+5,1);
}




//写分数
void draw_score(void){
		sprintf(score,"%d",length);
		OLED_ShowString(64,24,score,16);
}


//生成食物坐标
void generateFood(void){
	int i;
	do{
		food_x=8*(rand()%6)+8;
		food_y=8*(rand()%6)+8;
		for(i=0;i=0;i--){
		snake_x[i+1]=snake_x[i];
		snake_y[i+1]=snake_y[i];
	}
		snake_x[0]=head_x;
		snake_y[0]=head_y;
	
	//撞身判断
	for(i=1;i


实验成果:




用STM32F103RCT6+0.96寸OLED模块(ssd1306 12864 SPI)+4×4矩阵键盘实现贪吃蛇游戏的实验_第8张图片
(↑还没赢过。。。)


基本实现了游戏功能,然而这个游戏还是有bug的(比如长按按键可以暂停、可以快速掉头进行自杀),暂时没改。





参考资料:普通的贪吃蛇游戏算法 http://blog.csdn.net/fengsser/article/details/8474331

你可能感兴趣的:(stm32)