本篇实现了一个使用c8t6驱动0.96寸OLED的贪吃蛇游戏。也可以使用rct6,就是改改启动文件,芯片类型,宏定义等等。需要完整代码的可以私信我。
我是用的是四线IIC接口的OLED
B5 -> OLED上的SDA
B6 -> OLED上的SCL
B8 -> 左按键
3.3v -> 左按键
B9 -> 右按键
3.3v -> 右按键
B10 -> 下按键
3.3v -> 下按键
B11 -> 上按键
3.3v -> 上按键
B12 -> 结束按键
3.3v -> 结束按键
R -> 复位按键
GUD -> 复位按键
该代码主要实现在指定的x,y上打印一个点,将它存放在自定义的OLED_GRAM中,最终通过OLED_Refresh他们一并刷新到OLED上。
void OLED_DrawPoint(u8 x,u8 y)
{u8 pos,bx,temp=0;if(x>127||y>63)return;//超出范围了.pos=7-y/8;bx=y%8;temp=1<<(7-bx);OLED_GRAM[x][pos]|=temp;
}
void OLED_DrawNoPoint(u8 x,u8 y)
{u8 pos,bx,temp=0;if(x>127||y>63)return;//超出范围了.pos=7-y/8;bx=y%8;temp=1<<(7-bx);OLED_GRAM[x][pos]&=~temp;
}
因为0.96寸OLED屏幕是128*64,将每2*2的四个OLED上的节点看做蛇的一个节点,所以定义地图大小为32*12
#define MAXLENGTH 100 //蛇的最大长度int map[32][12]={0};//地图大小 x,y(一个坐标为4*4个像素点) 实际按4倍尺寸放大后地图大小为128*48个像素点int score; //分数bool eated=false; //蛇吃到食物的标记u8 KeyValue=0; //获取按键值struct { int snake_Grid[MAXLENGTH][2]; //二维数组,行坐标表示蛇节点,列表示当前节点的x,y坐标int length; //蛇的长度int direction;//蛇的方向
}snake; //定义结构体变量snakeint tailX, tailY; //标记尾部位置
int FoodX, FoodY; //标记食物位置
//创建地图函数
void Creat_map()//创建地图
{int i,j;for(i=0;i<12;i++){for(j=0;j<32;j++){if(i==0||i==11){map[j][i]=-2;}if(j==0||j==31){map[j][i]=-2;}}}
}//绘制地图函数
void Paint_Map(int x,int y)//绘制地图点坐标
{int i,j;for(i=4*y;i<4*y+4;i++) {for(j=4*x;j<4*x+4;j++){OLED_DrawPoint(j,i+16); }}}//绘制蛇头函数
void Paint_Head(int x,int y )//绘制蛇头点坐标
{int i,j;for(i=4*y;i<4*y+4;i++) {for(j=4*x;j<4*x+4;j++){if(i==4*y||i==4*y+3){OLED_DrawPoint(j,i+16); }if(j==4*x||j==4*x+3){OLED_DrawPoint(j,i+16); }}}
}//绘制蛇身函数
void Paint_Body(int x,int y )//绘制蛇身函数
{int i,j;for(i=4*y;i<4*y+4;i++) {for(j=4*x;j<4*x+4;j++){if(i==4*y||i==4*y+3){OLED_DrawPoint(j,i+16); }if(j==4*x||j==4*x+3){OLED_DrawPoint(j,i+16); }}}
}//绘制食物坐标函数
void Paint_Food(int x,int y )//绘制食物点坐标
{int i,j;for(i=4*y;i<4*y+4;i++) {for(j=4*x;j<4*x+4;j++){if(i==4*y+1||i==4*y+2){OLED_DrawPoint(j,i+16); }if(j==4*x+1||j==4*x+2){OLED_DrawPoint(j,i+16); } }}// 更新食物的坐标FoodX = x;FoodY = y;
}void Paint_Clean(int x,int y)//取消地图点坐标
{int i,j;for(i=4*y;i<4*y+4;i++) {for(j=4*x;j<4*x+4;j++){OLED_DrawNoPoint(j,i+16); }}}
//清除界面函数
void GUI_Clear()//界面清除
{int i,j;for(i=0;i<32;i++){for(j=0;j<12;j++){map[i][j]=0; }}
}//画蛇函数:将二维数组snake.snake_Grid里面的各个蛇坐标的值存入map数组
void drawSnake() //画蛇
{int i,x,y;//蛇头x=snake.snake_Grid[0][0];y=snake.snake_Grid[0][1];map[x][y]=1; //蛇身for(i=1;i<snake.length;i++){x=snake.snake_Grid[i][0];y=snake.snake_Grid[i][1];map[x][y]=2; }}
通过这个函数来输出这个游戏的所有显示数据。
//刷新界面函数:根据map数组里面的值一次性刷新游戏界面内的点坐标
void GUI_Refresh()//界面刷新
{int i,j,temp;for(i=0;i<32;i++) {for(j=0;j<12;j++){temp=map[i][j];switch (temp){case 2: Paint_Body(i,j); break;case 1: Paint_Head(i,j); break;case -2: Paint_Map(i,j); break;case-1: Paint_Food(i,j); break;case 0: Paint_Clean(i,j);break;} }}
}
初始化蛇长度为5、方向向右、蛇头坐标位于(7,5)。
//初始化蛇和地图函数:初定蛇长度为5、方向向右、蛇头坐标位于(7,5)
void Snake_Init()//蛇及地图初始化
{ int i;snake.length=5;snake.direction=RIGHT;score=0;snake.snake_Grid[0][0]=7;//x坐标,蛇头坐标snake.snake_Grid[0][1]=5;//y坐标,蛇头坐标tailX = snake.snake_Grid[snake.length - 1][0]; // Initialize tail coordinatestailY = snake.snake_Grid[snake.length - 1][1];for(i=1;i<snake.length;i++){snake.snake_Grid[i][0]=snake.snake_Grid[0][0]-i;snake.snake_Grid[i][1]=snake.snake_Grid[0][1]; //给刚开始的蛇身几个初始坐标}Creat_map();
}
初始在snake.h中宏定义了方向
#define RIGHT 1
#define LEFT 2
#define DOWN 3
#define UP 4
使用中断的方法读取按键对应引脚的上升沿,将值赋给全局变量KeyValue;
//按键处理函数:自定义矩形键盘值控制蛇的方向
void Get_Command()//获取键盘值
{u8 key=1;key=KeyValue; switch(key){case 1:if(snake.direction!=RIGHT) //左snake.direction=LEFT; break;case 2:if(snake.direction!=LEFT) //右snake.direction=RIGHT; break;case 3:if(snake.direction!=DOWN) //上snake.direction=UP;break;case 4:if(snake.direction!=UP) //下snake.direction=DOWN;break; }
}
void EXTI9_5_IRQHandler(void)
{ if(KEY8==1) //按键0{KeyValue=1;EXTI->PR=1<<8;}else if(KEY9==1){KeyValue=2;EXTI->PR=1<<9;}//清除LINE5上的中断标志位
}
//外部中断15~10服务程序
void EXTI15_10_IRQHandler(void)
{ if(KEY10==1) //按键1{KeyValue=3;EXTI->PR=1<<10;}else if(KEY11==1) //按键1{KeyValue=4;EXTI->PR=1<<11;}else if(KEY12==1) //按键1{Show_Endface();KeyValue=5;EXTI->PR=1<<12;}//清除LINE15上的中断标志位
}
//外部中断初始化程序
//初始化PA0,PC5,PA15为中断输入.
void EXTI_Init(void)
{KEY_Init();Ex_NVIC_Config(GPIO_B,8,RTIR); //上升沿触发Ex_NVIC_Config(GPIO_B,9,RTIR); //上升沿触发Ex_NVIC_Config(GPIO_B,10,RTIR); //上升沿触发Ex_NVIC_Config(GPIO_B,11,RTIR); //上升沿触发Ex_NVIC_Config(GPIO_B,12,RTIR); //上升沿触发MY_NVIC_Init(2,0,EXTI9_5_IRQn,2); //抢占2,子优先级2,组2MY_NVIC_Init(2,1,EXTI15_10_IRQn,2); //抢占2,子优先级2,组2
}
主要思想就是先判断蛇头结点是否与食物结点重合,如果没重合就删掉尾节点,头结点根据方向移动;如果重合,就不删掉尾节点,头结点根据方向移动。然后前结点的坐标等于后结点的坐标。
//蛇的移动函数:蛇身移动就让其坐标等于前一个坐标的值,蛇头则根据蛇的方向就行移动
void Move() {int i;int headX = snake.snake_Grid[0][0];int headY = snake.snake_Grid[0][1];tailX = snake.snake_Grid[snake.length - 1][0]; // 存储当前尾巴的坐标tailY = snake.snake_Grid[snake.length - 1][1];// 判断蛇头是否与食物坐标重合if (headX == FoodX && headY == FoodY) {snake.length++;eated = true; // 设置为true,表示吃到了食物score += 1;Food(); // 生成新的食物} else {map[tailX][tailY] = 0; // 清除尾巴}for (i = snake.length - 1; i > 0; i--) {snake.snake_Grid[i][0] = snake.snake_Grid[i - 1][0];snake.snake_Grid[i][1] = snake.snake_Grid[i - 1][1];}switch (snake.direction) {case UP:snake.snake_Grid[0][1]--;break;case DOWN:snake.snake_Grid[0][1]++;break;case LEFT:snake.snake_Grid[0][0]--;break;case RIGHT:snake.snake_Grid[0][0]++;break;}drawSnake();
}
//生成食物函数:在游戏界面内空位生成食物点坐标,并将食物坐标存入map数组
int Chek(int i,int j)//检查地图空位
{if(map[i][j]!=0){return 0;}return 1; //是空位就返回1
}void Food()//生成食物
{int i,j;do{i=(rand()%30)+1; //生成1~30之间的一个数j=(rand()%10)+1; //生成1~10之间的一个数}while(Chek(i,j)==0); //检查该点是否为空位map[i][j]=-1;//画出食物
}
bool GameOver()//游戏结束
{bool isGameOver=false;int sx=snake.snake_Grid[0][0],sy=snake.snake_Grid[0][1],i;//蛇头坐标for(i=1; i<snake.length; i++) //判断有没有吃到自己{if(snake.snake_Grid[i][0]==sx&&snake.snake_Grid[i][1]==sy)isGameOver=true;}if(snake.snake_Grid[0][0]==31||snake.snake_Grid[0][0]==0|| snake.snake_Grid[0][1]==11||snake.snake_Grid[0][1]==0) //判断有没有撞墙isGameOver=true;return isGameOver;
}
//显示分数
void Show_Score()//显示分数
{OLED_ShowString(30,6,"Score:",16);OLED_ShowNum(80,6,score,2,16);}
本文发布于:2024-01-29 00:55:57,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170646096211550.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |