added load npcs from json
This commit is contained in:
parent
b3fda88784
commit
943b6b4d21
36
resources/config2/npcs.json
Normal file
36
resources/config2/npcs.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"npcs": [
|
||||||
|
{
|
||||||
|
"id": "npc_01_default",
|
||||||
|
"name": "NPC Default Guard",
|
||||||
|
"texturePath": "resources/w/default_skin001.png",
|
||||||
|
"animationIdlePath": "resources/w/default_idle002.txt",
|
||||||
|
"animationWalkPath": "resources/w/default_walk001.txt",
|
||||||
|
"positionX": 0.0,
|
||||||
|
"positionY": 0.0,
|
||||||
|
"positionZ": -10.0,
|
||||||
|
"walkSpeed": 1.5,
|
||||||
|
"rotationSpeed": 8.0,
|
||||||
|
"modelScale": 0.01,
|
||||||
|
"modelCorrectionRotX": 0.0,
|
||||||
|
"modelCorrectionRotY": 180.0,
|
||||||
|
"modelCorrectionRotZ": 0.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "npc_02_ghost",
|
||||||
|
"name": "NPC Floating Ghost",
|
||||||
|
"texturePath": "resources/w/ghost_skin001.png",
|
||||||
|
"animationIdlePath": "resources/w/default_float001.txt",
|
||||||
|
"animationWalkPath": "resources/w/default_float001.txt",
|
||||||
|
"positionX": 0.0,
|
||||||
|
"positionY": 0.0,
|
||||||
|
"positionZ": -20.0,
|
||||||
|
"walkSpeed": 1.5,
|
||||||
|
"rotationSpeed": 8.0,
|
||||||
|
"modelScale": 0.01,
|
||||||
|
"modelCorrectionRotX": 0.0,
|
||||||
|
"modelCorrectionRotY": 180.0,
|
||||||
|
"modelCorrectionRotZ": 0.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -14,9 +14,9 @@ void Character::loadAnimation(AnimationState state, const std::string& filename,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::setTexture(std::shared_ptr<Texture> tex) {
|
/*void Character::setTexture(std::shared_ptr<Texture> tex) {
|
||||||
texture = tex;
|
texture = tex;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void Character::setTarget(const Eigen::Vector3f& target,
|
void Character::setTarget(const Eigen::Vector3f& target,
|
||||||
std::function<void()> onArrived) {
|
std::function<void()> onArrived) {
|
||||||
|
|||||||
@ -18,7 +18,10 @@ enum class AnimationState {
|
|||||||
class Character {
|
class Character {
|
||||||
public:
|
public:
|
||||||
void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
|
void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
|
||||||
void setTexture(std::shared_ptr<Texture> texture);
|
// void setTexture(std::shared_ptr<Texture> texture);
|
||||||
|
void setTexture(std::shared_ptr<Texture> texture) {
|
||||||
|
this->texture = texture;
|
||||||
|
}
|
||||||
void update(int64_t deltaMs);
|
void update(int64_t deltaMs);
|
||||||
// onArrived is called once when the character reaches this target.
|
// onArrived is called once when the character reaches this target.
|
||||||
// From Python you can chain further commands (walk, wait, trigger others).
|
// From Python you can chain further commands (walk, wait, trigger others).
|
||||||
|
|||||||
10
src/Game.cpp
10
src/Game.cpp
@ -169,6 +169,13 @@ namespace ZL
|
|||||||
Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));
|
Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));
|
||||||
|
|
||||||
std::cout << "Load resurces step 9" << std::endl;
|
std::cout << "Load resurces step 9" << std::endl;
|
||||||
|
|
||||||
|
// Load NPCs from JSON
|
||||||
|
npcs = GameObjectLoader::loadAndCreateNpcs("resources/config2/npcs.json", CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// === СТАРЫЙ КОД - ЗАКОММЕНТИРОВАНО, НПС ТЕПЕРЬ ГРУЗЯТСЯ ИЗ JSON ===
|
||||||
|
|
||||||
auto defaultTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/default_skin001.png", CONST_ZIP_FILE));
|
auto defaultTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/default_skin001.png", CONST_ZIP_FILE));
|
||||||
|
|
||||||
auto npc01 = std::make_unique<Character>();
|
auto npc01 = std::make_unique<Character>();
|
||||||
@ -207,6 +214,9 @@ namespace ZL
|
|||||||
npcs.push_back(std::move(npc02));
|
npcs.push_back(std::move(npc02));
|
||||||
|
|
||||||
std::cout << "Load resurces step 12" << std::endl;
|
std::cout << "Load resurces step 12" << std::endl;
|
||||||
|
|
||||||
|
// === КОНЕЦ СТАРОГО КОДА ===
|
||||||
|
*/
|
||||||
|
|
||||||
loadingCompleted = true;
|
loadingCompleted = true;
|
||||||
|
|
||||||
|
|||||||
@ -244,4 +244,134 @@ namespace ZL {
|
|||||||
return interactiveObjects;
|
return interactiveObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<NpcData> GameObjectLoader::loadNpcsFromJson(const std::string& jsonPath, const std::string& zipPath)
|
||||||
|
{
|
||||||
|
std::vector<NpcData> npcs;
|
||||||
|
json j;
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::ifstream file(jsonPath);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
throw std::runtime_error("Could not open file: " + jsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.peek() == std::ifstream::traits_type::eof()) {
|
||||||
|
throw std::runtime_error("JSON file is empty: " + jsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
file >> j;
|
||||||
|
|
||||||
|
if (!j.contains("npcs") || !j["npcs"].is_array()) {
|
||||||
|
std::cerr << "Warning: 'npcs' array not found in " << jsonPath << std::endl;
|
||||||
|
return npcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& item : j["npcs"]) {
|
||||||
|
NpcData data;
|
||||||
|
|
||||||
|
data.id = item.value("id", "npc_unknown");
|
||||||
|
data.name = item.value("name", "Unknown NPC");
|
||||||
|
data.texturePath = item.value("texturePath", "");
|
||||||
|
data.animationIdlePath = item.value("animationIdlePath", "");
|
||||||
|
data.animationWalkPath = item.value("animationWalkPath", "");
|
||||||
|
|
||||||
|
data.positionX = item.value("positionX", 0.0f);
|
||||||
|
data.positionY = item.value("positionY", 0.0f);
|
||||||
|
data.positionZ = item.value("positionZ", 0.0f);
|
||||||
|
|
||||||
|
data.walkSpeed = item.value("walkSpeed", 1.5f);
|
||||||
|
data.rotationSpeed = item.value("rotationSpeed", 8.0f);
|
||||||
|
data.modelScale = item.value("modelScale", 0.01f);
|
||||||
|
|
||||||
|
// Model correction rotation (in degrees, will convert to radians)
|
||||||
|
data.modelCorrectionRotX = item.value("modelCorrectionRotX", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
||||||
|
data.modelCorrectionRotY = item.value("modelCorrectionRotY", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
||||||
|
data.modelCorrectionRotZ = item.value("modelCorrectionRotZ", 0.0f) * static_cast<float>(M_PI) / 180.0f;
|
||||||
|
|
||||||
|
npcs.push_back(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Successfully loaded " << npcs.size() << " NPCs from " << jsonPath << std::endl;
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Error loading NPCs from JSON: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return npcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Character>> GameObjectLoader::loadAndCreateNpcs(
|
||||||
|
const std::string& jsonPath,
|
||||||
|
const std::string& zipPath)
|
||||||
|
{
|
||||||
|
std::vector<std::unique_ptr<Character>> npcs;
|
||||||
|
std::vector<NpcData> npcsData = loadNpcsFromJson(jsonPath, zipPath);
|
||||||
|
|
||||||
|
for (const auto& npcData : npcsData) {
|
||||||
|
std::cout << "Loading NPC: " << npcData.name << std::endl;
|
||||||
|
|
||||||
|
auto npc = std::make_unique<Character>();
|
||||||
|
|
||||||
|
// Load animations
|
||||||
|
try {
|
||||||
|
npc->loadAnimation(AnimationState::IDLE, npcData.animationIdlePath, zipPath);
|
||||||
|
std::cout << " Loaded IDLE animation: " << npcData.animationIdlePath << std::endl;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
std::cerr << "GameObjectLoader: Failed to load IDLE animation for '" << npcData.name << "': " << e.what() << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
npc->loadAnimation(AnimationState::WALK, npcData.animationWalkPath, zipPath);
|
||||||
|
std::cout << " Loaded WALK animation: " << npcData.animationWalkPath << std::endl;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
std::cerr << "GameObjectLoader: Failed to load WALK animation for '" << npcData.name << "': " << e.what() << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load texture
|
||||||
|
try {
|
||||||
|
auto texture = std::make_shared<Texture>(CreateTextureDataFromPng(npcData.texturePath, zipPath.c_str()));
|
||||||
|
npc->setTexture(texture);
|
||||||
|
std::cout << " Loaded texture: " << npcData.texturePath << std::endl;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
std::cerr << "GameObjectLoader: Failed to load texture for '" << npcData.name << "': " << e.what() << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set NPC properties
|
||||||
|
npc->walkSpeed = npcData.walkSpeed;
|
||||||
|
npc->rotationSpeed = npcData.rotationSpeed;
|
||||||
|
npc->modelScale = npcData.modelScale;
|
||||||
|
npc->position = Eigen::Vector3f(npcData.positionX, npcData.positionY, npcData.positionZ);
|
||||||
|
|
||||||
|
// Set model correction rotation
|
||||||
|
Eigen::Quaternionf corrRotQuat = Eigen::Quaternionf::Identity();
|
||||||
|
if (npcData.modelCorrectionRotX != 0.0f) {
|
||||||
|
corrRotQuat = Eigen::Quaternionf(Eigen::AngleAxisf(npcData.modelCorrectionRotX, Eigen::Vector3f::UnitX())) * corrRotQuat;
|
||||||
|
}
|
||||||
|
if (npcData.modelCorrectionRotY != 0.0f) {
|
||||||
|
corrRotQuat = Eigen::Quaternionf(Eigen::AngleAxisf(npcData.modelCorrectionRotY, Eigen::Vector3f::UnitY())) * corrRotQuat;
|
||||||
|
}
|
||||||
|
if (npcData.modelCorrectionRotZ != 0.0f) {
|
||||||
|
corrRotQuat = Eigen::Quaternionf(Eigen::AngleAxisf(npcData.modelCorrectionRotZ, Eigen::Vector3f::UnitZ())) * corrRotQuat;
|
||||||
|
}
|
||||||
|
npc->modelCorrectionRotation = corrRotQuat;
|
||||||
|
|
||||||
|
// Set initial target to current position
|
||||||
|
npc->setTarget(npc->position);
|
||||||
|
|
||||||
|
npcs.push_back(std::move(npc));
|
||||||
|
|
||||||
|
std::cout << "Successfully loaded NPC: " << npcData.name << " at position ("
|
||||||
|
<< npcData.positionX << ", " << npcData.positionY << ", " << npcData.positionZ << ")" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Total NPCs loaded: " << npcs.size() << std::endl;
|
||||||
|
return npcs;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
@ -6,12 +6,13 @@
|
|||||||
#include "external/nlohmann/json.hpp"
|
#include "external/nlohmann/json.hpp"
|
||||||
#include "TextModel.h"
|
#include "TextModel.h"
|
||||||
#include "InteractiveObject.h"
|
#include "InteractiveObject.h"
|
||||||
|
#include "Character.h"
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
struct Texture;
|
struct Texture;
|
||||||
struct VertexRenderStruct;
|
struct VertexRenderStruct;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
class Character;
|
||||||
|
|
||||||
struct GameObjectData {
|
struct GameObjectData {
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -32,6 +33,23 @@ namespace ZL {
|
|||||||
float interactionRadius = 2.0f;
|
float interactionRadius = 2.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NpcData {
|
||||||
|
std::string id;
|
||||||
|
std::string name;
|
||||||
|
std::string texturePath;
|
||||||
|
std::string animationIdlePath;
|
||||||
|
std::string animationWalkPath;
|
||||||
|
float positionX = 0.0f;
|
||||||
|
float positionY = 0.0f;
|
||||||
|
float positionZ = 0.0f;
|
||||||
|
float walkSpeed = 1.5f;
|
||||||
|
float rotationSpeed = 8.0f;
|
||||||
|
float modelScale = 0.01f;
|
||||||
|
float modelCorrectionRotX = 0.0f;
|
||||||
|
float modelCorrectionRotY = 0.0f;
|
||||||
|
float modelCorrectionRotZ = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
struct LoadedGameObject {
|
struct LoadedGameObject {
|
||||||
std::shared_ptr<Texture> texture;
|
std::shared_ptr<Texture> texture;
|
||||||
VertexRenderStruct mesh;
|
VertexRenderStruct mesh;
|
||||||
@ -53,6 +71,13 @@ namespace ZL {
|
|||||||
Renderer& renderer,
|
Renderer& renderer,
|
||||||
const std::string& zipPath = ""
|
const std::string& zipPath = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static std::vector<std::unique_ptr<Character>> loadAndCreateNpcs(
|
||||||
|
const std::string& jsonPath,
|
||||||
|
const std::string& zipPath = ""
|
||||||
|
);
|
||||||
|
|
||||||
|
static std::vector<NpcData> loadNpcsFromJson(const std::string& jsonPath, const std::string& zipPath = "");
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
Loading…
Reference in New Issue
Block a user