【平头哥RVB2601创意应用开发】掌上游戏机
[复制链接]
本帖最后由 nemon 于 2022-6-7 17:25 编辑
作品名称:掌上游戏机
作者:nemon
https://bbs.eeworld.com.cn/home.php?mod=space&uid=424743
https://occ.t-head.cn/people/user/4020178002997612544
一、项目背景
- 以前有人统计说大众最热衷3个G,其中为首的就是GAME。看到核心为平头哥CH2601芯片的RVB2601开发板的片上资源、板载资源都很丰富。于是基于这个平台,制作了掌上游戏机的原型。
-
二、作品简介
- 本项目完全基于RVB2601开发板本身资源,以用户按键K1、K2作为输入,OLED作为输出,自造了位图、字体、抽象屏幕、游戏应用框架4个车轮,优化了oled的刷新算法,手工绘制了全部所需位图,编制出主菜单和flappy bird共2个应用。
-
操作过程:开机后显示菜单。
根据屏幕提示,按右键(B)可以更换选项,按左键(A)运行游戏。
根据屏幕提示,按右键(B)退出,按左键(A)开始游戏。
在游戏中,按左键(A)提升小鸟,钻过缺口得一分,撞倒水管游戏结束。
三、系统框图
1、系统硬件组成
通过GPIO得到按键操作,经mpu处理,通过SPI接口,更新oled屏
2、组件关系图
main函数调用csi_gpio_pin进行初始化等。Menu和FlappyBird实现Game结构体,main函数调用Menu并传递事件给它;menu调用FlappyBird并传递事件给它。各种Game都使用Screen更新oled。Font使用Image存储点阵,Screen及各种Game都依赖Image、Font。
3、GAME的状态转移
父过程调用game的init来获取单例并初始化,game自己控制状态,在收到父过程通过event_handle传过来事件后,决定如何处理,并返回状态。当game将自己状态置为退出后,父进程接管控制流。
四、各部分功能说明和解析
1、源码文件清单
以上文件,以文件名对应第二部分“组件关系图”中的各组件。
2、位图(Image.h、Image.c):
结构体IMAGE包含3个子元素:位图宽,位图高,数据数组。此处为了简化多维数组处理,数据用了一维数组,于是就定义了一个宏 IMAGE_POT,用于将二维的表示法转为一维的定义。image_create_function 用数据创建位图,如果只提供了大小,可以创建空白图片。 image_destory_function 销毁位图,主要作用是释放位图占用的内存。另有5个工具函数,作用分别是:水平翻转、垂直翻转、旋转180度、右转90度、左转90度。
3、字体(Font.h、Font.c):
存储每个字符的位图,用函数font_get_char_function从“字库”里检索。
4、flappy bird游戏(game_FlappyBird.h、game_FlappyBird.c):
实现动画和游戏逻辑,包括按键处理、评分、各阶段屏幕绘制。
5、屏幕抽象层(Screen.h、Screen.c):
screen_init_function(int b_flag_inversen);用于初始化屏幕,并设置屏幕是否为反色输出。就是这个反色输出功能,使我能用习惯的黑白来画图。如果需要,也可以在OLEd和LCD间方便地切换。
screen_set_dirty_flag_function(int b_flag) 和 screen_set_auto_refresh_flag_function(int b_flag) 用于设置是否发生更改和是否自动向设备层刷新。这两个函数是联合使用,我一般先关掉自动刷新,然后绘图的时候,绘图函数自动根据颜色来设置是否有更改。所有的画图都完成后,再打开自动刷新,这时就会根据之前的更改标记来决定是否调用OLED驱动函数进行刷新。
void screen_refresh_function();如名字所示,执行它会进行一次强制刷新。
void screen_clean_function();如名字所示,执行它会清理缓存。
另外的几个功能函数,分别是screen_draw_bitmap_function(画位图)、screen_draw_string_function(调用字库画字符串)、screen_draw_Int32_function(数字转字符串画出)、screen_draw_horizontal_line_function(画水平线)、screen_draw_vertical_line_function(画垂直线)、screen_draw_rectangular_function(用边框色和填充色画矩形)、screen_draw_dot_function(画一个点)。
6、oled优化(只涉及函数oled_reflesh):
增加一级缓存,用于记录上一次更新后的屏幕数据:uint8_t g_oled_ram_cache[8][128]={0};
修改oled_reflesh(),增加输出前判断是否一致(由于硬件特性,连续修改不需要设置列的位置)。
7、抽象游戏结构体(Game.h)
在Game.c中仅是被注释起来的示例。game_event预定义了按键A、B、1、2、3、4按下,以及定时器触发和请求刷新显示事件。父过程通过结构体_GAME中的(*game_event_handle)(game_event event)向子过程传递事件,并获取最新的GAME_STAT。面向对象的角度看,每个游戏都是一个单例对象。启动一个游戏时,首先执行该游戏的init函数,获得指向该游戏的结构体指针game。之后有2种处理方法:用中断或是while(1):如果用中断,则(1)执行game->game_loop_handle直到退出;(2)在事件对应的处理函数中调用game->game_event_handle,将事件传递给game;(3)维护一个game*的栈,把当前的game压进去,并在game退出时,恢复最新的顶部game。如果使用while(1),则(1)while(1)要写在在main函数一级,也就是整个系统的最高层;(2)通过PIO、延时等方法判断是否触发事件,然后用game->game_event_handle,将事件传递给game,同时根据返回的GAME_STAT值,判断是否游戏已经退出。(3)由于这种情况下,需要父级game管理子级game,并在子级game退出时,接管输入输出。
8、主菜单(game_MainMenu.h、game_MainMenu.c):
用于显示菜单和启动游戏。因为现在只做了1个Flappy Bird,所以10个菜单挂的都是它。然后把菜单画出来,响应按钮事件,更换选择或执行选中游戏的操作。当选中时,将gameMenu状态设置成游戏中,同时初始化对应的game,这时所有的事件都应该传给当前的game。传事件之后顺便检查一下,要是已经退出了,那就把gameMenu的状态改回来,也就是接管控制。
五、作品源码
步统计,代码超过1600行。核心代码在发帖和博客中详细分析(见第七部分的链接)。
工程文件压缩后约35MB 。
六、视频演示
基于平头哥CH2601的游戏掌机原型:flappy bird:
链接地址:https://www.bilibili.com/video/BV1pa411L7JU
七、项目总结
1、项目总结:
本项目验证了RVB2601的资源和处理能力,在YoC的组件基础上,比较快速的搭建出了掌上游戏机平台。受时间约束,完成了主控和一个游戏,可以作为原型验证CH2601的运算速度和片上存储空间。
后期努力方向包括:
1)更多控制方式;
2)了解组件依赖关系,裁剪工程,提高编译速度;
3)研究udp协议实现,支持网络对战。
2、“【平头哥RVB2601创意应用开发】掌上游戏机”系列文章:
八、其他
感谢电子工程世界和平头哥芯片开放社区的支持!
九、作品完整设计说明WORD文档
nemon_平头哥RVB2601活动作品提交模板(2022-4-28).doc
(879.5 KB, 下载次数: 4)
|