概述
本文介绍了一个基于C++的游戏物品与角色管理系统,该系统实现了游戏中的物品分类、角色属性管理、队伍组建以及背包物品使用等功能。该系统采用面向对象的设计原则,通过继承和多态实现了可扩展的物品效果系统。
系统架构
1. 物品类型系统
系统定义了三种物品类型,通过枚举类ItemType
实现:
cpp
enum class ItemType {
FOOD, // 食物:可恢复角色属性
PROP, // 养成道具:用于角色培养
MATERIAL, // 材料:用于合成或制作
};
2. 物品基类设计
物品基类Item
作为抽象类,定义了所有物品的共同属性和接口:
cpp
class Item {
public:
Item() {};
int GetId() const { return id; }
virtual~Item() = 0;
protected:
int id; // 物品唯一标识
ItemType m_itemType; // 物品类型
string name; // 物品名称
};
3. 食物效果系统
系统通过抽象类FoodWeight
和其派生类实现了多种食物效果:
cpp
class FoodWeight {
public:
FoodWeight() {};
virtual ~FoodWeight() = 0;
virtual void restore() {};
virtual void showRestore() {};
virtual void restoreHp() {};
virtual FoodWeightType getFoodWeightType() = 0;
};
4. 角色管理系统
Role
类封装了游戏角色的各项属性:
cpp
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名角色的队伍管理功能:
cpp
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
类和其派生类实现了具体的食物物品:
cpp
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
类实现了物品的存储、检索和使用功能:
cpp
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
类实现了日落果的生命恢复效果:
cpp
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. 智能的物品使用策略
系统提供了智能的食物选择机制,可以根据角色需求自动选择最适合的食物:
cpp
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. 安全的资源管理
系统通过适当的析构函数实现,确保了动态分配的内存得到正确释放:
cpp
~Knapsack() {
for (auto f : Foods) {
delete f;
}
Foods.clear();
}
~Sunset() {
if (FoodWeight != nullptr) {
delete FoodWeight;
FoodWeight = nullptr;
}
}
应用示例
系统提供了一个完整的使用示例,展示了如何创建角色、食物,以及如何使用食物恢复角色生命值:
cpp
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;
}
完整代码
cpp
#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:
//物品id
int 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() {};
//角色id
int Id() { return id; }
//角色名称
string Name() { return name; }
//设置生命值
void sethp(int hp) {
this->hp = hp;
}
//获取生命值
int gethp() {
return hp;
}
private:
//角色id
int 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:
//队伍id
int 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();
});
//如果背包中已存在该食物 则数量加1
if (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;
}
总结
本文介绍的游戏物品与角色管理系统具有以下优点:
- 模块化设计:系统各个组件职责明确,便于维护和扩展
- 可扩展性:通过抽象类和继承机制,可以轻松添加新的物品类型和效果
- 资源安全:合理的析构函数设计确保了内存管理的安全性
- 智能决策:系统能够根据当前状态自动选择最合适的物品使用策略
这个系统为游戏开发提供了一个坚实的基础框架,可以在此基础上进一步开发更复杂的游戏机制和功能。