From 2d627a923dabf0b507e57052e759fb37037a218e Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sun, 8 Feb 2026 19:45:18 +0800 Subject: [PATCH] refactor: enhance type safety by changing SceneType from string to enum class --- src/scenes/base/SceneEvent.h | 21 ++++++++- src/scenes/base/SceneManager.cpp | 58 ++++++++++++++----------- src/scenes/base/SceneManager.h | 14 +++--- src/scenes/gameplay/GameScene.cpp | 4 +- src/scenes/gameplay/OnlineGameScene.cpp | 4 +- src/scenes/menu/MainMenuScene.cpp | 4 +- src/ui/base/IUIManager.h | 4 +- src/ui/managers/GameUIManager.cpp | 2 +- src/ui/managers/MainMenuUIManager.cpp | 4 +- 9 files changed, 69 insertions(+), 46 deletions(-) diff --git a/src/scenes/base/SceneEvent.h b/src/scenes/base/SceneEvent.h index 43df7f2..07f4488 100644 --- a/src/scenes/base/SceneEvent.h +++ b/src/scenes/base/SceneEvent.h @@ -16,11 +16,28 @@ enum class SceneEventType { PopScene, ///< 弹出当前场景事件 QuitGame ///< 退出游戏事件 }; + +enum class SceneType { + + MainMenuScene, + GameScene, + OnlineGameScene +}; + +// 自定义哈希器 +struct SceneTypeHash { + size_t operator()(SceneType s) const noexcept { + return static_cast(s); + } +}; + + /** * @struct SceneEvent * @brief 场景事件结构体,包含事件类型和相关数据 */ struct SceneEvent { SceneEventType type; ///< 事件类型 - std::string sceneName; ///< 只在 ChangeScene/PushScene 时使用 -}; \ No newline at end of file + SceneType sceneType; ///< 只在 ChangeScene/PushScene 时使用 +}; + diff --git a/src/scenes/base/SceneManager.cpp b/src/scenes/base/SceneManager.cpp index 310c13d..08e41c5 100644 --- a/src/scenes/base/SceneManager.cpp +++ b/src/scenes/base/SceneManager.cpp @@ -27,64 +27,65 @@ SceneManager::~SceneManager() { bool SceneManager::initialize() { // 注册所有场景工厂 registerAllScene(); - changeScene("MainMenuScene"); + changeScene(SceneType::MainMenuScene); return true; } void SceneManager::registerAllScene() { // 注册所有默认场景工厂(可以由外部覆盖/新增) - registerSceneFactory("MainMenuScene", []() -> std::shared_ptr { + registerSceneFactory(SceneType::MainMenuScene, []() -> std::shared_ptr { return std::make_shared(); }); - registerSceneFactory("GameScene", []() -> std::shared_ptr { + registerSceneFactory(SceneType::GameScene, []() -> std::shared_ptr { return std::make_shared(); }); - registerSceneFactory("OnlineGameScene", []() -> std::shared_ptr { + registerSceneFactory(SceneType::OnlineGameScene, []() -> std::shared_ptr { return std::make_shared(); }); } -std::shared_ptr SceneManager::createScene(const std::string& sceneName) { +std::shared_ptr SceneManager::createScene(SceneType sceneType) { // 使用注册的工厂创建场景实例 - auto it = m_sceneFactories.find(sceneName); + auto it = m_sceneFactories.find(sceneType); if (it != m_sceneFactories.end()) { auto scene = it->second(); if (scene) { // 并不缓存实例,而是返回给调用者,由调用者决定缓存与否 return scene; } else { - SDL_Log("SceneManager::createScene: factory for '%s' returned nullptr\n", sceneName.c_str()); + SDL_Log("SceneManager::createScene: factory returned nullptr\n"); } } else { - SDL_Log("SceneManager::createScene: no factory registered for '%s'\n", sceneName.c_str()); + SDL_Log("SceneManager::createScene: no factory registered \n"); } return nullptr; } -void SceneManager::registerSceneFactory(const std::string& sceneName, std::function()> factory) { - if (sceneName.empty()) return; - m_sceneFactories[sceneName] = std::move(factory); +void SceneManager::registerSceneFactory(SceneType sceneType, std::function()> factory) { + //if (sceneName.empty()) return; + m_sceneFactories[sceneType] = std::move(factory); } -void SceneManager::unregisterSceneFactory(const std::string& sceneName) { - m_sceneFactories.erase(sceneName); +void SceneManager::unregisterSceneFactory(SceneType sceneType) { + m_sceneFactories.erase(sceneType); } -void SceneManager::pushScene(const std::string& sceneName) { +void SceneManager::pushScene(SceneType sceneType) { + /* if (sceneName.empty()) { SDL_Log("SceneManager::pushScene: sceneName is empty!\n"); return; } - + */ // 检查场景是否已在缓存中 - auto it = m_sceneCache.find(sceneName); + auto it = m_sceneCache.find(sceneType); if (it == m_sceneCache.end()) { // 场景未缓存,尝试创建 - createScene(sceneName); - it = m_sceneCache.find(sceneName); + createScene(sceneType); + it = m_sceneCache.find(sceneType); if (it == m_sceneCache.end()) { - SDL_Log("SceneManager::pushScene: Scene '%s' not found in cache after creation!\n", sceneName.c_str()); + SDL_Log("SceneManager::pushScene: Scene not found in cache after creation!\n"); return; } } @@ -123,8 +124,8 @@ void SceneManager::popScene() { } -void SceneManager::changeScene(const std::string& sceneName) { - if (sceneName.empty()) return; +void SceneManager::changeScene(SceneType sceneType) { + //if (sceneName.empty()) return; /* // 检查场景是否已在缓存中 if (m_sceneCache.find(sceneName) == m_sceneCache.end()) { @@ -141,9 +142,9 @@ void SceneManager::changeScene(const std::string& sceneName) { */ // 不缓存场景,每次都创建新实例,以避免状态残留问题 - auto target = createScene(sceneName); + auto target = createScene(sceneType); if (!target) { - SDL_Log("SceneManager::changeScene: Scene '%s' could not be created!\n", sceneName.c_str()); + SDL_Log("SceneManager::changeScene: Scene could not be created!\n"); return; } target->setEventCallback([this](const SceneEvent& event) { @@ -156,7 +157,8 @@ void SceneManager::changeScene(const std::string& sceneName) { } // 切换到目标场景 m_scene = target; - + + m_coreData.sceneType = sceneType; m_scene->onEnter(m_renderer, UI::LogicalWidth, UI::LogicalHeight, m_uiRenderer, m_textureManager, &m_coreData); } @@ -173,6 +175,10 @@ void SceneManager::handleClickCurrent(glm::ivec2 clickOn) { void SceneManager::updateCurrent() { if (m_scene) m_scene->update(); + if (m_coreData.inputState.isBadApplePress) { + m_coreData.inputState.isBadApplePress = false; + std::cout << "SceneManager: badapple pressed\n"; + } } @@ -198,10 +204,10 @@ void SceneManager::handleSceneEvent(const SceneEvent& event) { switch (event.type) { case SceneEventType::ChangeScene: - changeScene(event.sceneName); + changeScene(event.sceneType); break; case SceneEventType::PushScene: - pushScene(event.sceneName); + pushScene(event.sceneType); break; case SceneEventType::PopScene: popScene(); diff --git a/src/scenes/base/SceneManager.h b/src/scenes/base/SceneManager.h index 5bb2dba..7baf396 100644 --- a/src/scenes/base/SceneManager.h +++ b/src/scenes/base/SceneManager.h @@ -52,26 +52,26 @@ public: * @brief 创建场景实例并缓存 * @param sceneName 场景名称 */ - std::shared_ptr createScene(const std::string& sceneName); + std::shared_ptr createScene(SceneType sceneType); /** * @brief 注册场景工厂函数,用于按名字动态创建场景实例 * @param sceneName 场景名称 * @param factory 返回新场景的函数,返回类型为 std::shared_ptr */ - void registerSceneFactory(const std::string& sceneName, std::function()> factory); + void registerSceneFactory(SceneType sceneType, std::function()> factory); /** * @brief 注销已注册的场景工厂 */ - void unregisterSceneFactory(const std::string& sceneName); + void unregisterSceneFactory(SceneType sceneType); /** * @brief 将新场景推入场景栈顶端并作为当前场景 * @param sceneName 场景名称,用于缓存查找。若缓存中不存在,则通过工厂函数动态创建 * @details 前一个当前场景将接收 onExit() 回调并保留在栈中。新场景成为当前场景并接收 onEnter() 回调 */ - void pushScene(const std::string& sceneName); + void pushScene(SceneType sceneType); /** * @brief 弹出当前场景并恢复前一个场景 @@ -85,7 +85,7 @@ public: * @details 当前场景将接收 onExit() 回调并被替换。若缓存中存在该名称的场景则复用, * 否则通过工厂函数创建新场景。新场景成为当前场景并接收 onEnter() 回调 */ - void changeScene(const std::string& sceneName); + void changeScene(SceneType sceneType); /** * @brief 处理当前场景的点击事件 @@ -130,8 +130,8 @@ private: TextureManager* m_textureManager; ///< 材质管理器指针 std::shared_ptr m_scene; ///< 当前场景(使用 shared_ptr 便于在缓存和栈中共享) std::stack> m_scenes; ///< 场景栈,存储场景层级关系(使用 shared_ptr) - std::unordered_map> m_sceneCache; ///< 场景缓存,按名字缓存场景以便切换时复用 - std::unordered_map()>> m_sceneFactories; ///< 场景工厂映射,按名字动态创建场景实例 + std::unordered_map, SceneTypeHash> m_sceneCache; ///< 场景缓存,按名字缓存场景以便切换时复用 + std::unordered_map()>, SceneTypeHash> m_sceneFactories; ///< 场景工厂映射,按名字动态创建场景实例 std::shared_ptr m_quitedScene; ///< 已经退出的场景,准备在最后销毁 /** * @brief 获取窗口尺寸的辅助方法 diff --git a/src/scenes/gameplay/GameScene.cpp b/src/scenes/gameplay/GameScene.cpp index 744d15f..22a564f 100644 --- a/src/scenes/gameplay/GameScene.cpp +++ b/src/scenes/gameplay/GameScene.cpp @@ -11,9 +11,9 @@ GameScene::~GameScene() { std::unique_ptr GameScene::createUIManager() { // 默认创建普通的GameUIManager return std::make_unique( - [this](const std::string& sceneName) { + [this](SceneType sceneType) { if (m_eventCallback) { - SceneEvent event{SceneEventType::ChangeScene, sceneName}; + SceneEvent event{SceneEventType::ChangeScene, sceneType}; m_eventCallback(event); } } diff --git a/src/scenes/gameplay/OnlineGameScene.cpp b/src/scenes/gameplay/OnlineGameScene.cpp index c37450a..76cb03b 100644 --- a/src/scenes/gameplay/OnlineGameScene.cpp +++ b/src/scenes/gameplay/OnlineGameScene.cpp @@ -4,9 +4,9 @@ std::unique_ptr OnlineGameScene::createUIManager() { auto onlineUIManager = std::make_unique( - [this](const std::string& sceneName) { + [this](SceneType sceneType) { if (m_eventCallback) { - SceneEvent event{SceneEventType::ChangeScene, sceneName}; + SceneEvent event{SceneEventType::ChangeScene, sceneType}; m_eventCallback(event); } } diff --git a/src/scenes/menu/MainMenuScene.cpp b/src/scenes/menu/MainMenuScene.cpp index 056a7f7..6f72eb7 100644 --- a/src/scenes/menu/MainMenuScene.cpp +++ b/src/scenes/menu/MainMenuScene.cpp @@ -10,9 +10,9 @@ void MainMenuScene::onEnter(SDL_Renderer* renderer, int width, int height, UIRen m_uiRenderer = uiRenderer; m_coreData = coreData; m_mainMenuUIManager = std::make_unique( - [this](const std::string& sceneName) { + [this](SceneType sceneType) { if (m_eventCallback) { - SceneEvent event{SceneEventType::ChangeScene, sceneName}; + SceneEvent event{SceneEventType::ChangeScene, sceneType}; m_eventCallback(event); } } diff --git a/src/ui/base/IUIManager.h b/src/ui/base/IUIManager.h index 4f91aec..5f41237 100644 --- a/src/ui/base/IUIManager.h +++ b/src/ui/base/IUIManager.h @@ -5,14 +5,14 @@ #include "ui/components/Button.h" #include "ui/components/Label.h" #include "ui/base/UIRenderData.h" - +#include "scenes/base/SceneEvent.h" #include #include #include class IUIManager { public: - using SceneEventCallback = std::function; + using SceneEventCallback = std::function; virtual ~IUIManager() = default; virtual void init() = 0; diff --git a/src/ui/managers/GameUIManager.cpp b/src/ui/managers/GameUIManager.cpp index 0cadbb3..6e19a97 100644 --- a/src/ui/managers/GameUIManager.cpp +++ b/src/ui/managers/GameUIManager.cpp @@ -163,7 +163,7 @@ void GameUIManager::setupUIComponents() { 550, 20, [this](){ - m_eventCallback("MainMenuScene"); + m_eventCallback(SceneType::MainMenuScene); } ); diff --git a/src/ui/managers/MainMenuUIManager.cpp b/src/ui/managers/MainMenuUIManager.cpp index 7c56f95..2c48107 100644 --- a/src/ui/managers/MainMenuUIManager.cpp +++ b/src/ui/managers/MainMenuUIManager.cpp @@ -14,14 +14,14 @@ MainMenuUIManager::~MainMenuUIManager() { void MainMenuUIManager::init() { auto startButton = UIWidgetFactory::createStandardButton( "StartButton", "开始游戏", 275, 180, - [this]() { m_eventCallback("GameScene"); } + [this]() { m_eventCallback(SceneType::GameScene); } ); m_buttons.emplace(startButton->getNameHash(), std::move(startButton)); auto onlineStartButton = UIWidgetFactory::createStandardButton( "OnlineStartButton", "联机对战", 275, 250, - [this]() {m_eventCallback("OnlineGameScene"); } + [this]() {m_eventCallback(SceneType::OnlineGameScene); } ); m_buttons.emplace(onlineStartButton->getNameHash(), std::move(onlineStartButton));