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 };
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 };
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 }
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 };
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 }
6.GameMode.cpp
BeginPlay()函数:调用DataHandle的InitializeGameData()函数,在游戏开始前完成对游戏所需数据的初始化
1 void ASlAiGameMode::BeginPlay() 2 { 3 // 初始化游戏数据 4 SlAiDataHandle::Get()->InitializeGameData(); 5 }