|
RAW-OS上的小游戏---你玩过Flappy Bird的三种模式吗
[复制链接]
本帖最后由 洗澡哥 于 2014-8-25 01:45 编辑
RAW-OS上的小游戏---你玩过Flappy Bird的三种模式吗 参与HELPER2416开发板助学计划 首先感谢BOSS,给了大家一个这么好的学习机会。
近期学习了国产实时操作系统RAW-OS,第一次接触RTOS,看了txj大神写的《高效实时操作系统设计》,感觉很不错,对于我这样的新手算是脑补了一下。很多RTOS的东西只是有了大概的印象,具体的留到以后实践中去检验学习。个人感觉国产RTOS前景广阔,这也是为什么作为一个新手我会选择学习RAW-OS的原因。RAW-OS源码可从RAW-OS官网下载。
第一次的实验,参考了这个贴子:HELPER2416学习笔记7——RAW-OS之任务创建、调度、挂起及恢复。计划将LED灯亮和LED灯灭两个任务改成LED亮和按键检测,当检测到按键按下时,LED才亮。结果在按键检测中犯了一个错误,没用while(1)循环,结果按键检测一次就退出了,始终达不到想要的效果。错误程序如下:
- void KEY_task(void *arg)
- {
- if((GPFDAT_REG)%2)
- GPBDAT_REG = 0x00000002;
- else
- {
- raw_task_resume(&LED_ON_OBJ);
- }
- }
复制代码
正确程序:
- void KEY_task(void *arg)
- {
- while(1)
- {
- if((GPFDAT_REG)%2)
- GPBDAT_REG = 0x00000002;
- else
- {
- raw_task_resume(&LED_ON_OBJ);
- }
- }
- }
复制代码
通过这次试验,让我认识到了,RTOS的任务间关系。LED亮起任务在等待按键检测到按下后,才能恢复运行。可是按键检测任务只执行了一次就结束了(因为没使用while(1)循环)因此来不及检测按键按下,也就没办法恢复LED亮的任务了。加上了while(1)循环后,程序就能达到,按下按键亮LED的效果了。
附上工程文件。按键是SW1。LED是屏幕下面那个。
第二次实验就是这个Flappy Bird小游戏了。创建了三个任务,按键检测,触摸屏检测,屏幕显示。
按键检测内容如下:
- void KEY_task(void *arg) //按键检测
- {
- while(1)
- {
- if(key)
- raw_sleep(10);
- else if(!((GPFDAT_REG)%2))
- {
- num=0;
- y=100;
-
- X[0]=480;X[1]=600;X[2]=720;X[3]=840;
-
- GUI_SetBkColor(GUI_BLUE); //蓝色背景
- GUI_MEMDEV_Select(hMem); //选择存储设备
- GUI_ClearRect(0,0,480,272); //清屏
- GUI_MEMDEV_CopyToLCD(hMem); //存储设备显示
-
- key=1;
- }
- else
- raw_sleep(1);
- }
- }
复制代码 这个按键检测的堆栈空间大小stack_size和上一个程序设置的一样64,结果每次按键按下后,程序就死机了。
运行仿真,发现每次程序都是停在RAW_ASSERT(0);附程序如下:
- void raw_stack_check(void)
- {
- PORT_STACK *task_stack_start;
-
- task_stack_start = raw_task_active->task_stack_base;
-
- /*statck check method 1*/
- if (*task_stack_start) {
-
- RAW_ASSERT(0);
- }
-
- /*statck check method 2*/
- if ((PORT_STACK *)(raw_task_active->task_stack) < task_stack_start) {
-
- RAW_ASSERT(0);
- }
-
- }
复制代码
一看估计程序是挂在是堆栈检测上了,难道是堆栈溢出?于是迅速打开《高效实时操作系统设计》,“任务堆栈空间监测机制”,看了如下的话:
“
假设任务的栈空间是往下增长的,假设任务函数体内已经栈溢出,在某个时候任务会主动切换到其它任务,或者通过中断触发到更高优先级的任务。这个时候在任务栈空间中已经保存了寄存器的时候,可以做两种判断机制:
第一种判断任务栈的底部是否是原先的0值,因为创建任务的时候,任务的栈会被全部清0,所以,如果这个时候任务栈的底部这个值不为0的话,上图中的红色底部区域表明栈空间已经不为0,说明栈空间已经溢出。
第二种判断是,在任务栈中保存了任务所有寄存器的前提下,判断当前任务的栈指针是否已经小于原先任务底部的栈值。在栈空间往下生长的情况下,如果是小于了,说明栈空间已经溢出了。
”
推测堆栈可能小了,于是换成128,程序就完美运行了。再也不卡死了。任务的栈溢出,及时的被raw-os的栈溢出机制检查了出来了,不错!
操作屏幕用的ucgui,一些基本的函数,现学现用。
附上Flappy Bird小游戏的工程文件和一份ucgui中文手册。工程文件的ucgui文件夹中有英文手册,以英文手册为准。
加上了很多自己的注释,相信很容易理清程序思路。
由于论坛上传15M的限制,请移步百度网盘下载:
Flappy Bird小游戏工程文件:
游客,如果您要查看本帖隐藏内容请 下载附件
保存到相册
2014-8-25 00:47 上传
各变量定义如下:
#define high 75 //安全区域高度
- #define width 40 //安全区域宽度
- volatile static unsigned int X[ ]={480,600,720,840}; //X坐标
- volatile static unsigned int Y[ ]={20,40,60,80,100,120,140,160,170};//Y坐标
- volatile static char a; //四个柱子循环显示
- volatile static char b[4]; //四个柱子随机高度
- volatile static char delay; //触摸屏扫描延时
- volatile static unsigned int num; //通过数字
- volatile static char key; //key=1运行游戏,key=0停止。按键sw1按下则使key=1
- volatile static char Key_Flag=1; //撞到柱子的标志位
- volatile static unsigned int y; //bird高度
- volatile static unsigned int Dead_High; //撞柱的柱子高度(Y坐标)
- volatile static unsigned int Length=5; //Bird(小方块)的边长
- volatile static char Button_Key; //按钮值:1,普通模式;2,作弊模式;3,无尽模式。
volatile static unsigned char Between_Where; //作弊模式用到的,用来分析下一根柱子的高度
复制代码 刷新四个移动的柱子,更新通过的柱子数:
- GUI_SetColor(GUI_GREEN);//颜色设置
- for(a=0;a<4;a++) //画柱子
- {
- GUI_ClearRect(X[a]-1,0, X[a],Y[ b[a] ]);
- GUI_ClearRect(X[a]-1,Y[ b[a] ]+high,X[a],271 );
-
- GUI_FillRect(X[a]-1-width,0, X[a]-1,Y[ b[a] ]);
- GUI_FillRect(X[a]-1-width,Y[ b[a] ]+high,X[a]-1,271 );
-
- if(X[a]-1-width == 144)
- num++;
-
- if(X[a]<=0)
- {
- X[a]=480; //更新下一根柱子
- b[a]=rand()%8;
- }
- else
- X[a]-=1;
- }
复制代码
作弊模式(外挂模式)如何实现的呢:其实是检测出接下来到的的那一根柱子可通过的最低高度 Y[ b[Between_Where] ] + high - Length,Between_Where是下一根即将到来的柱子对应的a值。在Bird(小方块)即将降到这个最低高度时,用程序模拟一次触屏按下即可。关键是检测Between_Where的大小。
检测及执行代码:
- <p>for(a=0;a<4;a++)//作弊模式
- {
- if( X[a] > 150 && X[a] < width+80+150 )
- Between_Where = a;
- }
-
- if(!delay) //触屏是否按下,扫描。delay的作用是让bird上升的过程更加平滑以及触屏消抖
- {
- if(y<=271-Length-2) //不断增加Bird高度,位置下移
- y+=2;
- else
- y=271-Length;
-
- if(GUI_TOUCH_GetState(pState)) //触屏被按下
- delay=3;
- if(Button_Key==2 && y > Y[ b[Between_Where] ] + high - Length - 3) //作弊模式代码,当位置较低时触发Bird向上运动
- delay=3;
- }
- else
- {
- if(y>=17)
- y-=17;
- else
- y=0;
- delay--;
- }
复制代码
无尽模式,就是每次碰到柱子后,bird的体积变大一次,当碰柱子的次数实在太多时,便只能重新开始游戏了。这告诉我们小的错误累计多了也是致命的。 建议大家可以这么玩(录完视频突然想到的),先用无尽模式,让bird变的比较大的时候,然后切换到作弊模式(外挂模式),让它自己通关,这样一对比,就看出程序控制和人操作的差距了。
优酷不失所望,仍然把我横屏录的视频竖起来了:
附上工程文件,带详细注释,欢迎大家来交流,或者有什么好的创意也可以分享一下,看能否加进这个游戏中:
通过三次实验,感觉在学习rtos这条路上还有很长的路要走,要在不断的犯错中学习。虽然是个小游戏吧,但是程序猿玩着自己写的游戏,跟玩别人写的游戏,感觉总是不一样的吧。
论坛ID:洗澡哥 提交时间:2014.08.23
|
赞赏
-
1
查看全部赞赏
-
|