mirror of
https://github.com/zhenyan121/SporeBG-Conid.git
synced 2026-04-10 06:14:08 +08:00
refactor: enhance type safety by changing SceneType from string to enum class
This commit is contained in:
@@ -16,11 +16,28 @@ enum class SceneEventType {
|
|||||||
PopScene, ///< 弹出当前场景事件
|
PopScene, ///< 弹出当前场景事件
|
||||||
QuitGame ///< 退出游戏事件
|
QuitGame ///< 退出游戏事件
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SceneType {
|
||||||
|
|
||||||
|
MainMenuScene,
|
||||||
|
GameScene,
|
||||||
|
OnlineGameScene
|
||||||
|
};
|
||||||
|
|
||||||
|
// 自定义哈希器
|
||||||
|
struct SceneTypeHash {
|
||||||
|
size_t operator()(SceneType s) const noexcept {
|
||||||
|
return static_cast<size_t>(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct SceneEvent
|
* @struct SceneEvent
|
||||||
* @brief 场景事件结构体,包含事件类型和相关数据
|
* @brief 场景事件结构体,包含事件类型和相关数据
|
||||||
*/
|
*/
|
||||||
struct SceneEvent {
|
struct SceneEvent {
|
||||||
SceneEventType type; ///< 事件类型
|
SceneEventType type; ///< 事件类型
|
||||||
std::string sceneName; ///< 只在 ChangeScene/PushScene 时使用
|
SceneType sceneType; ///< 只在 ChangeScene/PushScene 时使用
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,64 +27,65 @@ SceneManager::~SceneManager() {
|
|||||||
bool SceneManager::initialize() {
|
bool SceneManager::initialize() {
|
||||||
// 注册所有场景工厂
|
// 注册所有场景工厂
|
||||||
registerAllScene();
|
registerAllScene();
|
||||||
changeScene("MainMenuScene");
|
changeScene(SceneType::MainMenuScene);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::registerAllScene() {
|
void SceneManager::registerAllScene() {
|
||||||
// 注册所有默认场景工厂(可以由外部覆盖/新增)
|
// 注册所有默认场景工厂(可以由外部覆盖/新增)
|
||||||
|
|
||||||
registerSceneFactory("MainMenuScene", []() -> std::shared_ptr<Scene> {
|
registerSceneFactory(SceneType::MainMenuScene, []() -> std::shared_ptr<Scene> {
|
||||||
return std::make_shared<MainMenuScene>();
|
return std::make_shared<MainMenuScene>();
|
||||||
});
|
});
|
||||||
registerSceneFactory("GameScene", []() -> std::shared_ptr<Scene> {
|
registerSceneFactory(SceneType::GameScene, []() -> std::shared_ptr<Scene> {
|
||||||
return std::make_shared<GameScene>();
|
return std::make_shared<GameScene>();
|
||||||
});
|
});
|
||||||
registerSceneFactory("OnlineGameScene", []() -> std::shared_ptr<Scene> {
|
registerSceneFactory(SceneType::OnlineGameScene, []() -> std::shared_ptr<Scene> {
|
||||||
return std::make_shared<OnlineGameScene>();
|
return std::make_shared<OnlineGameScene>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Scene> SceneManager::createScene(const std::string& sceneName) {
|
std::shared_ptr<Scene> SceneManager::createScene(SceneType sceneType) {
|
||||||
// 使用注册的工厂创建场景实例
|
// 使用注册的工厂创建场景实例
|
||||||
auto it = m_sceneFactories.find(sceneName);
|
auto it = m_sceneFactories.find(sceneType);
|
||||||
if (it != m_sceneFactories.end()) {
|
if (it != m_sceneFactories.end()) {
|
||||||
auto scene = it->second();
|
auto scene = it->second();
|
||||||
if (scene) {
|
if (scene) {
|
||||||
// 并不缓存实例,而是返回给调用者,由调用者决定缓存与否
|
// 并不缓存实例,而是返回给调用者,由调用者决定缓存与否
|
||||||
return scene;
|
return scene;
|
||||||
} else {
|
} else {
|
||||||
SDL_Log("SceneManager::createScene: factory for '%s' returned nullptr\n", sceneName.c_str());
|
SDL_Log("SceneManager::createScene: factory returned nullptr\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SDL_Log("SceneManager::createScene: no factory registered for '%s'\n", sceneName.c_str());
|
SDL_Log("SceneManager::createScene: no factory registered \n");
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::registerSceneFactory(const std::string& sceneName, std::function<std::shared_ptr<Scene>()> factory) {
|
void SceneManager::registerSceneFactory(SceneType sceneType, std::function<std::shared_ptr<Scene>()> factory) {
|
||||||
if (sceneName.empty()) return;
|
//if (sceneName.empty()) return;
|
||||||
m_sceneFactories[sceneName] = std::move(factory);
|
m_sceneFactories[sceneType] = std::move(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::unregisterSceneFactory(const std::string& sceneName) {
|
void SceneManager::unregisterSceneFactory(SceneType sceneType) {
|
||||||
m_sceneFactories.erase(sceneName);
|
m_sceneFactories.erase(sceneType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::pushScene(const std::string& sceneName) {
|
void SceneManager::pushScene(SceneType sceneType) {
|
||||||
|
/*
|
||||||
if (sceneName.empty()) {
|
if (sceneName.empty()) {
|
||||||
SDL_Log("SceneManager::pushScene: sceneName is empty!\n");
|
SDL_Log("SceneManager::pushScene: sceneName is empty!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// 检查场景是否已在缓存中
|
// 检查场景是否已在缓存中
|
||||||
auto it = m_sceneCache.find(sceneName);
|
auto it = m_sceneCache.find(sceneType);
|
||||||
if (it == m_sceneCache.end()) {
|
if (it == m_sceneCache.end()) {
|
||||||
// 场景未缓存,尝试创建
|
// 场景未缓存,尝试创建
|
||||||
createScene(sceneName);
|
createScene(sceneType);
|
||||||
it = m_sceneCache.find(sceneName);
|
it = m_sceneCache.find(sceneType);
|
||||||
if (it == m_sceneCache.end()) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,8 +124,8 @@ void SceneManager::popScene() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SceneManager::changeScene(const std::string& sceneName) {
|
void SceneManager::changeScene(SceneType sceneType) {
|
||||||
if (sceneName.empty()) return;
|
//if (sceneName.empty()) return;
|
||||||
/*
|
/*
|
||||||
// 检查场景是否已在缓存中
|
// 检查场景是否已在缓存中
|
||||||
if (m_sceneCache.find(sceneName) == m_sceneCache.end()) {
|
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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
target->setEventCallback([this](const SceneEvent& event) {
|
target->setEventCallback([this](const SceneEvent& event) {
|
||||||
@@ -157,6 +158,7 @@ void SceneManager::changeScene(const std::string& sceneName) {
|
|||||||
// 切换到目标场景
|
// 切换到目标场景
|
||||||
m_scene = target;
|
m_scene = target;
|
||||||
|
|
||||||
|
m_coreData.sceneType = sceneType;
|
||||||
|
|
||||||
m_scene->onEnter(m_renderer, UI::LogicalWidth, UI::LogicalHeight, m_uiRenderer, m_textureManager, &m_coreData);
|
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() {
|
void SceneManager::updateCurrent() {
|
||||||
if (m_scene) m_scene->update();
|
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)
|
switch (event.type)
|
||||||
{
|
{
|
||||||
case SceneEventType::ChangeScene:
|
case SceneEventType::ChangeScene:
|
||||||
changeScene(event.sceneName);
|
changeScene(event.sceneType);
|
||||||
break;
|
break;
|
||||||
case SceneEventType::PushScene:
|
case SceneEventType::PushScene:
|
||||||
pushScene(event.sceneName);
|
pushScene(event.sceneType);
|
||||||
break;
|
break;
|
||||||
case SceneEventType::PopScene:
|
case SceneEventType::PopScene:
|
||||||
popScene();
|
popScene();
|
||||||
|
|||||||
@@ -52,26 +52,26 @@ public:
|
|||||||
* @brief 创建场景实例并缓存
|
* @brief 创建场景实例并缓存
|
||||||
* @param sceneName 场景名称
|
* @param sceneName 场景名称
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<Scene> createScene(const std::string& sceneName);
|
std::shared_ptr<Scene> createScene(SceneType sceneType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 注册场景工厂函数,用于按名字动态创建场景实例
|
* @brief 注册场景工厂函数,用于按名字动态创建场景实例
|
||||||
* @param sceneName 场景名称
|
* @param sceneName 场景名称
|
||||||
* @param factory 返回新场景的函数,返回类型为 std::shared_ptr<Scene>
|
* @param factory 返回新场景的函数,返回类型为 std::shared_ptr<Scene>
|
||||||
*/
|
*/
|
||||||
void registerSceneFactory(const std::string& sceneName, std::function<std::shared_ptr<Scene>()> factory);
|
void registerSceneFactory(SceneType sceneType, std::function<std::shared_ptr<Scene>()> factory);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 注销已注册的场景工厂
|
* @brief 注销已注册的场景工厂
|
||||||
*/
|
*/
|
||||||
void unregisterSceneFactory(const std::string& sceneName);
|
void unregisterSceneFactory(SceneType sceneType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 将新场景推入场景栈顶端并作为当前场景
|
* @brief 将新场景推入场景栈顶端并作为当前场景
|
||||||
* @param sceneName 场景名称,用于缓存查找。若缓存中不存在,则通过工厂函数动态创建
|
* @param sceneName 场景名称,用于缓存查找。若缓存中不存在,则通过工厂函数动态创建
|
||||||
* @details 前一个当前场景将接收 onExit() 回调并保留在栈中。新场景成为当前场景并接收 onEnter() 回调
|
* @details 前一个当前场景将接收 onExit() 回调并保留在栈中。新场景成为当前场景并接收 onEnter() 回调
|
||||||
*/
|
*/
|
||||||
void pushScene(const std::string& sceneName);
|
void pushScene(SceneType sceneType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 弹出当前场景并恢复前一个场景
|
* @brief 弹出当前场景并恢复前一个场景
|
||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
* @details 当前场景将接收 onExit() 回调并被替换。若缓存中存在该名称的场景则复用,
|
* @details 当前场景将接收 onExit() 回调并被替换。若缓存中存在该名称的场景则复用,
|
||||||
* 否则通过工厂函数创建新场景。新场景成为当前场景并接收 onEnter() 回调
|
* 否则通过工厂函数创建新场景。新场景成为当前场景并接收 onEnter() 回调
|
||||||
*/
|
*/
|
||||||
void changeScene(const std::string& sceneName);
|
void changeScene(SceneType sceneType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 处理当前场景的点击事件
|
* @brief 处理当前场景的点击事件
|
||||||
@@ -130,8 +130,8 @@ private:
|
|||||||
TextureManager* m_textureManager; ///< 材质管理器指针
|
TextureManager* m_textureManager; ///< 材质管理器指针
|
||||||
std::shared_ptr<Scene> m_scene; ///< 当前场景(使用 shared_ptr 便于在缓存和栈中共享)
|
std::shared_ptr<Scene> m_scene; ///< 当前场景(使用 shared_ptr 便于在缓存和栈中共享)
|
||||||
std::stack<std::shared_ptr<Scene>> m_scenes; ///< 场景栈,存储场景层级关系(使用 shared_ptr)
|
std::stack<std::shared_ptr<Scene>> m_scenes; ///< 场景栈,存储场景层级关系(使用 shared_ptr)
|
||||||
std::unordered_map<std::string, std::shared_ptr<Scene>> m_sceneCache; ///< 场景缓存,按名字缓存场景以便切换时复用
|
std::unordered_map<SceneType, std::shared_ptr<Scene>, SceneTypeHash> m_sceneCache; ///< 场景缓存,按名字缓存场景以便切换时复用
|
||||||
std::unordered_map<std::string, std::function<std::shared_ptr<Scene>()>> m_sceneFactories; ///< 场景工厂映射,按名字动态创建场景实例
|
std::unordered_map<SceneType, std::function<std::shared_ptr<Scene>()>, SceneTypeHash> m_sceneFactories; ///< 场景工厂映射,按名字动态创建场景实例
|
||||||
std::shared_ptr<Scene> m_quitedScene; ///< 已经退出的场景,准备在最后销毁
|
std::shared_ptr<Scene> m_quitedScene; ///< 已经退出的场景,准备在最后销毁
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口尺寸的辅助方法
|
* @brief 获取窗口尺寸的辅助方法
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ GameScene::~GameScene() {
|
|||||||
std::unique_ptr<GameUIManager> GameScene::createUIManager() {
|
std::unique_ptr<GameUIManager> GameScene::createUIManager() {
|
||||||
// 默认创建普通的GameUIManager
|
// 默认创建普通的GameUIManager
|
||||||
return std::make_unique<GameUIManager>(
|
return std::make_unique<GameUIManager>(
|
||||||
[this](const std::string& sceneName) {
|
[this](SceneType sceneType) {
|
||||||
if (m_eventCallback) {
|
if (m_eventCallback) {
|
||||||
SceneEvent event{SceneEventType::ChangeScene, sceneName};
|
SceneEvent event{SceneEventType::ChangeScene, sceneType};
|
||||||
m_eventCallback(event);
|
m_eventCallback(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
std::unique_ptr<GameUIManager> OnlineGameScene::createUIManager() {
|
std::unique_ptr<GameUIManager> OnlineGameScene::createUIManager() {
|
||||||
auto onlineUIManager = std::make_unique<OnlineGameUIManager>(
|
auto onlineUIManager = std::make_unique<OnlineGameUIManager>(
|
||||||
[this](const std::string& sceneName) {
|
[this](SceneType sceneType) {
|
||||||
if (m_eventCallback) {
|
if (m_eventCallback) {
|
||||||
SceneEvent event{SceneEventType::ChangeScene, sceneName};
|
SceneEvent event{SceneEventType::ChangeScene, sceneType};
|
||||||
m_eventCallback(event);
|
m_eventCallback(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ void MainMenuScene::onEnter(SDL_Renderer* renderer, int width, int height, UIRen
|
|||||||
m_uiRenderer = uiRenderer;
|
m_uiRenderer = uiRenderer;
|
||||||
m_coreData = coreData;
|
m_coreData = coreData;
|
||||||
m_mainMenuUIManager = std::make_unique<MainMenuUIManager>(
|
m_mainMenuUIManager = std::make_unique<MainMenuUIManager>(
|
||||||
[this](const std::string& sceneName) {
|
[this](SceneType sceneType) {
|
||||||
if (m_eventCallback) {
|
if (m_eventCallback) {
|
||||||
SceneEvent event{SceneEventType::ChangeScene, sceneName};
|
SceneEvent event{SceneEventType::ChangeScene, sceneType};
|
||||||
m_eventCallback(event);
|
m_eventCallback(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
#include "ui/components/Button.h"
|
#include "ui/components/Button.h"
|
||||||
#include "ui/components/Label.h"
|
#include "ui/components/Label.h"
|
||||||
#include "ui/base/UIRenderData.h"
|
#include "ui/base/UIRenderData.h"
|
||||||
|
#include "scenes/base/SceneEvent.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class IUIManager {
|
class IUIManager {
|
||||||
public:
|
public:
|
||||||
using SceneEventCallback = std::function<void(const std::string&)>;
|
using SceneEventCallback = std::function<void(SceneType sceneType)>;
|
||||||
virtual ~IUIManager() = default;
|
virtual ~IUIManager() = default;
|
||||||
|
|
||||||
virtual void init() = 0;
|
virtual void init() = 0;
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ void GameUIManager::setupUIComponents() {
|
|||||||
550,
|
550,
|
||||||
20,
|
20,
|
||||||
[this](){
|
[this](){
|
||||||
m_eventCallback("MainMenuScene");
|
m_eventCallback(SceneType::MainMenuScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ MainMenuUIManager::~MainMenuUIManager() {
|
|||||||
void MainMenuUIManager::init() {
|
void MainMenuUIManager::init() {
|
||||||
auto startButton = UIWidgetFactory::createStandardButton(
|
auto startButton = UIWidgetFactory::createStandardButton(
|
||||||
"StartButton", "开始游戏", 275, 180,
|
"StartButton", "开始游戏", 275, 180,
|
||||||
[this]() { m_eventCallback("GameScene"); }
|
[this]() { m_eventCallback(SceneType::GameScene); }
|
||||||
);
|
);
|
||||||
|
|
||||||
m_buttons.emplace(startButton->getNameHash(), std::move(startButton));
|
m_buttons.emplace(startButton->getNameHash(), std::move(startButton));
|
||||||
|
|
||||||
auto onlineStartButton = UIWidgetFactory::createStandardButton(
|
auto onlineStartButton = UIWidgetFactory::createStandardButton(
|
||||||
"OnlineStartButton", "联机对战", 275, 250,
|
"OnlineStartButton", "联机对战", 275, 250,
|
||||||
[this]() {m_eventCallback("OnlineGameScene"); }
|
[this]() {m_eventCallback(SceneType::OnlineGameScene); }
|
||||||
);
|
);
|
||||||
|
|
||||||
m_buttons.emplace(onlineStartButton->getNameHash(), std::move(onlineStartButton));
|
m_buttons.emplace(onlineStartButton->getNameHash(), std::move(onlineStartButton));
|
||||||
|
|||||||
Reference in New Issue
Block a user