我們在上一步驟中建立了快捷欄的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存在ObjectAttrMap中)、StringToObjectType函式解析string到ObjectType
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 }