下载 GameDame 文件夹的所有内容,运行Game.exe 体验游戏。
操作方式为WASD + Enter
本游戏起源于一次暑期培训实习,我们小组的任务是在5天内开发一款游戏。团队成员的能力不佳,从未接触过项目开发。我作为组长凭借多次Hackathon经验,需要设计一个简单的游戏架构。经过实习前期对过程的了解,我学习参考了其他2D游戏引擎,然后基于团队成员都会的 MFC 设计了本框架。因此本架构最重要的作用是指引团队成员开发,优化分工,控制复杂度。最重要的是:
美工兼产品:我觉得的这个功能能加。
我:加功能需要改架构,短期实现不了。
游戏采用纯键盘操作方式,因为游戏内精灵的生存周期是不定的,不能采用事件传递回调的方式响应键盘输入,同时游戏使用PeekMessage();
自建消息循环,所以可以在游戏内轮询。框架选择查表的方式检测输入。框架内响应WM_KEYDOWN WM_KEYUP
设置全局按键表,然后在具体的node对象内检测按键是否按下。
使用MFC的class MemDC
做双缓冲管理。预计使用脏矩形技术,但是因为性能没有太大的损耗,再加上预计npc也是会运动的,添加脏矩形会增加class Node
的复杂度所以没有采用。
该类作为表现类的共有基类声明了一些字段用于储存节点的状态,声明了一些纯虚函数用于处理状态的改变,作为节点间交互的接口。
游戏具有多个关卡,并具有独立的战斗场景,因此使用Scene类管理场景资源。Scene继承自class Node
,并作为渲染的起始点,通过调用bool Scene::run(CWnd* pWnd);
执行游戏的一次循环。通过调用bool Node::update(Scene* scene, int callbk)
更新节点的状态,通过调用bool Node::draw(CDC& dc);
将节点渲染到缓冲区。
Director类负责管理各个场景的生命周期,创建节点并添加到Scene中,主要是在关卡切换中保留玩家的数据,并可选性的复活npc。通过Scene *Director::getScene();
获取当前Scene并绘制。Director使用单例模式,作为CChildView的静态变量,Scene通过CChildView获得Director,并发送场景切换信息。因为两个类耦合度较高,在开发时出现了难以调试的问题。在重构时打算使用IOC/DI容器管理。
Map类是特殊的Node子类,他的生命周期与Scene绑定,绘制时最先绘制,是静态的(动态背景通过切换图片,移动视口实现),所以有必要单独实现一个类。另外为了实现游戏窗口的可缩放性(待实现),与地图场景的物理碰撞(未实现)。
游戏需要GUI界面,初步的设计是墙纸+按钮,因为时间紧迫,只是初步设计了接口,在游戏中并没有使用。再次是C++使用reactor编程对成员的能力要求太高,不利于项目的按时完成。后来了解到GUI也有Immediate Mode GUI和Retained Mode GUI,对于GUI的具体设计还在规划中,因为一不小心就设计成了GUI库了。