姓名 | 学号 | 分工 | 贡献占比 |
---|---|---|---|
曹津硕 | 2353127 | 项目任务分工 代码审查 除tmx地图外所有美术资源搜集与处理 项目说明文档撰写 音频引擎 常量整理与命名 StartMenu 类Player 类碰撞检测功能与行走功能AudioPlayer 类SettingScene 类Animal 类整合和完善N pc 类整合和完善BackpackScene 类重构并完善画面Mapscene 类重构并完善画面 |
40% |
胡浩杰 | 2351493 | 项目框架搭建 项目说明文档撰写 项目答辩ppt制作 代码美化与注释 Player 类基本初始化和移动功能Animal 类基础功能实现Npc 类基础功能实现Backpack 类I tem 类BackpackScene 类Mine 类MapScene 类基础功能实现BaseMapScene 类MapLayer 类Map1Scene 类Map2Scene 类Map3Scene 类 |
40% |
胡正华 | 2353741 | 所有tmx地图绘制以及碰撞对象层的绘制 项目答辩ppt制作 Player 类的碰撞检测功能MapLayer 类的碰撞检测功能任务委托的策划和人物对话内容设计 |
20% |
农场管理
玩家可以耕种、种植并收获多种作物(包括胡萝卜、南瓜等作物)
农场操作包括浇水、施肥、收获作物(按住P键并且鼠标左键点击土地为种植,左键点击作物为收获)
养殖功能,在农村中养殖有牛、羊、猪等动物
可以在农场中砍伐与种植树木(按住T键并且鼠标左键点击土地为种植,左键点击树木为砍伐)
社区交互
与镇上的居⺠建⽴关系,包括友谊和浪漫关系,在家中和伴侣可以开展对话并建立浪漫关系
接受并完成居⺠的委托任务,在星露岛上可以接受村长的任务,包括收集特定物品、帮助修复建筑等
参与定期的社区活动,矿工会邀请主角进行采矿活动
探索和冒险
探索农场周边的地区,包括森林、⼭脉和神秘洞⽳
在洞穴中可以挖掘矿物并收集稀有宝石(按住U键并且鼠标左键点击矿物)
角色成长和技能
⻆⾊技能树,包括人物移动速度和人物力量。
随着技能提升,人物的特性提升
背包界面中可以为人物更换装备
-
团队成员少于建议人数,每位成员承担更多的工作量,满足加分要求
-
具备初始游戏加载界面和设置界面
-
支持背景音效,在各个场景切换时具有提示音效
-
版本控制和团队协作
- 合理使用 Git 控制版本,将项目开源至 Github
- 团队成员少于建议人数,每位成员承担更多的工作量,满足加分要求
- 本项目依据团队每个成员所擅长的领域,进行了合理的分工。
-
功能和架构
-
界面精美
-
界面 UI 设计
-
页面设计
根据场景切换,本项目设计了 多个相互关联的场景,例如游戏界面场景(GameManu)、设置场景(SettingScene)、地图选择场景(MapScene)、背包场景(BackpackScene)、矿洞场景(Map1Scene)、星露岛场景(Map2Scene)、房屋场景(Map3Scene)等。
-
按钮设计
Cocos2dx 具有两个状态的按钮,分别为标准态和激活态。为了保证画面精美,本项目设计了按钮的高亮等细节处理,鼠标悬浮时按钮高亮,点击时按钮放大以响应点击事件。在设计按钮时,项目考虑了与当前场景色调的一致性,使得画面和谐精美。此外本项目也设计了滑动条、进度条,根据当前界面的主色调进行设计,符合原游戏特性。
-
背包与地图界面 UI 设计
自定义背包与地图界面的UI设计,参考了原游戏风格,画面美观。
-
-
图标和动画设计
-
图标设计
游戏进行了精美图标设计:对装备的图标参考了原游戏,保证美观。此外,设计时重视细节之处,游戏中对话时npc具有表情变化功能,各类人物图标均经过精心设计。
-
动画设计
对游戏中的人物向各个方向行走时均有不同的动画表现,同时行走动画流畅精美,人物的表现也会随着站立方向的改变而更新,使得人物移动逼真精致。在砍伐树木,收获作物,采集矿石时也增添了相应的动画。
-
-
项目目录结构清晰
本项目根据文件的不同功能,将各种资源文件进行了分类。所有类都被归置
Classes
文件夹,并且根据实现功能的不同又细分了Player、Scene、Object等子文件夹,更能直观地管理各类文件;同时将各种资源文件都放置在Resources
文件夹,把所有图片资源、音乐资源、字体资源等按照功能分类到对应的子文件夹,条理清楚,文件目录规整。- 没有内存泄露
动态内存是一种在程序运行时分配和释放的内存空间,动态内存的分配和释放通过使用特定的函数或操作符来完成。例如:
Player* Player::create() { Player* ret = new(std::nothrow) Player(); // 动态分配 Player 对象 if (ret && ret->init()) // 初始化成功 { ret->autorelease(); // 使用 Cocos2d-x 的自动释放池管理内存 return ret; } delete ret; // 初始化失败,手动释放内存 return nullptr; }
-
描述:在
Player::create()
函数中,通过new
操作符动态分配了一个Player
对象。如果对象初始化成功,调用autorelease()
将其添加到 Cocos2d-x 的自动释放池中,自动管理其生命周期;如果初始化失败,则手动释放内存以防止内存泄漏。 -
内存管理:
- 成功初始化:由 Cocos2d-x 的自动释放池管理,不需要手动释放。
- 失败初始化:通过
delete ret;
手动释放,防止内存泄漏。
-
程序运行过程不会发生崩溃情况
程序对各种可能存在的潜在问题都进行了处理,程序运行过程不会发生崩溃情况。
-
尽可能多地使用了 C++11 特性
-
STL容器
在代码中使用了std::vector、std::list、std::unordered_map等容器,简化了属性和物品的管理,提供了高效的存储和访问机制。
-
迭代器
在程序中使用了范围基于的
for
循环,以及隐式使用迭代器。迭代器提供了遍历容器元素的灵活方式,无论容器类型如何,均可通过迭代器或范围基于的for
循环进行访问。 -
类和多态
项目中使用了 Cocos2d-x 框架的类作为基类,派生出自定义的类,如
BackpackScene
继承自Scene
类。此外在 Cocos2d-x 中,基类通常定义为虚函数,以允许派生类重写,实现多态行为。 -
模板
- 模板类
ObjectManager<T>
- 目的:通用对象管理器,支持管理任意类型的对象。
- 用法:
ObjectManager<Item> _backpack;
模板的优势:通过模板类和模板函数,实现了代码的通用性和复用性,无需为每种类型编写重复的管理逻辑。
类型擦除:结合
std::unique_ptr
和多态,实现了对不同类型属性的统一管理。 - 模板类
-
异常处理
使用try-catch语句,用于捕获和处理异常,以确保程序在遇到错误时不会崩溃,并且可以优雅地处理错误
try { auto npcLeah = Npc::createWithPosition(npcPosition, "Leah", _npcLeahDialogues, LeahOption); if (!npcLeah) throw std::runtime_error("Failed to create Npc_Leah instance."); CCLOG("Npc_Leah created successfully."); npcLeah->setScale(0.1f); // 设置NPC的缩放 _tiledMap->addChild(npcLeah, 25); } catch (const std::exception& e) { CCLOG("Exception: %s", e.what()); Director::getInstance()->end(); // 结束游戏 }
-
函数和操作符重载
在代码中使用函数和操作符的重载,提高代码的直观性和可维护性。
// 重载输出流操作符 friend std::ostream& operator<<(std::ostream& os, const Item& item);
-
类型推导
C++11 引入了
auto
关键字,其允许编译器自动推导变量或表达式的类型,方便开发者编码也简化了代码。auto
:让编译器在编译器就推导出变量的类型,可以通过=
右边的类型推导出变量的类型。本项目在开发时大量合理使用类型推导,大大提升了代码简洁性:auto sheep = Animal::create(animalArea, "Sheep"); _tiledMap->addChild(sheep, 20); auto pig = Animal::create(animalArea, "Pig"); _tiledMap->addChild(pig, 20);
-
空指针关键字
nullptr
C++11 引入了
nullptr
关键字,它是一个表示空指针的字面量,用于替代传统 C++ 中的NULL
。在之前的 C++ 标准中,NULL
通常被定义为0
或((void*)0)
,这可能导致类型歧义和一些难以发现的错误。nullptr
的引入解决了这些问题,同时提供了更清晰、更安全的方式来表示空指针。使用举例如下:// 初始化移动状态 _isMoving = false; _isMovingLeft = false; _isMovingRight = false; _isMovingUp = false; _isMovingDown = false; _isInBackpackScene = false; _isInMapScene = false;
-
修饰常量
constexpr
constexpr
是 C++11 新引入的关键字,用于编译时的常量和常量函数。constexpr
修饰的才是真正的常量,它会在编译期间就会被计算出来,整个运行过程中都不可以被改变,constexpr
可以用于修饰函数,这个函数的返回值会尽可能在编译期间被计算出来当作一个常量,但是如果编译期间此函数不能被计算出来,那它就会当作一个普通函数被处理。使用举例如下:constexpr float SCENE_TRANSITION_DURATION = 0.3f; // 场景切换时间 constexpr float SETTING_BUTTON_SCALE = 12.0f; // 设置按钮缩放比例 constexpr float SETTING_BUTTON_OFFSET = 50.0f; // 设置按钮偏移量 constexpr float SETTINGS_SCENE_SLIDER_OFFSET_X = 50.0f; // 设置场景滑动条X轴偏移量 constexpr float SETTINGS_SCENE_BGMSLIDER_OFFSET_Y = 80.0f; // 设置场景背景音乐滑动条Y轴偏移量 constexpr float SETTINGS_SCENE_EFFSLIDER_OFFSET_Y = -70.0f; // 设置场景音效滑动条Y轴偏移量
-
lambda
表达式lambda
表达式是 C++11 最重要也最常用的一个特性之一。它能够就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象。以更直接的方式去写程序,好的可读性和可维护性。使用示例如下:// 创建菜单项,并绑定回调函数 auto item = MenuItemLabel::create(label, [=](Ref* sender) { // C++11特性:Lambda表达式 currentMapIndex = i; onMapItemClicked(sender); });
-
Unicode
编码支持C++11 引入了对
Unicode
的支持,并且引入了几种新的字符串字面量,在本项目中,使用了u8
。u8
用于表示 UTF-8 编码的字符串字面量。UTF-8 是一种可变长度的字符编码,用于编码Unicode
字符。这使得 C++ 程序能够更容易地处理多种语言和字符集。使用举例如下:// 初始化NPC的对话内容(使用统一初始化列表,C++11特性) _npcLeahDialogues = { {u8"Hey,Jackey.", ""}, {u8"What’s up with you?", ""}, {u8"You look tired.", ""}, {u8"You must pay attention to rest.", ""} };
-
规范统一的代码风格
本项目在正式开始前明确了团队项目代码规范,并且组长负责 Code Review 工作。
- 游戏还原度高
本游戏以《StardewValley》游戏为参考,仿照原游戏的模式进行开发,还原度良好,但由于时间关系还有许多地方需要改进,这些都可以作为游戏开发的未来计划。
- 常变量的集中定义
本项目的
Constant.h
头文件集中存放了所有常变量的定义,注释完备,方便项目维护。 -
感谢老师以及助教的细心指导,同时感谢小组的每一位成员,本次项目历时一个月,是所有人辛苦工作的成果,在完成项目后,我们对c++的面向对象特性有了更清楚的认知,代码能力也获得了大幅度提升。由于时间和能力的限制,本游戏还存在许多的不足需要改进,以及多人联机游戏等功能都在未来的开发计划中。希望在未来可以将游戏实现地更加精美完善。
2024年12月22日