基于原神游戲物品系統小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://www.pswp.cn/bicheng/96086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96086.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Grounded-Segment-Anything 環境配置

Grounded-Segment-Anything 環境配置Grounded-Segment-Anything 介紹環境配置Install osx&#xff08;非必須&#xff09;:Install RAM & Tag2Text:報錯 module ‘pkgutil‘ has no attribute ‘ImpImporter‘. Did you mean: ‘zipimporter‘?運行輸出分割文本提示檢測遠…

ZYNQ 定時器

一、ZYNQ定時器簡介 每個Cortex-A9處理器都有自己的專用32位定時器和32位看門狗定時器。兩個處理器共享一個全局64位定時器。這些計時器的時鐘始終為CPU頻率&#xff08;CPU_3x2x&#xff09;的1/2。在系統級&#xff0c;有一個24位看門狗定時器和兩個16位三重定時器/計數器。系…

Java8 Comparator接口 和 List Steam 排序使用案例

在Java中&#xff0c;Comparator接口主要用于實現自定義排序邏輯&#xff0c;適用于未實現Comparable接口或需要覆蓋默認比較規則的場景。以下是核心使用方法和注意事項&#xff1a;一、基礎用法?匿名內部類實現?傳統方式通過匿名內部類重寫compare()方法&#xff0c;例如對整…

word2vec模型案例

代碼實現&#xff1a;import torch.optim as optim from tqdm import tqdm, trange import numpy as np import torch from torch import nn import torch.nn.functional as FCONTEXT_SIZE 2raw_text """We are about to study the idea of a computational p…

< 自用文 OS 有關 > (續)發現正在被攻擊 后的自救 Fail2ban + IPset + UFW 工作流程詳解

繼上編&#xff1a;&#xff1c; 自用文 主機 USC 記錄&#xff1a;&#xff1e; 發現正在被攻擊 后的自救-CSDN博客 環境&#xff1a; 改進&#xff1a; 以下是把代碼&#xff0c;懶得寫&#xff0c;扔給了 AI &#xff0c;讓它出的&#xff1a; Fail2ban IPset UFW 工作…

Linux —— 虛擬進程地址空間

&#x1f381;個人主頁&#xff1a;工藤新一 &#x1f50d;系列專欄&#xff1a;C面向對象&#xff08;類和對象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;終會照亮我前方的路 &#x1f389;歡迎大家點贊&#x1f44d;評論&#x1f4dd;收藏?文章 文章目錄虛…

簡單聊一聊js

JavaScript 是一種高級的、解釋型的編程語言。它是現代 Web 開發的三大核心基石之一&#xff0c;與 HTML 和 CSS 并列。?HTML?&#xff1a;負責網頁的結構和內容?&#xff08;如標題、段落、圖片&#xff09;。?CSS?&#xff1a;負責網頁的樣式和布局?&#xff08;如顏色…

造粒機cad+設計說明書

摘要 隨著現代化工業的快速發展&#xff0c;生產出大量的固體廢棄物。這些廢棄物對環境造成了很大的污染&#xff0c;因此需要采取有效的措施進行處理。機械強壓式造粒機就是一種非常有效的處理工具&#xff0c;它可以將廢渣、廢料、飼料和化肥等材料通過機械強力擠壓&#xff…

第五課 C#語言基本元素概覽,初始類型,變量與方法,算法簡介

熟悉C#語言要求&#xff1a;對構成C#語言的基本元素&#xff0c;隨便拿出一個你都認識&#xff0c;對于常見基本元素&#xff0c;都能正確使用它 精通C#語言要求&#xff1a;對于構成C#語言的基本元素&#xff0c;隨便拿出一個都會使用&#xff0c;對于常用基本元素&#xff0…

LLM學習:大模型基礎——視覺大模型以及autodl使用

1、常見的VLM 在大模型中,VLM 是視覺語言模型(Vision-Language Model)的縮寫,是一種多模態、生成式 AI 模型,能夠理解和處理視頻、圖像和文本。 VLM 通過將大語言模型(LLM)與視覺編碼器相結合構建而成,使 LLM 具有 “看” 的能力,從而可以處理并提供對提示中的…

Vue—路由配置中設置了meta.title,但頁面標題仍然顯示為“Vite App“?【讓我來看看~】

路由配置中明明設置了meta.title&#xff0c;但是頁面標題仍然顯示為"Vite App"&#xff1f;這是因為僅僅在路由配置中設置meta.title是不夠的&#xff0c;還需要在路由守衛中動態設置頁面標題。需要做以下幾件事來正確設置頁面標題&#xff1a;1.首先更新HTML文件的…

【機器學習】綜合實訓(二)

項目五 電影評分預測【教學內容】使用 MovieLens 數據集&#xff0c;訓練一個模型預測用戶對電影的評分。主要有以下幾個知識點&#xff1a;&#xff08;1&#xff09;數據加載與探索性分析&#xff08;EDA&#xff09;。&#xff08;2&#xff09;處理稀疏數據&#xff08;如用…

STM32 UART + DMA + 空閑中斷使用中的幀錯誤(FE)問題及解決方案

STM32 UART + DMA + IDLE中斷使用中的幀錯誤(FE)問題及解決方案 在我調試STM32H7串口空閑中斷DMA接受時遇到了一個bug,這個現象發生在系統剛上電時,有個串口由于幀錯誤FE掛起了中斷,之后在HAL_UART_IRQHandler這個全局中斷處理函數結束后,所有的中斷使能標志位都被清除了,經過…

TDengine 選擇函數 BOTTOM() 用戶手冊

BOTTOM() 函數用戶手冊 函數定義 BOTTOM(expr, k)功能說明 BOTTOM() 函數統計表/超級表中某列的值最小 k 個非 NULL 值。如果多條數據取值一樣&#xff0c;全部取用又會超出 k 條限制時&#xff0c;系統會從相同值中隨機選取符合要求的數量返回。 返回值 數據類型: 同應用…

西門子 S7-200 SMART PLC 實現星三角降壓啟動控制:原理、案例與完整程序

在工業控制場景中&#xff0c;中型異步電機直接啟動時會產生遠超額定電流的沖擊電流&#xff08;通常為額定電流的 5-7 倍&#xff09;&#xff0c;不僅會影響電網穩定性&#xff0c;還可能對機械設備造成損傷。星三角&#xff08;Y-Δ&#xff09;降壓啟動是解決這一問題的經典…

【Android】View 的基礎知識

【Android】View 的基礎知識 1. 什么是 View&#xff1f; View 是 Android 中所有UI組件的基礎類。它表示屏幕上的一個矩形區域&#xff0c;負責繪制內容和處理用戶交互事件。所有的 UI 組件&#xff08;如按鈕、文本框等&#xff09;都是 View 的子類&#xff0c;而 ViewGroup…

西門子 S7-200 SMART PLC 實現電機點動與連續運行綜合控制

在工業生產中&#xff0c;電機控制并非單一模式&#xff1a;調試設備時需要 “按動即轉、松開即停” 的點動功能&#xff0c;正常生產時則需要 “一鍵啟動、持續運行” 的連續控制。本文以西門子 S7-200 SMART PLC 為載體&#xff0c;詳細講解電機點動控制原理&#xff0c;并設…

如何解決pip安裝報錯ModuleNotFoundError: No module named ‘sphinx-rtd-theme’問題

【Python系列Bug修復PyCharm控制臺pip install報錯】如何解決pip安裝報錯ModuleNotFoundError: No module named ‘sphinx-rtd-theme’問題 摘要 在使用 PyCharm 開發 Python 項目時&#xff0c;pip install 報錯是常見痛點。特別是在構建文檔或引入第三方庫時&#xff0c;開…

HakcMyVM-Literal

目錄信息搜集漏洞利用權限提升信息搜集 主機發現 ┌──(kali?kali)-[~] └─$ nmap -sn 192.168.21.0/24 Nmap scan report for 192.168.21.5端口掃描 ┌──(kali?kali)-[~] └─$ nmap -sS -sV -O -p- 192.168.21.5 Starting Nmap 7.95 ( https://nmap.org ) a…

0904 類的繼承

Part 1.梳理思維導圖一.繼承中的特殊成員函數1.構造函數父類的構造函數會被繼承到子類中&#xff0c;在構造的順序中&#xff0c;是先構造父類&#xff0c;再構造子類#include <iostream>using namespace std;class Father { public:string name; protected:int *age; pr…