PicoLoop
项目概述
PicoLoop 是一款像素风格闯关类练手小游戏,使用 C++ 面向对象开发。
项目不仅拥有经典人物闯关玩法,还在此基础上创新出了自制模式。
项目经过优化,让人物能够流畅移动,让人物与物体相互作用稳定。
项目将玩家产生的数据持久化存储到文件中,关闭游戏不会丢失数据。
效果展示
技术栈
- C++ 面向对象
- Easyx 图形库
特点
本项目运用了 C++ 面向对象特性,例如继承、派生、多态与封装,
Page基类是页面的基类,能够监听与处理用户交互事件的,所有子页面都派生于它;
Element是所有游戏元素的基类,各类具体元素重写相应功能的虚函数,让元素有不同功能。
项目没有使用智能指针,内存均为手动管理,使用了堆内存手动申请与释放, 解决了浅拷贝、重复释放、空指针等内存管理问题。
如果您对游戏或源代码感兴趣,可点击 下载源码 ,导航到底部下载标题进行下载。
游戏玩法
核心玩法
核心玩法很简单:玩家使用键盘操纵人物到达终点旗帜,这是唯一的胜利方式。
玩法分类
- 闯关模式(play):玩家通过按键盘的方向键,使人物移动或跳跃; 控制人物穿过预设的重重障碍,收集所有钥匙,躲避致命元素,合理利用道具, 抵达终点即可通过关卡。关卡采用自选模式,无需担心卡关问题;
- 自制模式(make):玩家放置控制人物和元素并控制人物抵达终点。 内置 84 个可编辑关卡,数据持久化存档。玩家可发挥自己的创意, 放置玩家以及各种元素,创建属于自己的关卡并预览游玩。
元素介绍
要想胜利就不可避免与元素产生交互,不同元素会对玩家产生不同影响:
- 砖块元素:阻挡玩家的移动路线,是游戏的主要障碍;
- 钥匙元素:玩家需要收集全部钥匙才能解锁终点旗帜并过关;
- 跑鞋元素:玩家拾取后,跳跃高度有显著增加,能跳得更高;
- 火元素:当人物触碰到火元素时,会立即被击杀,游戏自动重玩;
- ……
游戏里有对游戏操作和元素功能的详细介绍, 大家可以下载后,在关卡页点击 help 按钮查看图鉴。
因篇幅限制,元素介绍在这里不一一列出。
设计思路
整体架构设计
本项目采用模块化架构,基于 EasyX 图形库搭建完整游戏运行框架, 游戏开发流程是:初始化 → 游戏循环 → 资源释放。 这样按功能拆分独立模块,有利于降低耦合度,便于维护与扩展。
-
全局以
Game游戏类为主类, 统一调度生命周期、全局状态与逻辑流转,作为程序入口; -
依托
Window窗口类、Page页面类、PicoElement元素类三层拆分,分别负责窗口事件、 页面切换、游戏元素管理,这样明确了职责,便于维护和添加新元素; -
采用基类派生的继承设计,设计了
Page、Button和PicoElement抽象基类及其子类。
像素视觉设计
游戏的所有绘图都是使用图形库内置函数绘制的,未使用任何图片文件。 绘图始终保持简约的像素风格,并开启了动画流畅性优化。
当窗口最小化或失去焦点时,动画播放会自动暂停,以节省资源。
碰撞检测设计
游戏采用了最经典的矩形碰撞检测方法,根据玩家与元素的四个顶点的相对位置来判断, 分为以下几种情况:
- 触碰元素任何地方,即“碰到”元素
- 触碰元素上、下、左、右外表面
- 触碰元素上、下、左、右内表面
- 触碰元素中心点,即“通过”元素
- 触碰元素上、下、左、右外表面或内表面,但未对齐
例如触碰元素上表面代码:
// Touch element top surface
return this->y > player.y + player.size &&
	this->y <= player.y + player.size + player.MOVE_STEP &&
	this->x <= player.x + player.size &&
	this->x + this->size >= player.x;
游戏少量元素拥有动画,通过实现时钟计时方法来播放,可在图鉴中看到。
关卡功能设计
在游戏广场中,玩家通过按键盘控制人物移动和跳跃,暂停游戏,重玩,退出。具体操作:
- 按 方向 键使人物移动或跳跃;
- 按 空格 键暂停游戏;
- 按 R 键或退格键重玩当前关卡;
- 按 Esc 键或点击右上角关闭按钮退出游戏。
玩家如果想具体了解一个元素的功能,可以点击 help 按钮查看图鉴。
问题解决
问题描述
编写项目的过程中遇到了许多问题:
- 碰撞检测不够准确、角色运动不够流畅的各类异常问题;
- 主循环执行逻辑与元素管理方式不当,导致画面闪烁与交互卡顿;
- 数据读写容错性差,用户不慎修改文件导致读取失败、存档异常丢失问题;
- 按钮对象创建时文字对象指针的浅拷贝、资源重复释放的内存管理问题;
- 元素编辑器读取空指针或已释放对象导致程序崩溃的问题。
解决方案
针对以上问题,项目开发者分别进行了以下优化:
-
统一采用基于
Element基类的矩形碰撞判定算法,明确了“小于”和“小于或等于”的边界情况,使穿模概率大幅下降。 -
优化
Game类主循环流程,采用 “更新 → 计算 → 渲染” 顺序;使用BeginBatchDraw和EndBatchDraw批量绘制来消除闪烁; 优化元素及人物绘制策略,移动时只更新人物区域背景,避免全屏重绘; 使用基类Page统一事件监听的形式,避免组件跨页面响应。 - 增加文件格式校验与字段合法性判断,异常时自动将所有数据置零;采用安全写入机制, 类型、数据范围错误时直接抛异常,避免因文件数据损坏导致存档丢失。
-
明确
_tcsdup宏底层会申请LPTSTR类型(开发时环境)的动态指针,在按钮实体析构函数中使用free释放资源,实现拷贝构造函数、 拷贝赋值运算符,手动实现深拷贝逻辑,避免成员指针共用内存隐患以及内存泄漏问题。 -
在编辑器模块访问
Element对象前增加空指针校验, 确保仅对有效实例进行操作,避免释放后使用对象。
下载源码
本项目开放源码下载功能,可点击下方链接在 GitHub 上免费下载源码。
注意源码为个人编写,仅供参考,还存在不足的方面,不保证代码的质量和准确性。 大家可以在源码的基础上修改,以新增更多元素、更多关卡,创造出更好的游戏体验。
备注
免责声明
- 本项目为个人学习练手项目,仅代表个人创意,不对代码的正确性、完整性、 有效性、及时性做出任何保证。请勿将源代码用于正式开发环境中或其它非法用途。
- 项目的所有源代码仅供学习交流使用,不得用于任何商业用途。 若因复制源代码用于生产环境等行为造成的损失,项目设计者及开发者不承担任何责任。
- 若项目名称和第三方商标名称发生局部命名冲突,纯属命名巧合, 项目设计者及开发者无任何侵权目的。
所有评论 (...)