当前位置: 首页 > news >正文

智能手表:小恐龙游戏

 小恐龙

初始菜单下 Key3 按下进入游戏选择界面呈现 “谷歌小恐龙”,Key2 可下移光标定位该选项,再按 Key3 进入游戏,游戏中 Key3 控制小恐龙起跳、OLED 以 0.1s 为单位计时,小恐龙碰障碍物则触发 “Game Over” 结束游戏 。 

先写一个计分页面,通过计时器0.1s  cnt++ 在定时器中调用

每累计到 100(对应 0.1 秒计时单位)就将分数Score加 1

int Score=0;
//显示分数
void Show_Score(void)
{OLED_ShowNum(91,0,Score,5,OLED_6X8);
}
void Dino_Tick(void)
{static uint8_t Score_Count=0,Ground_cnt,Cloud_Count;Score_Count++;Ground_cnt++;Cloud_Count++;if(Score_Count>=100)//计分 0.1s{Score_Count=0;Score++;}
}

写地面向左移动效果

地面的宽为256个像素点 高为8

让其不断向左移动

   

将256分为2组,当一组刚好移动到显示平外时,另一组刚好在屏幕内

每20ms Ground_Pos ++ 标志位加一

OLED_DisplayBuf[7][i]显存数组在 OLED 屏幕的特定行(第 7 行)绘制地面(Ground)图案,并通过偏移 Ground_Pos变量实现地面的滚动效果

Ground[];是取模生成的地面

显存函数就128个  但是Ground的256个

当Ground_Pos<128时,正常显示

当Ground_Pos>128时,比如 Ground_Pos=200, 255-200=55此时地面才有55长度,不够屏幕的宽度,怎么办呢,所以就得从开头的位置截取73的长度,也就是,让Ground_Pos从0计数到73,来补全空余的

//显示地面
uint16_t Ground_Pos;
void Show_Ground(void)
{if(Ground_Pos<128){for(uint8_t i=0;i<128;i++){OLED_DisplayBuf[7][i]=Ground[i+Ground_Pos];}}else {for(uint8_t i=0;i<255-Ground_Pos;i++){OLED_DisplayBuf[7][i]=Ground[i+Ground_Pos];}for(uint8_t i=255-Ground_Pos;i<128;i++){OLED_DisplayBuf[7][i]=Ground[i-(255-Ground_Pos)];}}}
void Dino_Tick(void)
{static uint8_t Score_Count=0,Ground_cnt,Cloud_Count;Score_Count++;Ground_cnt++;Cloud_Count++;if(Score_Count>=100)//计分 0.1s{Score_Count=0;Score++;}if(Ground_cnt>=20){Ground_cnt=0;//20ms地面 和 仙人掌一起移动Ground_Pos++;Barrier_Pos++;if(Ground_Pos>=256)Ground_Pos=0;if(Barrier_Pos>=144) Barrier_Pos=0;}
}

写障碍物显示的函数

当障碍物移动过去时,才显示取一次随机数

barrier_flag用于选择障碍物类型(随机取 0-2),Barrier_Pos记录障碍物偏移位置;当偏移量≥143 时重新随机切换障碍物类型,通过OLED_ShowImage在 (127-Barrier_Pos,44) 位置显示 16x18 大小的障碍物图像。

//障碍物
uint8_t barrier_flag;
uint8_t Barrier_Pos;
struct Object_Position barrier;
void Show_Barrier(void)
{if(Barrier_Pos>=143){barrier_flag=rand()%3;}OLED_ShowImage(127-Barrier_Pos,44,16,18,Barrier[barrier_flag]);barrier.minX=127-Barrier_Pos;barrier.maxX=127-Barrier_Pos+16;barrier.minY=44;barrier.maxY=44+18;}
void Dino_Tick(void)
{static uint8_t Score_Count=0,Ground_cnt,Cloud_Count;Score_Count++;Ground_cnt++;Cloud_Count++;if(Score_Count>=100)//计分 0.1s{Score_Count=0;Score++;}if(Ground_cnt>=20){Ground_cnt=0;//20ms地面 和 仙人掌一起移动Ground_Pos++;Barrier_Pos++;if(Ground_Pos>=256)Ground_Pos=0;if(Barrier_Pos>=144) Barrier_Pos=0;}
}

显示云朵 50ms移动一次 16x8 大小的云朵图像

uint8_t Cloud_Pos;
void Show_Cloud(void)
{OLED_ShowImage(127-Cloud_Pos,9,16,8,Cloud);
}void Dino_Tick(void)
{//接上面程序if(Cloud_Count>=50){  Cloud_Count=0;Cloud_Pos++;if(Cloud_Pos>=200)Cloud_Pos=0;}
}

画小恐龙,后脚着地,前脚着地,双脚着地的图片,取模软件取模

两种状态 奔跑 跳跃

奔跑:前后脚着地,每50ms切换一次

跳跃:就是Y坐标从小到大再到小

也就是sin函数 w=2*pi/T=2*pi/2*1s=pi

Y=28*sin(pi*t/1000)把s转化为ms

通过按键 1 触发跳跃(dino_jump_flag=1),利用正弦函数计算跳跃位移(Jump_Pos=28*sin(pi*jump_t/1000))模拟抛物线运动;奔跑状态下根据Cloud_Pos奇偶性切换两张恐龙图像实现跑步动画,跳跃时显示跳跃姿态图像;

//恐龙
extern uint8_t KeyNum;
uint16_t jump_t;	//跳跃计数
uint8_t dino_jump_flag=0;//0 奔跑 1 跳跃
uint8_t Jump_Pos;	//跳跃位移
extern double pi;struct Object_Position dino;void Show_Dino(void)
{KeyNum=Key_GetNum();if(KeyNum==1) dino_jump_flag=1;Jump_Pos=28*sin((float)(pi*jump_t/1000));if(dino_jump_flag==0){if(Cloud_Pos%2==0) OLED_ShowImage(0,44,16,18,Dino[0]);else OLED_ShowImage(0,44,16,18,Dino[1]);}else{OLED_ShowImage(0,44-Jump_Pos,16,18,Dino[2]);}dino.minX=0;dino.maxX=16;dino.minY=44-Jump_Pos;dino.maxY=62-Jump_Pos;}

写个检测是否碰到障碍

  1. 定义碰撞边界
    为小恐龙和障碍物分别设定矩形碰撞框(通过struct Object_Position存储):

    • 小恐龙:dino.minX(左边界)、dino.maxX(右边界)、dino.minY(上边界)、dino.maxY(下边界)
    • 障碍物:barrier.minXbarrier.maxXbarrier.minYbarrier.maxY
  2. 判断坐标重叠
    当两个物体的矩形区域同时满足以下条件时,判定为碰撞:

    • 小恐龙的右边界 > 障碍物的左边界(dino.maxX > barrier.minX
    • 小恐龙的左边界 < 障碍物的右边界(dino.minX < barrier.maxX
    • 小恐龙的下边界 > 障碍物的上边界(dino.maxY > barrier.minY
    • 小恐龙的上边界 < 障碍物的下边界(dino.minY < barrier.maxY

void Show_Dino(void)
{//接上面的代码dino.minX=0;dino.maxX=16;dino.minY=44-Jump_Pos;dino.maxY=62-Jump_Pos;}
void Show_Barrier(void)
{//接上面的代码barrier.minX=127-Barrier_Pos;barrier.maxX=127-Barrier_Pos+16;barrier.minY=44;barrier.maxY=44+18;}
int isColliding(struct Object_Position *a,struct Object_Position *b)
{if((a->maxX>b->minX) && (a->minX<b->maxX) &&(a->maxY>b->minY) &&(a->minY<b->maxY)){OLED_Clear();OLED_ShowString(28,24,"Game Over",OLED_8X16);OLED_Update();Delay_s(1);OLED_Clear();OLED_Update();return 1;}return 0;}

 

http://www.lryc.cn/news/608139.html

相关文章:

  • Linux自主实现shell
  • C#开发入门指南_学习笔记
  • Ubuntu系统VScode实现opencv(c++)图像翻转和旋转
  • Java 注解详解(含底层原理)
  • Vue 3.0 Composition API:重新定义组件逻辑的组织方式
  • 算法训练营DAY46 第九章 动态规划part13
  • 全球化 2.0 | 中国香港教育机构通过云轴科技ZStack实现VMware替代
  • stm32103如果不用32k晶振,那引脚是悬空还是接地
  • SLAM中的非线性优化-2D图优化之零空间实战(十六)
  • Linux iptables防火墙操作
  • Apache Doris数据库——大数据技术
  • SpringBoot怎么查看服务端的日志
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博舆情数据可视化分析-热词情感趋势树形图
  • sqli-labs:Less-21关卡详细解析
  • 【BTC】挖矿难度调整
  • 人类学家与建筑师:区分UX研究和项目管理的需求分析
  • 隧道照明“隐形革命”:智能控制如何破解安全与节能双重命题
  • 【iOS】strong和copy工作流程探寻、OC属性关键字复习
  • 电脑手机热点方式通信(下)
  • 「iOS」————weak底层原理
  • 「iOS」————SideTable
  • JAVA国际版同城服务同城信息同城任务发布平台APP源码Android + IOS
  • Ajax——异步前后端交互提升OA系统性能体验
  • Dice Combinations(Dynamic Programming)
  • 8.2 状态机|贪心|dfs_dp
  • Linux初步认识与指令与权限
  • 机器学习——K 折交叉验证(K-Fold Cross Validation),实战案例:寻找逻辑回归最佳惩罚因子C
  • Jotai:React轻量级原子化状态管理,告别重渲染困扰
  • React ahooks——副作用类hooks之useThrottleFn
  • react 和 react native 的开发过程区别