UE4纯C++实现游戏快捷栏之物品读取

我们在上一步骤中创建了快捷栏的UI界面,在这一部分我们将从Json文件中读取物品的相关信息(种类以及属性),来填充到游戏数据中进行存储以便快捷栏使用,具体分以下几部分完成。

  1.Types.h:

添加物品类型、物品属性结构体(成员变量及初始化函数)

 1 // 物品类型
 2 namespace EObjectType
 3 {
 4     enum Type
 5     {
 6         Normal = 0,    // 普通物品:木头、石头
 7         Food,        // 食物:苹果、肉
 8         Tool,        // 工具:锤子、斧子
 9         Weapon        // 武器:剑
10     };
11 }
12 
13 // 物品属性结构体
14 struct ObjectAttribute 
15 {
16     FText EN;    // 英文名
17     FText ZH;    // 中文名
18     EObjectType::Type ObjectType;    // 物品类型
19     int PlantAttack;    // 对植物的攻击力
20     int MetalAttack;    // 对金属资源的攻击力
21     int AnimalAttack;    // 对动物的攻击力
22     int AffectRange;    // 攻击距离
23     FString TexPath;    // 图片路径
24 
25     // 构造函数
26     ObjectAttribute(const FText ENName, const FText ZHName, const EObjectType::Type OT, const int PA, const int MA,
27         const int AA, const int AR, const FString TP) : EN(ENName), ZH(ZHName), ObjectType(OT), PlantAttack(PA),
28         MetalAttack(MA), AnimalAttack(MA), AffectRange(AR), TexPath(TP)
29     {}
30 
31 };
View Code

  2.JsonHandle.h:

添加物品解析(解析函数、文件名、路径)、从string解析ObjectType

 1 {
 2 public:
 3     
 4 
 5     // 解析物品属性
 6     void ObjectAttrJsonRead(TMap<int, TSharedPtr<ObjectAttribute>>& ObjectAttrMap);
 7 
 8 private:
 9 
10     
11     // 定义一个从 FString 转换到 ObjectType 的方法
12     EObjectType::Type StringToObjectType(const FString ArgStr);
13 
14 private:
15 
16     FString RecordDataFileName;
17 
18     // 物品属性文件名
19     FString ObjectAttrFileName;
20 
21     FString RelativePath;
22 };
View Code

  3.JsonHandle.cpp:

构造函数:绑定Json文件路径、

ObjectAttrJsonRead函数:读取物品信息表的Json文件,将物品列表根据id为key信息为value存于ObjectAttrMap中、

StringToObjectType函数:解析string描述的类型获取到ObjectType描述的类型(当然也可以借助ue的反射系统)

 1 SlAiJsonHandle::SlAiJsonHandle()
 2 {
 3     RecordDataFileName = FString("RecordData.json");
 4     // 添加物品属性的 Json 文件路径
 5     ObjectAttrFileName = FString("ObjectAttribute.json");
 6 
 7     RelativePath = FString("Res/ConfigData/");
 8 }
 9 
10 // 读取物品的 Json 信息
11 void SlAiJsonHandle::ObjectAttrJsonRead(TMap<int, TSharedPtr<ObjectAttribute>>& ObjectAttrMap)
12 {
13     FString JsonValue;
14     LoadStringFromFile(ObjectAttrFileName, RelativePath, JsonValue);
15 
16     TArray<TSharedPtr<FJsonValue>> JsonParsed;
17     TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonValue);
18 
19     if (FJsonSerializer::Deserialize(JsonReader, JsonParsed)) {
20         for (int i = 0; i < JsonParsed.Num(); ++i) {
21             TArray<TSharedPtr<FJsonValue>> ObjectAttr = JsonParsed[i]->AsObject()->GetArrayField(FString::FromInt(i));
22             FText EN = FText::FromString(ObjectAttr[0]->AsObject()->GetStringField("EN"));
23             FText ZH = FText::FromString(ObjectAttr[1]->AsObject()->GetStringField("ZH"));
24             FString ObjectTypeStr = ObjectAttr[2]->AsObject()->GetStringField("ObjectType");
25             int PlantAttack = ObjectAttr[3]->AsObject()->GetIntegerField("PlantAttack");
26             // 老师的变量名打错了,如果像我这样把 MetalAttcck 改成 MetalAttack 的话,Json 文件
27             // 里面的对象名记得改一下
28             int MetalAttack = ObjectAttr[4]->AsObject()->GetIntegerField("MetalAttack");
29             int AnimalAttack = ObjectAttr[5]->AsObject()->GetIntegerField("AnimalAttack");
30             int AffectRange = ObjectAttr[6]->AsObject()->GetIntegerField("AffectRange");
31             FString TexPath = ObjectAttr[7]->AsObject()->GetStringField("TexPath");
32             
33             EObjectType::Type ObjectType = StringToObjectType(ObjectTypeStr);
34             TSharedPtr<ObjectAttribute> ObjectAttrPtr = MakeShareable(new ObjectAttribute(EN, ZH, ObjectType, PlantAttack, MetalAttack, AnimalAttack, AffectRange, TexPath));
35             
36             ObjectAttrMap.Add(i, ObjectAttrPtr);
37         }
38     }
39     else {
40         SlAiHelper::Debug(FString("Deserialize Failed"));
41     }
42 }
43 
44 
45 // 这里硬编码是因为数据结构类里面,这个枚举类型没有添加反射宏,没办法用 SlAiDataHandle 里的类似代码
46 // 如果读者想写得通用些的话参考 SlAiDataHandle 的类似代码
47 EObjectType::Type StringToObjectType(const FString ArgStr)
48 {
49     if (ArgStr.Equals(FString("Normal"))) return EObjectType::Normal;
50     if (ArgStr.Equals(FString("Food"))) return EObjectType::Food;
51     if (ArgStr.Equals(FString("Tool"))) return EObjectType::Tool;
52     if (ArgStr.Equals(FString("Weapon"))) return EObjectType::Weapon;
53     return EObjectType::Normal;
54 }
View Code

   4.DataHandle.h

添加在游戏中存储物品信息列表的ObjectAttrMap

创建给所有游戏数据初始化的InitializeGameData()函数

创建给ObjectAttrMap初始化的InitObjectAttr()函数

 1 class SLAICOURSE_API SlAiDataHandle
 2 {
 3 public:
 4 
 5     // 游戏数据初始化
 6     void InitializeGameData();
 7 
 8 public:
 9     // 物品属性图
10     TMap<int, TSharedPtr<ObjectAttribute>> ObjectAttrMap;
11 
12 private:
13 
14     // 初始化物品属性图
15     void InitObjectAttr();
16 };
View Code

  5.DataHandle.cpp

InitializeGameData()函数:调用初始化ObjectAttrMap的InitObjectAttr()函数

InitObjectAttr()函数:调用JsonHandle提供的ObjectAttrJsonRead函数,从Json文件中读取物品集数据并填充到ObjectAttrMap中完成初始化

 1 void SlAiDataHandle::InitializeGameData()
 2 {
 3     // 初始化物品属性图
 4     InitObjectAttr();
 5 }
 6 
 7 void SlAiDataHandle::InitObjectAttr()
 8 {
 9     SlAiSingleton<SlAiJsonHandle>::Get()->ObjectAttrJsonRead(ObjectAttrMap);
10 
11 }
View Code

  6.GameMode.cpp

BeginPlay()函数:调用DataHandle的InitializeGameData()函数,在游戏开始前完成对游戏所需数据的初始化

1 void ASlAiGameMode::BeginPlay()
2 {
3     // 初始化游戏数据
4     SlAiDataHandle::Get()->InitializeGameData();
5 }
View Code

 

posted @ 2024-04-23 00:18  七星易  阅读(23)  评论(0编辑  收藏  举报