diff --git a/CMakeLists.txt b/CMakeLists.txt index 73ede5e..45a562e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ set(SOURCE_FILES src/ui/managers/MainMenuUIManager.cpp src/graphics/ui/UIRenderer.cpp src/graphics/font/BitmapFont.cpp + src/utils/ConfigLoader.cpp ) diff --git a/assets/config.json b/assets/config.json new file mode 100644 index 0000000..e364aed --- /dev/null +++ b/assets/config.json @@ -0,0 +1,20 @@ +{ + "window": { + "width": 1280, + "height": 720, + "fullscreen": false, + "vsync": true, + "title": "孢子棋" + }, + + "render": { + "logical_width": 640, + "logical_height": 360, + "scale_mode": "integer" + }, + + "ui": { + "font": "fonts/SourceHanSansSC-Regular.otf", + "font_size": 16 + } +} \ No newline at end of file diff --git a/src/core/GameApplication.cpp b/src/core/GameApplication.cpp index 4bf3fe8..bab9ca5 100644 --- a/src/core/GameApplication.cpp +++ b/src/core/GameApplication.cpp @@ -18,6 +18,9 @@ bool GameApplication::initialize() { SDL_Log("无法初始化 SDL_ttf: %s", SDL_GetError()); return false; } + if (!ConfigLoader::load("assets/config.json", m_config)) { + SDL_Log("无法加载json"); + } // 输入管理 m_inputManager = std::make_unique(); // 窗口管理 diff --git a/src/core/GameApplication.h b/src/core/GameApplication.h index c5f1d0f..2df6e88 100644 --- a/src/core/GameApplication.h +++ b/src/core/GameApplication.h @@ -5,7 +5,7 @@ #include "scenes/base/SceneManager.h" #include "input/InputManager.h" #include "utils/Config.h" - +#include "utils/ConfigLoader.h" #include "graphics/font/TextRenderer.h" #include "graphics/font/FontManager.h" @@ -21,7 +21,7 @@ private: std::unique_ptr m_textRenderer; std::unique_ptr m_uiRenderer; - WindowConfig m_config; + Config m_config; public: GameApplication(); diff --git a/src/core/WindowManager.cpp b/src/core/WindowManager.cpp index 463506c..e1d3aff 100644 --- a/src/core/WindowManager.cpp +++ b/src/core/WindowManager.cpp @@ -10,17 +10,18 @@ WindowManager::~WindowManager() { Shutdown(); } -bool WindowManager::Initialize(WindowConfig& config) { - m_viewport.logicalWidth = config.logicalWidth; - m_viewport.logicalHeight = config.logicalHeight; +bool WindowManager::Initialize(Config& config) { + m_viewport.logicalWidth = config.render.logicalWidth; + m_viewport.logicalHeight = config.render.logicalHeight; // 创建窗口(支持高DPI和横屏)[3,4](@ref) m_window = SDL_CreateWindow( - "孢子棋", // 窗口标题,显示在标题栏上 - m_viewport.logicalWidth, // 窗口的逻辑宽度(例如 800),用于统一布局,不受屏幕 DPI 影响 - m_viewport.logicalHeight, // 窗口的逻辑高度(例如 600) + config.window.title.c_str(), // 窗口标题,显示在标题栏上 + config.window.width, // 窗口的逻辑宽度(例如 800),用于统一布局,不受屏幕 DPI 影响 + config.window.height, // 窗口的逻辑高度(例如 600) SDL_WINDOW_HIGH_PIXEL_DENSITY | // 启用高像素密度支持(HiDPI/Retina),确保在高分屏上画面清晰 SDL_WINDOW_RESIZABLE // 允许用户调整窗口大小(可拉伸) ); + //SDL_Log("window width %d\nwindow height %d\ntitle %s\n", config.window.width, config.window.height, config.window.title); if (!m_window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建窗口失败: %s", SDL_GetError()); @@ -44,7 +45,7 @@ bool WindowManager::Initialize(WindowConfig& config) { m_height, SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); */ - SDL_SetWindowSize(m_window, UI::StartWindowWidth, UI::StartWindowHeight); + //SDL_SetWindowSize(m_window, UI::StartWindowWidth, UI::StartWindowHeight); // 创建逻辑画布 // RGBA8888: 32位色,8位红绿蓝和透明度 // TARGET: 纹理可作为渲染目标 diff --git a/src/core/WindowManager.h b/src/core/WindowManager.h index 5e5c166..4a5823c 100644 --- a/src/core/WindowManager.h +++ b/src/core/WindowManager.h @@ -6,7 +6,7 @@ public: WindowManager(); ~WindowManager(); // 初始化 - bool Initialize(WindowConfig& config); + bool Initialize(Config& config); //关闭 void Shutdown(); //清理上一帧窗口 diff --git a/src/utils/Config.h b/src/utils/Config.h index 2f42a54..be4c800 100644 --- a/src/utils/Config.h +++ b/src/utils/Config.h @@ -9,11 +9,11 @@ struct WindowConfig { 640x360 逻辑分辨率(窗口大小的1/2) 画面更高清晰 */ - int logicalWidth = 640; - int logicalHeight = 360; - std::string windowTitle = "孢子棋"; + int width = 320 * 4; // 初始窗口宽度(像素) + int height = 180 * 4; // 初始窗口高度(像素) + std::string title = "孢子棋"; bool vsync = true; - int scale = 2; + /* @@ -24,6 +24,12 @@ struct WindowConfig { */ } ; +struct RenderConfig { + int logicalWidth = 640; + int logicalHeight = 360; + int scale = 2; +}; + // 获取棋盘渲染区域信息(用于坐标转换) struct BoardArea { int x, y; // 左上角像素坐标 @@ -42,8 +48,7 @@ namespace UI constexpr int FontHeight = 8; constexpr int LogicalWidth = 640; constexpr int LogicalHeight = 360; - constexpr int StartWindowWidth = 320 * 4; // 初始窗口宽度(像素) - constexpr int StartWindowHeight = 180 * 4; // 初始窗口高度(像素) + // 字体大小(逻辑像素) constexpr int DIALOG_FONT_SIZE = 14; constexpr int UI_SMALL_FONT_SIZE = 8; @@ -73,4 +78,9 @@ struct Viewport { // 逻辑画面被放大后,在窗口中的位置和大小 // 用于 SDL_RenderTexture / 输入坐标转换 SDL_FRect dst{}; +}; + +struct Config { + WindowConfig window; + RenderConfig render; }; \ No newline at end of file diff --git a/src/utils/ConfigLoader.cpp b/src/utils/ConfigLoader.cpp new file mode 100644 index 0000000..4ef1c80 --- /dev/null +++ b/src/utils/ConfigLoader.cpp @@ -0,0 +1,59 @@ +#include "ConfigLoader.h" +#include +#include +using json = nlohmann::json; + + +static void loadWindow(const json& j, WindowConfig& window) { + auto get = [&](const char* key, auto& out) { + if (j.contains(key)) + j.at(key).get_to(out); + else { + std::cout << "Unkonw key " << key << "\n"; + } + }; + get("width", window.width); + get("height", window.height); + get("title", window.title); +} + +static void loadRender(const json& j, RenderConfig& render) { + auto get = [&](const char* key, auto& out) { + if (j.contains(key)) + j.at(key).get_to(out); + else { + std::cout << "Unkonw key " << key << "\n"; + } + }; + get("logical_width", render.logicalWidth); + get("logical_height", render.logicalHeight); +} + +bool ConfigLoader::load(const std::string& path, Config& config) { + std::ifstream file(path); + + if (!file.is_open()) { + std::cerr << "[Config] Cannot open " << path << "\n"; + return false; + } + + json j; + + try { + file >> j; + } + catch (const json::parse_error& e) { + std::cerr << "[Config] JSON parse error: " << e.what() << std::endl; + return false; + } + + if (j.contains("window")) { + loadWindow(j["window"], config.window); + } + if (j.contains("render")) { + loadRender(j["render"], config.render); + } + std::cout << "load json success!\n"; + return true; + +} \ No newline at end of file diff --git a/src/utils/ConfigLoader.h b/src/utils/ConfigLoader.h new file mode 100644 index 0000000..ba24106 --- /dev/null +++ b/src/utils/ConfigLoader.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Config.h" +#include + +class ConfigLoader { +public: + static bool load(const std::string& path, Config& config); + + +};