当前位置: 首页 > news >正文

基于原神游戏物品系统小demo制作思路

概述

本文介绍了一个基于C++的游戏物品与角色管理系统,该系统实现了游戏中的物品分类、角色属性管理、队伍组建以及背包物品使用等功能。该系统采用面向对象的设计原则,通过继承和多态实现了可扩展的物品效果系统。

系统架构

1. 物品类型系统

系统定义了三种物品类型,通过枚举类ItemType实现:

enum class ItemType {FOOD,      // 食物:可恢复角色属性PROP,      // 养成道具:用于角色培养MATERIAL,  // 材料:用于合成或制作
};

2. 物品基类设计

物品基类Item作为抽象类,定义了所有物品的共同属性和接口:

class Item {
public:Item() {};int GetId() const { return id; }virtual~Item() = 0;
protected:int id;              // 物品唯一标识ItemType m_itemType; // 物品类型string name;         // 物品名称
};

3. 食物效果系统

系统通过抽象类FoodWeight和其派生类实现了多种食物效果:

class FoodWeight {
public:FoodWeight() {};virtual ~FoodWeight() = 0;virtual void restore() {};virtual void showRestore() {};virtual void restoreHp() {};virtual FoodWeightType getFoodWeightType() = 0;
};

4. 角色管理系统

Role类封装了游戏角色的各项属性:

class Role {
public:Role() = default;Role(int id, string name, int lev, int ran, int Hp, int att, int deff, string ele): id(id), name(name), level(lev), rank(ran), hp(Hp), attack(att), defense(deff), element(ele) {}int Id() { return id; }string Name() { return name; }void sethp(int hp) { this->hp = hp; }int gethp() { return hp; }private:int id=0;string name="";int level = 1;int rank=0;int hp=0;int attack=0;int defense=0;string element="无";
};

5. 队伍管理系统

Team类实现了最多4名角色的队伍管理功能:

class Team {
public:void addRole(Role& role) {if (roles.size() < Teamnumber) {roles.push_back(&role);} else {cout << "队伍已满,无法添加更多角色" << endl;}}void removeRole(int roleId) {// 移除指定ID的角色}void showRoles() {// 显示队伍中的所有角色}private:int id;string name;vector<Role*> roles;
};

6. 食物与效果实现

系统通过Food类和其派生类实现了具体的食物物品:

class Food : public Item {
public:Food() { m_itemType = ItemType::FOOD; }~Food() {}int GetId() const{ return id; }int GetNum() const { return num; }void updateAddnum() { num +=1; }void updateSubnum() { num -= 1; }FoodWeight* getFoodWeight() { return FoodWeight; }protected:int num;FoodWeight* FoodWeight;
};

7. 背包管理系统

Knapsack类实现了物品的存储、检索和使用功能:

class Knapsack {
public:Knapsack() {};~Knapsack() {for (auto f : Foods) { delete f; }Foods.clear();}void addFood(Food* food) {// 添加食物到背包,支持堆叠相同物品}Food* selectFood(Food& foodId) {// 选择指定食物}void useFood(Food&& food) {// 使用食物}auto getFoods() { return Foods; }private:vector<Item*>Foods;
};

系统特点

1. 灵活的物品效果系统

通过FoodWeight抽象类及其派生类,系统可以轻松扩展新的食物效果类型。例如,SunsetFruitRestore类实现了日落果的生命恢复效果:

class SunsetFruitRestore : public RestoreHp {
public:int hp = 100;virtual void restoreHp() override {cout << "使用日落果 恢复角色生命值" << endl;}virtual FoodWeightType getFoodWeightType() override {return FoodWeightType::RESTOREHP;}virtual int getHp() { return hp; }
};

2. 智能的物品使用策略

系统提供了智能的食物选择机制,可以根据角色需求自动选择最适合的食物:

void useFoodCur(Role* role, Knapsack &Knapsack) {// 自动选择恢复效果最好的食物auto fid = find_if(f.begin(), f.end(), [&](Item* item) {auto F = (Food*)item;auto getfw = (F->getFoodWeight());return ((SunsetFruitRestore*)getfw)->getHp() > max; });// 使用选中的食物恢复角色生命值if (fid != f.end()) {auto food = (Food*)(*fid);auto fw = food->getFoodWeight();if (fw->getFoodWeightType() == FoodWeightType::RESTOREHP) {auto rhp = dynamic_cast<RestoreHp*>(fw);role->sethp(role->gethp() + rhp->getHp());rhp->restoreHp();Knapsack.useFood(move(*food));}}
}

3. 安全的资源管理

系统通过适当的析构函数实现,确保了动态分配的内存得到正确释放:

~Knapsack() {for (auto f : Foods) {delete f;}Foods.clear();
}~Sunset() {if (FoodWeight != nullptr) {delete FoodWeight;FoodWeight = nullptr;}
}

应用示例

系统提供了一个完整的使用示例,展示了如何创建角色、食物,以及如何使用食物恢复角色生命值:

int main(void) {// 创建角色Role r1(1,"迪卢特",50,2,0,618,914,"火");// 创建背包并添加食物Knapsack knapsack;Food* f1 = new Sunset();Food* f2 = new Sunset();Food* f3 = new Sunset();Food* f4 = new Sunset();Food* f5 = new Sunset();knapsack.addFood(f1);knapsack.addFood(f2);knapsack.addFood(f3);knapsack.addFood(f4);knapsack.addFood(f5);// 使用食物恢复角色生命值useFoodCur(&r1, knapsack);useFoodCur(&r1, knapsack);useFoodCur(&r1, knapsack);useFoodCur(&r1, knapsack);useFoodCur(&r1, knapsack);cout << "当前角色生命值为:" << r1.gethp() << endl;// 释放资源delete f5;delete f4;delete f3;delete f2;delete f1;return 0;
}

完整代码

#include<iostream>
#include<string>
#include<vector>
using namespace std;//物品类型
enum class ItemType {//食物FOOD,//养成道具PROP,//材料MATERIAL,
};
//物品类(抽象类)
class Item {public:Item() {};int GetId() const { return id; }virtual~Item() = 0;
protected://物品idint id;//物品类型ItemType m_itemType;//物品名称string name;};Item::~Item(){}//食物类权值类型
enum class  FoodWeightType {//恢复角色生命值RESTOREHP,//恢复角色加入时间限制RESTORETIME,
};// 食物类权值抽象类
class FoodWeight {
public:FoodWeight() {};virtual ~FoodWeight() = 0;//恢复角色加入时间限制virtual void restore() {};//查看恢复角色加入时间限制	virtual void showRestore() {};//恢复角色生命值virtual void restoreHp() {};virtual  FoodWeightType  getFoodWeightType() = 0;};FoodWeight::~FoodWeight() {}//角色
class Role {public:Role() = default;// 修正 Role 构造函数成员初始化列表,成员变量名应与声明一致Role(int id, string name, int lev, int ran, int Hp, int att, int deff, string ele): id(id), name(name), level(lev), rank(ran), hp(Hp), attack(att), defense(deff), element(ele) {}~Role() {};//角色idint Id() { return id; }//角色名称string Name() { return name; }//设置生命值void sethp(int hp) {this->hp = hp;}//获取生命值int gethp() {return hp;}private://角色idint id=0;//角色名称string name="";//角色等级int level = 1;//角色等阶int rank=0;//角色生命值int hp=0;//角色攻击力int attack=0;//角色防御力int defense=0;//角色元素 属性string element="无";
};//特殊秘境判断 可以为5//队伍最大人数const int Teamnumber = 4;
//角色队伍
class Team {public:Team() {};~Team() {};//添加角色成员void addRole(Role& role) {//判断队伍是否已满auto&& size = roles.size();if (size < Teamnumber) {auto&& ptr = addressof(role);roles.push_back(ptr);}else {cout << "队伍已满,无法添加更多角色" << endl;}}//移除角色成员void removeRole(int roleId) {for (auto it = roles.begin(); it != roles.end(); ++it) {int is_id = (* it)->Id();if (is_id== roleId) {roles.erase(it);cout << "角色已移除" << endl;return;}}cout << "未找到该角色" << endl;}//查看队伍成员void showRoles() {cout << "队伍成员:" << endl;for (const auto& role : roles) {cout << "角色名称: " << role->Name() << endl;}}
private://队伍idint id;//队伍名称string name;//队伍中角色成员vector<Role*> roles;
};//恢复角色生命值
class RestoreHp :public FoodWeight {
public://角色队伍所对应成员恢复生命值RestoreHp() {}~RestoreHp() {};virtual void  restoreHp() override {cout << "恢复角色生命值" << endl;}virtual int  getHp() = 0;Team* m_Team;
};//日落果恢复
class SunsetFruitRestore : public RestoreHp {
public:SunsetFruitRestore() {}~SunsetFruitRestore() override {}int hp	= 100;virtual void restoreHp() override {cout << "使用日落果 恢复角色生命值" << endl;}virtual FoodWeightType getFoodWeightType() override {return FoodWeightType::RESTOREHP;}virtual int  getHp() {return hp;}
};// 食物类
class Food :public Item {
public:Food() {m_itemType = ItemType::FOOD;}//虚析构函数~Food() {}int GetId() const{ return id; }int GetNum() const { return num; }void updateAddnum()	{ num +=1; }void updateSubnum() { num -= 1; }FoodWeight* getFoodWeight() { return FoodWeight; }
protected:int num;FoodWeight* FoodWeight;
};//日落果
class Sunset:public Food{
public:Sunset() {id = 1;name = "日落果";FoodWeight = new SunsetFruitRestore();num = 1;}~Sunset() {if (FoodWeight != nullptr) {delete FoodWeight;FoodWeight = nullptr;}}};///背包类
class Knapsack {public:Knapsack() {};~Knapsack() {for (auto f : Foods) {delete f;}Foods.clear();}//添加食物void addFood(Food* food) {if (food == nullptr) {return;}if (!Foods.empty()) {auto fid = find_if(Foods.begin(), Foods.end(), [&](Item* item) {return item->GetId() == food->GetId();});//如果背包中已存在该食物 则数量加1if (fid != Foods.end()) {auto f = dynamic_cast<Food*>(*fid);f->updateAddnum();return;}}Foods.push_back(food);}//选择食物Food* selectFood(Food& foodId) {auto fid = find_if(Foods.begin(), Foods.end(), [&](const Item* item) {return item->GetId() == foodId.GetId();});if (fid != Foods.end()) {auto f = dynamic_cast<Food*>(*fid);return f;}else {cout << "背包中无该食物" << endl;return nullptr;}}//消耗食物void useFood(Food&& food) {auto func= [&](const Item* item) {return item->GetId() == food.GetId();};auto fid = find_if(Foods.begin(), Foods.end(), func);if (fid != Foods.end()) {auto f = dynamic_cast<Food*>(*fid);int num = f->GetNum();if (num > 1) {f->updateSubnum();}else {Foods.erase(fid);}}else {cout << "背包中无该食物" << endl;}}auto  getFoods() {return Foods;}private:vector<Item*>Foods;
};//使用背包恢复当前角色
void useFoodCur(Role* role, Knapsack &Knapsack) {if (role == nullptr) {cout << "当前角色为空" << endl;return;}auto f= Knapsack.getFoods();if (f.empty()) {cout << "背包中无食物" << endl;return;}int max = 10;//自动选择 最好的auto fid = find_if(f.begin(), f.end(), [&](Item* item) {auto F = (Food*)item;auto getfw = (F->getFoodWeight());return  ((SunsetFruitRestore*)getfw)->getHp() > max; });if (fid!=f.end()) {auto food = (Food*)(*fid);auto fw = food->getFoodWeight();if (fw->getFoodWeightType() == FoodWeightType::RESTOREHP) {auto rhp = dynamic_cast<RestoreHp*>(fw);rhp->m_Team = nullptr;role->sethp(role->gethp() + rhp->getHp());rhp->restoreHp();Knapsack.useFood(move(*food));}}else {cout << "背包中无合适食物" << endl;}}int main(void) {Role r1(1,"迪卢特",50,2,0,618,914,"火");Knapsack knapsack;Food* f1 = new Sunset();Food* f2= new Sunset();Food* f3 = new Sunset();Food* f4= new Sunset();Food* f5 = new Sunset();knapsack.addFood(f1);knapsack.addFood(f2);knapsack.addFood(f3);knapsack.addFood(f4);knapsack.addFood(f5);//使用背包里的食物 恢复当前角色生命值useFoodCur(& r1, knapsack );useFoodCur(&r1, knapsack);useFoodCur(&r1, knapsack);useFoodCur(&r1, knapsack);useFoodCur(&r1, knapsack);cout << "当前角色生命值为:" << r1.gethp() << endl;delete f5;delete f4;delete f3;delete f2;delete f1;return 0;
}

总结

本文介绍的游戏物品与角色管理系统具有以下优点:

  1. 模块化设计:系统各个组件职责明确,便于维护和扩展
  2. 可扩展性:通过抽象类和继承机制,可以轻松添加新的物品类型和效果
  3. 资源安全:合理的析构函数设计确保了内存管理的安全性
  4. 智能决策:系统能够根据当前状态自动选择最合适的物品使用策略

这个系统为游戏开发提供了一个坚实的基础框架,可以在此基础上进一步开发更复杂的游戏机制和功能。


文章转载自:

http://WjG2hFwP.dnmzL.cn
http://A49Ml2mr.dnmzL.cn
http://zvzzxhRK.dnmzL.cn
http://5KfwiJDd.dnmzL.cn
http://fnPzPcFc.dnmzL.cn
http://PYwUY4Tp.dnmzL.cn
http://YVK7O4gc.dnmzL.cn
http://RRSgRZ3k.dnmzL.cn
http://kvD2vJUV.dnmzL.cn
http://G3IZasY8.dnmzL.cn
http://RQI6hWOH.dnmzL.cn
http://mBxqiVd2.dnmzL.cn
http://a1EebBjt.dnmzL.cn
http://u4CuzM06.dnmzL.cn
http://YZgTcVRk.dnmzL.cn
http://QfaknyaN.dnmzL.cn
http://YKDn5fcZ.dnmzL.cn
http://boLanAok.dnmzL.cn
http://QaJt7L9u.dnmzL.cn
http://F6tx5W7X.dnmzL.cn
http://S8euJTyQ.dnmzL.cn
http://PjPrWVZ3.dnmzL.cn
http://PZ3hKSjw.dnmzL.cn
http://XSXn2EK7.dnmzL.cn
http://3cWoiiJ7.dnmzL.cn
http://bKHP83CK.dnmzL.cn
http://v0lgApfy.dnmzL.cn
http://pK65McT9.dnmzL.cn
http://vvIVTYGv.dnmzL.cn
http://LU50OvlT.dnmzL.cn
http://www.dtcms.com/a/371478.html

相关文章:

  • docker,本地目录挂载
  • The Xilinx 7 series FPGAs 设计PCB 该选择绑定哪个bank引脚,约束引脚时如何定义引脚电平标准?
  • 算法:选择排序+堆排序
  • UE4/UE5反射系统动态注册机制解析
  • 【开题答辩全过程】以 汽车知名品牌信息管理系统为例,包含答辩的问题和答案
  • rabbitmq 的 TTL
  • Linux内核网络的连接跟踪conntrack简单分析
  • Java Stream流:从入门到精通
  • java常见面试题杂记
  • SAP匈牙利新闻
  • Java全栈工程师的面试实战:从基础到高阶技术解析
  • 计算机毕设选题:基于Python+Django的B站数据分析系统的设计与实现【源码+文档+调试】
  • 【嵌入式】【树莓派】【大疆PSDK】用树莓派4B开发大疆行业无人机应用系统小结-【硬件篇】
  • 深度学习——自然语言处理NLP
  • 灾难性遗忘:神经网络持续学习的核心挑战与解决方案
  • bug | 事务粒度不能太大,含demo
  • 如何建立针对 .NET Core web 程序的线程池的长期监控
  • 41个开源大语言模型基准测试报告
  • unsloth 笔记:从最近的检查点继续微调
  • 区域导航系统 | 印度区域卫星导航系统(IRNSS/NavIC)深度解析
  • Linux服务器资源自动监控与报警脚本详解
  • 社交新零售时代本地化微商的发展路径研究——基于开源AI智能名片链动2+1模式S2B2C商城小程序源的创新实践
  • Tailwind CSS v4 终极指南:体验 Rust 驱动的闪电般性能与现代化 CSS 工作流
  • 模块--红外跟随避障模块
  • 使用MQTT.fx和ESP32连接Onenet平台
  • 功率器件固晶挑战:抗高温翘曲治具提升IGBT焊接强度30%
  • Text2Sql.Net架构深度解析:从自然语言到SQL的智能转换之道
  • UE5 基础应用 —— 10 - 控制台命令
  • Linux内核Syncookies机制:抵御SYN Flood攻击的坚实防线
  • Axum 最佳实践:如何构建优雅的 Rust 错误处理系统?(三)