独立游戏《星尘异变》UE5 C++程序开发日志3——实现一个存存组件

本篇日志中,我将会介绍如何实现一个有格子,每个格子有容量的物品库存,如下图:

一.库存容器

1.储存数据的容器

        库存容器最重要的目的就是存储每一种类的物品拥有的数量,这里我用的是哈希表:

std::unordered_map<std::string, int>StardustCount;//从星尘ID到存储的数量的映射

哈希表的优点就是查询速度极快,我们的的库存在每次发生“反应”,进口等过程时都要进行数量的查询,所以要尽可能降低查询的复杂度,这也就是为什么我们不用TMap,因为TMap在每次使用"[]"运算符前,要检查其是否含有要查询的元素。

        而他的优点就是不便于展示,因为我们要实现的库存是有有格子,每个格子有存储上限的容器,所以我们要再定义一个数组,数组中的每一个索引对应的就是展示的一个格子:

2.显示数据的容器

	UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category="Storage")TArray<UStardustItemClass*>Storage;//输入仓库

        数组中的数据类型是一个UObject指针,该UObject内除了上一篇日志中展示的数据外,多了一个该槽位物品数量的变量"Quantity":


USTRUCT(BlueprintType)
struct FStardustItem
{GENERATED_BODY();UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "StardustBase")FName StardustName{"Empty"};//名称UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "StardustBase")FText Description;//描述UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "StardustBase")FName StardustId{ "Empty" };//编号UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "StardustBase")FStardustStatisticsForReaction ReactionStatistics{FStardustStatisticsForReaction()};//反应数据UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "StardustBase")FStardustStatisticsForInventory InventoryStatistics{FStardustStatisticsForInventory()};//库存数据UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "StardustBase", meta = (UIMin = 1))int Quantity{0};//数量FStardustItem() = default;explicit FStardustItem(const FStardustDataTable& Stardust){StardustId = Stardust.StardustId;StardustName = Stardust.StardustName;Description = Stardust.Description;Quantity = 0;ReactionStatistics = Stardust.ReactionStatistics;InventoryStatistics = Stardust.InventoryStatistics;}void SetQuantity(int Num)//设置该槽位内的星尘数量{if (Num > 0){Quantity =  Num;}else{//数量为0就将其替换成默认空的物品*this = FStardustItem();};}};UCLASS(BlueprintType)
class ASTROMUTATE_2_API UStardustItemClass : public UObject
{GENERATED_BODY()
public://物品信息UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category="StardustItem")FStardustItem ItemData;};

3.库存的其他数据

        我们游戏中的库存不是无限大的,所有有一个最大的槽位数,该变量可能受游戏中的因素影响,上面的数组大小始终等于该变量大小

        然后我们还需要加载全局单例,后面需要用到上一篇日志中提到过的“星尘”数据表

//仓库槽位数
UPROPERTY(EditAnywhere, BlueprintReadWrite, category = "StardustInventory")
int SlotsCapacity;
//全局单例,用于查询数据表中的物品数据
UPROPERTY()
class UAstromutateGameInstance* Instance;
//在.cpp的BeginPlay中实例化Instance
//Instance = Cast<UAstromutateGameInstance>(GetWorld()->GetGameInstance());

二.容器的查询

        因为我们之前实现过哈希表,所以可以直接O(1)查询某物品在库存中的容量

UFUNCTION(BlueprintCallable, Category = "StardustInventory")
FORCEINLINE int CheckStardust(FName StardustType) {return StardustCount[TCHAR_TO_UTF8(*StardustType.ToString())];};//从映射中O(1)查询其在库存中的数量	

        我们还有一个查询某物品在库存中还能添加多少的函数,也是利用哈希表O(1)实现

//.h中的声明
//检查星尘在库存中还能添加多少
UFUNCTION(BlueprintCallable, Category = "StardustInventory")
int CheckAddable(const FName& StardustId);//.cpp中的实现
nt UStarInventoryComponent::CheckAddable(const FName& StardustId)
{std::string StardustIdString{ TCHAR_TO_UTF8(*StardustId.ToString()) };//将FName转换成std::stringint StackLimit{ Instance->StardustMap[StardustIdString]->InventoryStatistics.StardustStackLimit };//该类物品的堆叠上限int AvailableInPartial{ StackLimit - StardustCount[StardustIdString] % StackLimit };//该类物品在非空槽位中还能装多少if (StardustCount[StardustIdString] % StackLimit == 0)//所有物品的堆叠上限不能为0{AvailableInPartial = 0;}int AvailableInEmptySlots = StardustCount["Empty"] * StackLimit;//在空槽位中可放的数量return AvailableInEmptySlots + AvailableInPartial;
}

三.库存的修改

        我们库存中的增加和删除操作都是基于对单个槽位的修改实现的,传入参数是期望的“星尘”,用的是完整的槽位中物品的结构,返回值为是否修改成功,修改时需要同时维护数组和哈希表:

bool UStarInventoryComponent::SetSlotElement(const FName StardustId,const int Amount, int index)
{if (index < 0 || index >= Storage.Num()){//检查索引是否合法UE_LOG(LogTemp, Error, TEXT("se slot at %d failed,invalid index"), index);return false;}int OriginalAmount = Storage[index]->ItemData.GetQuantity();	FName OriginalId = Storage[index]->ItemData.StardustId;StardustCount[TCHAR_TO_UTF8(*Storage[index]->ItemData.StardustId.ToString())] -= OriginalAmount;//先将这一格清空//如果星尘是新加进来的,就要将表格中的数据赋给新星尘std::string NewStardustId{ TCHAR_TO_UTF8(*StardustId.ToString()) };FStardustTable StardustInfo= *Instance->StardustMap[NewStardustId];int StackLimit = StardustInfo.InventoryStatistics.StardustStackLimit;//将新星辰的数据覆盖原星辰Storage[index]->ItemData = FStardustItem(StardustInfo);if (Amount > StackLimit){//超出堆叠上限的部分直接抛弃if (OriginalId == "Empty" && Storage[index]->ItemData.StardustId != "Empty"){StardustCount["Empty"]--;}if (OriginalId != "Empty" && Storage[index]->ItemData.StardustId == "Empty"){StardustCount["Empty"]++;}StardustCount[NewStardustId] += StackLimit;Storage[index]->ItemData.SetQuantity(StackLimit);return true;}if (Amount <= 0){//将该槽位的星尘替换成空星尘StardustCount["Empty"]++;Storage[index]->ItemData.SetQuantity(Amount);return true;}if (OriginalId == "Empty" && Storage[index]->ItemData.StardustId != "Empty"){StardustCount["Empty"]--;}if (OriginalId != "Empty" && Storage[index]->ItemData.StardustId == "Empty"){StardustCount["Empty"]++;}//正常更改数量Storage[index]->ItemData.SetQuantity(Amount);StardustCount[NewStardustId] += Amount;return true;
}

        我们还有一个整理背包的函数,可以实现将库存中同类物品尽可能放在一起:        

持续更新中。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/12123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

huggingface:利用git克隆目标资源

前言 因为有很多模型资源都被放在了huggingface上&#xff0c;为了下载它们&#xff0c;着实让一个不懂git的人犯了难&#xff0c;绕了很多远路&#xff0c;甚至将不需要解决的问题也都拿上了台面&#xff0c;因此我将在本篇博客中记载一些关于【huggingface】中利用git克隆目标…

【c++】全面理解C++多态:虚函数表深度剖析与实践应用

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;通过本篇文章&#xff0c;来详细理解多态的内容 目录 1.多态的定义及实现1.1多态的构成条件1.2虚函数的重写1.3 C11 override 和 final1.4重载、覆盖(重写)、隐藏…

鸿蒙内核源码分析 (内核启动篇) | 从汇编到 main ()

这应该是系列篇最难写的一篇&#xff0c;全是汇编代码&#xff0c;需大量的底层知识&#xff0c;涉及协处理器&#xff0c;内核镜像重定位&#xff0c;创建内核映射表&#xff0c;初始化 CPU 模式栈&#xff0c;热启动&#xff0c;到最后熟悉的 main() 。 内核入口 在链接文件…

在k8s中安装Grafana并对接Prometheus,实现k8s集群监控数据的展示

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Grafana&#xff1a;让数据说话的魔术师》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Grafana简介 2、Grafana的重要性与影响力 …

强化训练:day9(添加逗号、跳台阶、扑克牌顺子)

文章目录 前言1. 添加逗号1.1 题目描述2.2 解题思路2.3 代码实现 2. 跳台阶2.1 题目描述2.2 解题思路2.3 代码实现 3. 扑克牌顺子3.1 题目描述3.2 解题思路3.3 代码实现 总结 前言 1. 添加逗号   2. 跳台阶   3. 扑克牌顺子 1. 添加逗号 1.1 题目描述 2.2 解题思路 我的写…

STM32学习和实践笔记(28):printf重定向实验

1.printf重定向简介 在C语言中printf函数里&#xff0c;默认输出设备是显示器&#xff0c;如果想要用这个函数将输出结果到串口或者LCD上显示&#xff0c;就必须重定义标准库函数里中printf函数调用的与输出设备相关的函数。 比如要使用printf输出到串口&#xff0c;需要先将f…

linux 任务管理(临时任务定时任务) 实验

目录 任务管理临时任务管理周期任务管理 任务管理 临时任务管理 执行如下命令添加单次任务&#xff0c;输入完成后按组合键Ctrl-D。 [rootopenEuler ~]# at now5min warning: commands will be executed using /bin/sh at> echo "aaa" >> /tmp/at.log at&g…

J-STAGE (日本电子科学与技术信息集成)数据库介绍及文献下载

J-STAGE (日本电子科学与技术信息集成)是日本学术出版物的平台。它由日本科学技术振兴机构&#xff08;JST&#xff09;开发和管理。该系统不仅包括期刊&#xff0c;还有论文集&#xff0c;研究报告、技术报告等。文献多为英文&#xff0c;少数为日文。目前网站上所发布的内容来…

使用Vue调用ColaAI Plus大模型,实现聊天(简陋版)

首先去百度文心注册申请自己的api 官网地址&#xff1a;LuckyCola 注册点开个人中心 查看这个文档自己申请一个ColaAI Plus定制增强大模型API | LuckyColahttps://luckycola.com.cn/public/docs/shares/api/colaAi.html来到vue的页面 写个样式 <template><Header …

ICode国际青少年编程竞赛- Python-5级训练场-综合练习6

ICode国际青少年编程竞赛- Python-5级训练场-综合练习6 1、 for i in range(3):Dev.step(2 * (i 1))Dev.turnLeft()while Flyer[2 - i].disappear():wait()Dev.step(2 * (i 1))Dev.turnRight()while Dev.x ! Item[i].x:wait()2、 for i in range(3):Dev.step(2 * i 1)while …

用Python的pynput库成为按键记录高手

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 揭秘键盘输入&#xff1a;pynput库的基本介绍 无论是为了安全审计、数据分析还是创建热键操作&#xff0c;能够记录和处理键盘事件都显得尤为关键。这就是pynput库发挥作用的地方。pynput是一个Python库&#xff0c…

Java 对象序列化

序列化&#xff1a;把对象转化为可传输的字节序列过程称为序列化。 反序列化&#xff1a;把字节序列还原为对象的过程称为反序列化 序列化的作用是方便存储和传输&#xff0c;细节可参考如下文章&#xff1a; 序列化理解起来很简单 - 知乎序列化的定义 序列化&#xff1a;把对…

echarts map地图添加背景图

给map地图添加了一个阴影3d的效果&#xff0c;添加一张背景图&#xff0c;给人感觉有3d的效果 具体配置如下&#xff1a; html代码模块&#xff1a; <div class"echart_img" style"position: fixed; visibility: hidden;"></div><div id&q…

Autoware内容学习与初步探索(一)

0. 简介 之前作者主要是基于ROS2&#xff0c;CyberRT还有AutoSar等中间件完成搭建的。有一说一&#xff0c;这种从头开发当然有从头开发的好处&#xff0c;但是如果说绝大多数的公司还是基于现成的Apollo以及Autoware来完成的。这些现成的框架中也有很多非常好的方法。目前作者…

【Java的抽象类和接口】

1. 抽象类 1.1 抽象类概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果 一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类。 以上代码中…

Leaflet系列——【一】初识Leaflet与Leaflet视图操作

初识Leaflet&#xff08;vue3 &#xff09; 前言&#xff1a;当你熟悉了openlayer、mapbox、cesium等一些GIS框架之后&#xff0c;对于我们开发来说其实他们的本质就是往瓦片上面叠加图层、【点、线、面、瓦片、geoJson、热力图、图片、svg等等】都是一层层的Layer图层&#xf…

Ceph集群扩容及数据再均衡原理分析

用户文件在Ceph RADOS中存储、定位过程大概包括&#xff1a;用户文件切割成对象、对象映射到PG、PG分组PGP、PG映射到OSD。这些过程中&#xff0c;可能涉及了大量概念和变量&#xff0c;而其实它们大部分是通过HASH、CRUSH等算法计算出来的&#xff0c;初始参数可能也就只有这么…

sql实践

1.从excel导入数据 在excel导入数据时要先在数据库中创建对应的数据库表 CREATE TABLE your_table_name (crawl_datetime DATE,url CHAR(255),company_name CHAR(255),company_size CHAR(255),company_type CHAR(255),job_type CHAR(255),job_name CHAR(255),edu CHAR(255),e…

暗区突围TWITCH掉宝关联帐号不了 无法关联帐号 关联不上

Twitch&#xff0c;作为全球知名的游戏直播平台&#xff0c;常常携手热门游戏如《暗区突围》举办互动活动&#xff0c;为玩家带来独特的参与体验。在这个过程中&#xff0c;“绑定关联”成为了连接直播观众与游戏世界的桥梁。简单来说&#xff0c;Twitch绑定关联《暗区突围》指…

leetcode——链表的中间节点

876. 链表的中间结点 - 力扣&#xff08;LeetCode&#xff09; 链表的中间节点是一个简单的链表OJ。我们要返回中间节点有两种情况&#xff1a;节点数为奇数和节点数是偶数。如果是奇数则直接返回中间节点&#xff0c;如果是偶数则返回第二个中间节点。 这道题的解题思路是&a…