From e1b491be7342917ad40b63cb10d0ff195b150d2a Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 7 Apr 2026 20:17:04 +0600 Subject: [PATCH] added load from json game objects --- proj-windows/CMakeLists.txt | 3 + resources/config2/gameobjects.json | 40 +++++++++ src/Game.cpp | 16 +++- src/Game.h | 7 +- src/items/GameObjectLoader.cpp | 134 +++++++++++++++++++++++++++++ src/items/GameObjectLoader.h | 45 ++++++++++ 6 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 resources/config2/gameobjects.json create mode 100644 src/items/GameObjectLoader.cpp create mode 100644 src/items/GameObjectLoader.h diff --git a/proj-windows/CMakeLists.txt b/proj-windows/CMakeLists.txt index 4d361bd..9b18fb5 100644 --- a/proj-windows/CMakeLists.txt +++ b/proj-windows/CMakeLists.txt @@ -73,6 +73,9 @@ add_executable(space-game001 ../src/GameConstants.cpp ../src/ScriptEngine.h ../src/ScriptEngine.cpp + + ../src/items/GameObjectLoader.h + ../src/items/GameObjectLoader.cpp ) # Установка проекта по умолчанию для Visual Studio diff --git a/resources/config2/gameobjects.json b/resources/config2/gameobjects.json new file mode 100644 index 0000000..0a9b49d --- /dev/null +++ b/resources/config2/gameobjects.json @@ -0,0 +1,40 @@ +{ + "objects": [ + { + "name": "firebox", + "texturePath": "resources/w/Cube001.png", + "meshPath": "resources/w/firebox.txt", + "rotationX": 0.0, + "rotationY": -1.5707963267948966, + "rotationZ": 0.0, + "positionX": 0.0, + "positionY": 0.0, + "positionZ": 0.0, + "scale": 1.0 + }, + { + "name": "inai", + "texturePath": "resources/w/inai001.png", + "meshPath": "resources/w/inai001.txt", + "rotationX": 0.0, + "rotationY": -1.5707963267948966, + "rotationZ": 0.0, + "positionX": 2.5, + "positionY": 1.4, + "positionZ": -9.9, + "scale": 1.0 + }, + { + "name": "bench", + "texturePath": "resources/w/bench001opt.png", + "meshPath": "resources/w/bench002opt.txt", + "rotationX": 0.0, + "rotationY": 3.141592653589793, + "rotationZ": 0.0, + "positionX": -2.1, + "positionY": 0.5, + "positionZ": -7.9, + "scale": 3.0 + } + ] + } \ No newline at end of file diff --git a/src/Game.cpp b/src/Game.cpp index 55a1bb9..e1b5f01 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -147,6 +147,11 @@ namespace ZL roomMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI*0.5, Eigen::Vector3f::UnitY())).toRotationMatrix()); roomMesh.RefreshVBO(); std::cout << "Load resurces step 5" << std::endl; + + gameObjects = GameObjectLoader::loadAndCreateGameObjects("resources/config2/gameobjects.json", renderer, CONST_ZIP_FILE); + + /* + std::cout << "Load resurces step 5" << std::endl; fireboxTexture = std::make_unique(CreateTextureDataFromPng("resources/w/Cube001.png", CONST_ZIP_FILE)); fireboxMesh.data = LoadFromTextFile02("resources/w/firebox.txt", CONST_ZIP_FILE); fireboxMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5, Eigen::Vector3f::UnitY())).toRotationMatrix()); @@ -168,6 +173,7 @@ namespace ZL benchMesh.data.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())).toRotationMatrix()); benchMesh.data.Move({ -2.1, 0.5, -7.9 }); benchMesh.RefreshVBO(); + */ std::cout << "Load resurces step 8" << std::endl; @@ -271,14 +277,20 @@ namespace ZL glBindTexture(GL_TEXTURE_2D, roomTexture->getTexID()); renderer.DrawVertexRenderStruct(roomMesh); - + + for (auto& [name, gameObj] : gameObjects) { + glBindTexture(GL_TEXTURE_2D, gameObj.texture->getTexID()); + renderer.DrawVertexRenderStruct(gameObj.mesh); + } + + /* glBindTexture(GL_TEXTURE_2D, fireboxTexture->getTexID()); renderer.DrawVertexRenderStruct(fireboxMesh); glBindTexture(GL_TEXTURE_2D, inaiTexture->getTexID()); renderer.DrawVertexRenderStruct(inaiMesh); glBindTexture(GL_TEXTURE_2D, benchTexture->getTexID()); renderer.DrawVertexRenderStruct(benchMesh); - + */ if (player) player->draw(renderer); for (auto& npc : npcs) npc->draw(renderer); diff --git a/src/Game.h b/src/Game.h index 30c42e5..6287e04 100644 --- a/src/Game.h +++ b/src/Game.h @@ -9,6 +9,7 @@ #include "UiManager.h" #include "Projectile.h" #include "utils/TaskManager.h" +#include "items/GameObjectLoader.h" #include #include #include @@ -17,7 +18,7 @@ #include #include "MenuManager.h" #include "ScriptEngine.h" - +#include #include namespace ZL { @@ -48,6 +49,9 @@ namespace ZL { std::shared_ptr roomTexture; VertexRenderStruct roomMesh; + std::unordered_map gameObjects; + + /* std::shared_ptr fireboxTexture; VertexRenderStruct fireboxMesh; @@ -56,6 +60,7 @@ namespace ZL { std::shared_ptr benchTexture; VertexRenderStruct benchMesh; + */ std::unique_ptr player; std::vector> npcs; diff --git a/src/items/GameObjectLoader.cpp b/src/items/GameObjectLoader.cpp new file mode 100644 index 0000000..85ee3eb --- /dev/null +++ b/src/items/GameObjectLoader.cpp @@ -0,0 +1,134 @@ +#include "GameObjectLoader.h" +#include +#include +#include +#include "render/Renderer.h" +#include "render/TextureManager.h" +#include "utils/Utils.h" +#include + +namespace ZL { + + using json = nlohmann::json; + + std::vector GameObjectLoader::loadFromJson(const std::string& jsonPath, const std::string& zipPath) + { + std::vector objects; + 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("objects") || !j["objects"].is_array()) { + std::cerr << "Warning: 'objects' array not found in " << jsonPath << std::endl; + return objects; + } + + for (const auto& item : j["objects"]) { + GameObjectData data; + + data.name = item.value("name", "Unknown"); + data.texturePath = item.value("texturePath", ""); + data.meshPath = item.value("meshPath", ""); + + data.rotationX = item.value("rotationX", 0.0f); + data.rotationY = item.value("rotationY", 0.0f); + data.rotationZ = item.value("rotationZ", 0.0f); + + data.positionX = item.value("positionX", 0.0f); + data.positionY = item.value("positionY", 0.0f); + data.positionZ = item.value("positionZ", 0.0f); + + data.scale = item.value("scale", 1.0f); + + if (!data.meshPath.empty()) { + objects.push_back(data); + } + } + + std::cout << "Successfully loaded " << objects.size() << " game objects from " << jsonPath << std::endl; + + } catch (const std::exception& e) { + std::cerr << "Error loading JSON: " << e.what() << std::endl; + } + + return objects; + } + + std::unordered_map GameObjectLoader::loadAndCreateGameObjects( + const std::string& jsonPath, + Renderer& renderer, + const std::string& zipPath) + { + std::unordered_map gameObjects; + std::vector objectsData = loadFromJson(jsonPath, zipPath); + + for (const auto& objData : objectsData) { + std::cout << "Loading game object: " << objData.name << std::endl; + + LoadedGameObject gameObj; + gameObj.name = objData.name; + + // Load texture + try { + gameObj.texture = std::make_shared(CreateTextureDataFromPng(objData.texturePath, zipPath.c_str())); + } + catch (const std::exception& e) { + std::cerr << "GameObjectLoader: Failed to load texture for '" << objData.name << "': " << e.what() << std::endl; + continue; + } + + // Load mesh + try { + gameObj.mesh.data = LoadFromTextFile02(objData.meshPath, zipPath); + } + catch (const std::exception& e) { + std::cerr << "GameObjectLoader: Failed to load mesh for '" << objData.name << "': " << e.what() << std::endl; + continue; + } + + // Apply rotation + Eigen::Quaternionf rotationQuat = Eigen::Quaternionf::Identity(); + + if (objData.rotationX != 0.0f) { + rotationQuat = Eigen::Quaternionf(Eigen::AngleAxisf(objData.rotationX, Eigen::Vector3f::UnitX())) * rotationQuat; + } + if (objData.rotationY != 0.0f) { + rotationQuat = Eigen::Quaternionf(Eigen::AngleAxisf(objData.rotationY, Eigen::Vector3f::UnitY())) * rotationQuat; + } + if (objData.rotationZ != 0.0f) { + rotationQuat = Eigen::Quaternionf(Eigen::AngleAxisf(objData.rotationZ, Eigen::Vector3f::UnitZ())) * rotationQuat; + } + + gameObj.mesh.data.RotateByMatrix(rotationQuat.toRotationMatrix()); + + // Apply scale + if (objData.scale != 1.0f) { + gameObj.mesh.data.Scale(objData.scale); + } + + // Apply position + if (objData.positionX != 0.0f || objData.positionY != 0.0f || objData.positionZ != 0.0f) { + gameObj.mesh.data.Move({ objData.positionX, objData.positionY, objData.positionZ }); + } + + gameObj.mesh.RefreshVBO(); + gameObjects[objData.name] = gameObj; + + std::cout << "Successfully loaded: " << objData.name << std::endl; + } + + std::cout << "Total game objects loaded: " << gameObjects.size() << std::endl; + return gameObjects; + } + +} // namespace ZL \ No newline at end of file diff --git a/src/items/GameObjectLoader.h b/src/items/GameObjectLoader.h new file mode 100644 index 0000000..d5fbc73 --- /dev/null +++ b/src/items/GameObjectLoader.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include +#include "external/nlohmann/json.hpp" +#include "TextModel.h" + +namespace ZL { + + struct Texture; + struct VertexRenderStruct; + class Renderer; + + struct GameObjectData { + std::string name; + std::string texturePath; + std::string meshPath; + float rotationX = 0.0f; + float rotationY = 0.0f; + float rotationZ = 0.0f; + float positionX = 0.0f; + float positionY = 0.0f; + float positionZ = 0.0f; + float scale = 1.0f; + }; + + struct LoadedGameObject { + std::shared_ptr texture; + VertexRenderStruct mesh; + std::string name; + }; + + class GameObjectLoader { + public: + static std::vector loadFromJson(const std::string& jsonPath, const std::string& zipPath = ""); + + static std::unordered_map loadAndCreateGameObjects( + const std::string& jsonPath, + Renderer& renderer, + const std::string& zipPath = "" + ); + }; + +} // namespace ZL \ No newline at end of file