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

概述

本文介绍了一个基于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;
}

总结

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

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

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

相关推荐
宁檬精5 小时前
算法练习——55.跳跃游戏
数据结构·算法·游戏
wanhengidc6 小时前
高性价比云手机挑选指南
运维·网络·安全·游戏·智能手机
m0_5522008212 小时前
《UE5_C++多人TPS完整教程》学习笔记48 ——《P49 瞄准偏移(Aim Offset)》
c++·游戏·ue5
wanhengidc13 小时前
云手机可以用来托管游戏吗?
运维·网络·安全·游戏·智能手机
伽蓝_游戏14 小时前
UGUI源码剖析(15):Slider的运行时逻辑与编辑器实现
游戏·ui·unity·性能优化·c#·游戏引擎·.net
颯沓如流星1 天前
SLG游戏中沙盘元素(通常指资源点、野怪、宝箱等可交互对象)的刷新设计
游戏
m0_552200821 天前
《UE5_C++多人TPS完整教程》学习笔记49 ——《P50 应用瞄准偏移(Applying Aim Offset)》
c++·游戏·ue5
m0_552200821 天前
《UE5_C++多人TPS完整教程》学习笔记50 ——《P51 多人游戏中的俯仰角(Pitch in Multiplayer)》
c++·游戏·ue5
红红大虾1 天前
前台小姐姐10分钟就能掌握的Defold游戏引擎需要的lua入门知识
游戏