From 06c96b56fa5887260bb07bf6f33430e3bfff5e0a Mon Sep 17 00:00:00 2001 From: Ziyu Date: Tue, 27 May 2025 17:23:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=9C=BA=E6=99=AF=E4=B8=8E?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 + src/engine/core/game_app.cpp | 100 ++++-------------- src/engine/core/game_app.h | 13 ++- src/engine/scene/scene.cpp | 134 ++++++++++++++++++++++++ src/engine/scene/scene.h | 99 ++++++++++++++++++ src/engine/scene/scene_manager.cpp | 160 +++++++++++++++++++++++++++++ src/engine/scene/scene_manager.h | 62 +++++++++++ src/game/scene/game_scene.cpp | 56 ++++++++++ src/game/scene/game_scene.h | 32 ++++++ 9 files changed, 570 insertions(+), 89 deletions(-) create mode 100644 src/engine/scene/scene.cpp create mode 100644 src/engine/scene/scene.h create mode 100644 src/engine/scene/scene_manager.cpp create mode 100644 src/engine/scene/scene_manager.h create mode 100644 src/game/scene/game_scene.cpp create mode 100644 src/game/scene/game_scene.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d38bee6..a576ff1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,9 @@ add_executable(${TARGET} src/engine/object/game_object.cpp src/engine/component/sprite_component.cpp src/engine/component/transform_component.cpp + src/engine/scene/scene.cpp + src/engine/scene/scene_manager.cpp + src/game/scene/game_scene.cpp ) # 链接库 diff --git a/src/engine/core/game_app.cpp b/src/engine/core/game_app.cpp index a2d9980..e8436c6 100644 --- a/src/engine/core/game_app.cpp +++ b/src/engine/core/game_app.cpp @@ -5,17 +5,14 @@ #include "../render/renderer.h" #include "../render/camera.h" #include "../input/input_manager.h" -#include "../object/game_object.h" -#include "../component/transform_component.h" -#include "../component/sprite_component.h" #include "config.h" +#include "../scene/scene_manager.h" +#include "../../game/scene/game_scene.h" #include #include namespace engine::core { -engine::object::GameObject game_object("test_game_object"); - GameApp::GameApp() = default; GameApp::~GameApp() { @@ -57,13 +54,14 @@ bool GameApp::init() { if (!initInputManager()) return false; if (!initContext()) return false; + if (!initSceneManager()) return false; - // 测试资源管理器 - testResourceManager(); + // 创建第一个场景并压入栈 + auto scene = std::make_unique("GameScene", *context_, *scene_manager_); + scene_manager_->requestPushScene(std::move(scene)); is_running_ = true; spdlog::trace("GameApp 初始化成功。"); - testGameObject(); return true; } @@ -74,12 +72,12 @@ void GameApp::handleEvents() { return; } - testInputManager(); + scene_manager_->handleInput(); } -void GameApp::update(float /* delta_time */) { +void GameApp::update(float delta_time) { // 游戏逻辑更新 - testCamera(); + scene_manager_->update(delta_time); } void GameApp::render() { @@ -87,8 +85,7 @@ void GameApp::render() { renderer_->clearScreen(); // 2. 具体渲染代码 - testRenderer(); - game_object.render(*context_); + scene_manager_->render(); // 3. 更新屏幕显示 renderer_->present(); @@ -222,77 +219,16 @@ bool GameApp::initContext() return true; } -// --- 测试用函数 --- - -void GameApp::testResourceManager() +bool GameApp::initSceneManager() { - resource_manager_->getTexture("assets/textures/Actors/eagle-attack.png"); - resource_manager_->getFont("assets/fonts/VonwaonBitmap-16px.ttf", 16); - resource_manager_->getSound("assets/audio/button_click.wav"); - - resource_manager_->unloadTexture("assets/textures/Actors/eagle-attack.png"); - resource_manager_->unloadFont("assets/fonts/VonwaonBitmap-16px.ttf", 16); - resource_manager_->unloadSound("assets/audio/button_click.wav"); -} - -void GameApp::testRenderer() -{ - engine::render::Sprite sprite_world("assets/textures/Actors/frog.png"); - engine::render::Sprite sprite_ui("assets/textures/UI/buttons/Start1.png"); - engine::render::Sprite sprite_parallax("assets/textures/Layers/back.png"); - - static float rotation = 0.0f; - rotation += 0.1f; - - // 注意渲染顺序 - renderer_->drawParallax(*camera_, sprite_parallax, glm::vec2(100, 100), glm::vec2(0.5f, 0.5f), glm::bvec2(true, false)); - renderer_->drawSprite(*camera_, sprite_world, glm::vec2(200, 200), glm::vec2(1.0f, 1.0f), rotation); - renderer_->drawUISprite(sprite_ui, glm::vec2(100, 100)); - -} - -void GameApp::testCamera() -{ - auto key_state = SDL_GetKeyboardState(nullptr); - if (key_state[SDL_SCANCODE_UP]) camera_->move(glm::vec2(0, -1)); - if (key_state[SDL_SCANCODE_DOWN]) camera_->move(glm::vec2(0, 1)); - if (key_state[SDL_SCANCODE_LEFT]) camera_->move(glm::vec2(-1, 0)); - if (key_state[SDL_SCANCODE_RIGHT]) camera_->move(glm::vec2(1, 0)); -} - -void GameApp::testInputManager() -{ - std::vector actions = { - "move_up", - "move_down", - "move_left", - "move_right", - "jump", - "attack", - "pause", - "MouseLeftClick", - "MouseRightClick" - }; - - for (const auto& action : actions) { - if (input_manager_->isActionPressed(action)) { - spdlog::info(" {} 按下 ", action); - } - if (input_manager_->isActionReleased(action)) { - spdlog::info(" {} 抬起 ", action); - } - if (input_manager_->isActionDown(action)) { - spdlog::info(" {} 按下中 ", action); - } + try { + scene_manager_ = std::make_unique(*context_); + } catch (const std::exception& e) { + spdlog::error("初始化场景管理器失败: {}", e.what()); + return false; } -} - -void GameApp::testGameObject() -{ - game_object.addComponent(glm::vec2(100, 100)); - game_object.addComponent("assets/textures/Props/big-crate.png", *resource_manager_, engine::utils::Alignment::CENTER); - game_object.getComponent()->setScale(glm::vec2(2.0f, 2.0f)); - game_object.getComponent()->setRotation(30.0f); + spdlog::trace("场景管理器初始化成功。"); + return true; } } // namespace engine::core \ No newline at end of file diff --git a/src/engine/core/game_app.h b/src/engine/core/game_app.h index 11bfc21..3f27ecb 100644 --- a/src/engine/core/game_app.h +++ b/src/engine/core/game_app.h @@ -18,6 +18,10 @@ namespace engine::input { class InputManager; } +namespace engine::scene { +class SceneManager; +} + namespace engine::core { // 命名空间的最佳实践:与文件路径一致 class Time; class Config; @@ -40,6 +44,7 @@ private: std::unique_ptr config_; std::unique_ptr input_manager_; std::unique_ptr context_; + std::unique_ptr scene_manager_; public: GameApp(); @@ -72,13 +77,7 @@ private: [[nodiscard]] bool initCamera(); [[nodiscard]] bool initInputManager(); [[nodiscard]] bool initContext(); - - // 测试用函数 - void testResourceManager(); - void testRenderer(); - void testCamera(); - void testInputManager(); - void testGameObject(); + [[nodiscard]] bool initSceneManager(); }; } // namespace engine::core diff --git a/src/engine/scene/scene.cpp b/src/engine/scene/scene.cpp new file mode 100644 index 0000000..9e1c219 --- /dev/null +++ b/src/engine/scene/scene.cpp @@ -0,0 +1,134 @@ +#include "scene.h" +#include "../object/game_object.h" +#include "scene_manager.h" +#include // for std::remove_if +#include + +namespace engine::scene { + +Scene::Scene(std::string name, engine::core::Context& context, engine::scene::SceneManager& scene_manager) + : scene_name_(std::move(name)), context_(context), scene_manager_(scene_manager), is_initialized_(false) { + spdlog::trace("场景 '{}' 构造完成。", scene_name_); +} + +Scene::~Scene() = default; + +void Scene::init() { + is_initialized_ = true; // 子类应该最后调用父类的 init 方法 + spdlog::trace("场景 '{}' 初始化完成。", scene_name_); +} + +void Scene::update(float delta_time) { + if (!is_initialized_) return; + + // 更新所有游戏对象,并删除需要移除的对象 + for (auto it = game_objects_.begin(); it != game_objects_.end();) { + if (*it && !(*it)->isNeedRemove()) { // 正常更新游戏对象 + (*it)->update(delta_time, context_); + ++it; + } else { + if (*it) { // 安全删除需要移除的对象 + (*it)->clean(); + } + it = game_objects_.erase(it); // 删除需要移除的对象,智能指针自动管理内存 + } + } + + processPendingAdditions(); // 处理待添加(延时添加)的游戏对象 +} + +void Scene::render() { + if (!is_initialized_) return; + // 渲染所有游戏对象 + for (const auto& obj : game_objects_) { + if (obj) obj->render(context_); + } +} + +void Scene::handleInput() { + if (!is_initialized_) return; + + // 遍历所有游戏对象,并删除需要移除的对象 + for (auto it = game_objects_.begin(); it != game_objects_.end();) { + if (*it && !(*it)->isNeedRemove()) { + (*it)->handleInput(context_); + ++it; + } else { + // 安全删除需要移除的对象 + if (*it) (*it)->clean(); + it = game_objects_.erase(it); + } + } +} + +void Scene::clean() { + if (!is_initialized_) return; + + for (const auto& obj : game_objects_) { + if (obj) obj->clean(); + } + game_objects_.clear(); + + is_initialized_ = false; // 清理完成后,设置场景为未初始化 + spdlog::trace("场景 '{}' 清理完成。", scene_name_); +} + +void Scene::addGameObject(std::unique_ptr&& game_object) { + if (game_object) game_objects_.push_back(std::move(game_object)); + else spdlog::warn("尝试向场景 '{}' 添加空游戏对象。", scene_name_); +} + +void Scene::safeAddGameObject(std::unique_ptr&& game_object) +{ + if (game_object) pending_additions_.push_back(std::move(game_object)); + else spdlog::warn("尝试向场景 '{}' 添加空游戏对象。", scene_name_); +} + +void Scene::removeGameObject(engine::object::GameObject* game_object_ptr) { + if (!game_object_ptr) { + spdlog::warn("尝试从场景 '{}' 中移除一个空的游戏对象指针。", scene_name_); + return; + } + + // erase-remove 移除法不可用,因为智能指针与裸指针无法比较 + // 需要使用 std::remove_if 和 lambda 表达式自定义比较的方式 + auto it = std::remove_if(game_objects_.begin(), game_objects_.end(), + [game_object_ptr](const std::unique_ptr& p) { + return p.get() == game_object_ptr; // 比较裸指针是否相等(自定义比较方式) + }); + + if (it != game_objects_.end()) { + (*it)->clean(); // 因为传入的是指针,因此只可能有一个元素被移除,不需要遍历it到末尾 + game_objects_.erase(it, game_objects_.end()); // 删除从it到末尾的元素(最后一个元素) + spdlog::trace("从场景 '{}' 中移除游戏对象。", scene_name_); + } else { + spdlog::warn("游戏对象指针未找到在场景 '{}' 中。", scene_name_); + } +} + +void Scene::safeRemoveGameObject(engine::object::GameObject* game_object_ptr) +{ + game_object_ptr->setNeedRemove(true); +} + +engine::object::GameObject *Scene::findGameObjectByName(const std::string &name) const +{ + // 找到第一个符合条件的游戏对象就返回 + for (const auto& obj : game_objects_) { + if (obj && obj->getName() == name) { + return obj.get(); + } + } + return nullptr; +} + +void Scene::processPendingAdditions() +{ + // 处理待添加的游戏对象 + for (auto& game_object : pending_additions_) { + addGameObject(std::move(game_object)); + } + pending_additions_.clear(); +} + +} // namespace engine::scene \ No newline at end of file diff --git a/src/engine/scene/scene.h b/src/engine/scene/scene.h new file mode 100644 index 0000000..98836f5 --- /dev/null +++ b/src/engine/scene/scene.h @@ -0,0 +1,99 @@ +#pragma once +#include +#include +#include + +namespace engine::core { + class Context; +} + +namespace engine::render { + class Renderer; + class Camera; +} + +namespace engine::input { + class InputManager; +} + +namespace engine::object { + class GameObject; +} + +namespace engine::scene { + class SceneManager; + +/** + * @brief 场景基类,负责管理场景中的游戏对象和场景生命周期。 + * + * 包含一组游戏对象,并提供更新、渲染、处理输入和清理的接口。 + * 派生类应实现具体的场景逻辑。 + */ +class Scene { +protected: + std::string scene_name_; ///< @brief 场景名称 + engine::core::Context& context_; ///< @brief 上下文引用(隐式,构造时传入) + engine::scene::SceneManager& scene_manager_; ///< @brief 场景管理器引用(构造时传入) + bool is_initialized_ = false; ///< @brief 场景是否已初始化(非当前场景很可能未被删除,因此需要初始化标志避免重复初始化) + std::vector> game_objects_; ///< @brief 场景中的游戏对象 + std::vector> pending_additions_; ///< @brief 待添加的游戏对象(延时添加) + +public: + /** + * @brief 构造函数。 + * + * @param name 场景的名称。 + * @param context 场景上下文。 + * @param scene_manager 场景管理器。 + */ + Scene(std::string name, engine::core::Context& context, engine::scene::SceneManager& scene_manager); + + virtual ~Scene(); // 1. 基类必须声明虚析构函数才能让派生类析构函数被正确调用。 + // 2. 析构函数定义必须写在cpp中,不然需要引入GameObject头文件 + + // 禁止拷贝和移动构造 + Scene(const Scene&) = delete; + Scene& operator=(const Scene&) = delete; + Scene(Scene&&) = delete; + Scene& operator=(Scene&&) = delete; + + // 核心循环方法 + virtual void init(); ///< @brief 初始化场景。 + virtual void update(float delta_time); ///< @brief 更新场景。 + virtual void render(); ///< @brief 渲染场景。 + virtual void handleInput(); ///< @brief 处理输入。 + virtual void clean(); ///< @brief 清理场景。 + + /// @brief 直接向场景中添加一个游戏对象。(初始化时可用,游戏进行中不安全) (&&表示右值引用,与std::move搭配使用,避免拷贝) + virtual void addGameObject(std::unique_ptr&& game_object); + + /// @brief 安全地添加游戏对象。(添加到pending_additions_中) + virtual void safeAddGameObject(std::unique_ptr&& game_object); + + /// @brief 直接从场景中移除一个游戏对象。(一般不使用,但保留实现的逻辑) + virtual void removeGameObject(engine::object::GameObject* game_object_ptr); + + /// @brief 安全地移除游戏对象。(设置need_remove_标记) + virtual void safeRemoveGameObject(engine::object::GameObject* game_object_ptr); + + /// @brief 获取场景中的游戏对象容器。 + const std::vector>& getGameObjects() const { return game_objects_; } + + /// @brief 根据名称查找游戏对象(返回找到的第一个对象)。 + engine::object::GameObject* findGameObjectByName(const std::string& name) const; + + // getters and setters + void setName(const std::string& name) { scene_name_ = name; } ///< @brief 设置场景名称 + const std::string& getName() const { return scene_name_; } ///< @brief 获取场景名称 + void setInitialized(bool initialized) { is_initialized_ = initialized; } ///< @brief 设置场景是否已初始化 + bool isInitialized() const { return is_initialized_; } ///< @brief 获取场景是否已初始化 + + engine::core::Context& getContext() const { return context_; } ///< @brief 获取上下文引用 + engine::scene::SceneManager& getSceneManager() const { return scene_manager_; } ///< @brief 获取场景管理器引用 + std::vector>& getGameObjects() { return game_objects_; } ///< @brief 获取场景中的游戏对象 + +protected: + void processPendingAdditions(); ///< @brief 处理待添加的游戏对象。(每轮更新的最后调用) +}; + +} // namespace engine::scene \ No newline at end of file diff --git a/src/engine/scene/scene_manager.cpp b/src/engine/scene/scene_manager.cpp new file mode 100644 index 0000000..9fd882b --- /dev/null +++ b/src/engine/scene/scene_manager.cpp @@ -0,0 +1,160 @@ +#include "scene_manager.h" +#include "scene.h" +#include "../core/context.h" +#include + +namespace engine::scene { + +SceneManager::SceneManager(engine::core::Context& context) + : context_(context) { + spdlog::trace("场景管理器已创建。"); +} + +SceneManager::~SceneManager() { + spdlog::trace("场景管理器已销毁。"); + close(); // 即使不手动调用 close 也能确保清理 +} + +Scene* SceneManager::getCurrentScene() const { + if (scene_stack_.empty()) { + return nullptr; + } + return scene_stack_.back().get(); // 返回栈顶场景的裸指针 +} + +void SceneManager::update(float delta_time) { + // 只更新栈顶(当前)场景 + Scene* current_scene = getCurrentScene(); + if (current_scene) { + current_scene->update(delta_time); + } + // 执行可能的切换场景操作 + processPendingActions(); +} + +void SceneManager::render() { + // 渲染时需要叠加渲染所有场景,而不只是栈顶 + for (const auto& scene : scene_stack_) { + if (scene) { + scene->render(); + } + } +} + +void SceneManager::handleInput() { + // 只考虑栈顶场景 + Scene* current_scene = getCurrentScene(); + if (current_scene) { + current_scene->handleInput(); + } +} + +void SceneManager::close() { + spdlog::trace("正在关闭场景管理器并清理场景栈..."); + // 清理栈中所有剩余的场景(从顶到底) + while (!scene_stack_.empty()) { + if (scene_stack_.back()) { + spdlog::debug("正在清理场景 '{}' 。", scene_stack_.back()->getName()); + scene_stack_.back()->clean(); + } + scene_stack_.pop_back(); + } +} + +void SceneManager::requestPopScene() +{ + pending_action_ = PendingAction::Pop; +} + +void SceneManager::requestReplaceScene(std::unique_ptr&& scene) +{ + pending_action_ = PendingAction::Replace; + pending_scene_ = std::move(scene); +} + +void SceneManager::requestPushScene(std::unique_ptr&& scene) +{ + pending_action_ = PendingAction::Push; + pending_scene_ = std::move(scene); +} + +// --- Private Methods --- + +void SceneManager::processPendingActions() +{ + if (pending_action_ == PendingAction::None) { + return; + } + + switch (pending_action_) { + case PendingAction::Pop: + popScene(); + break; + case PendingAction::Replace: + replaceScene(std::move(pending_scene_)); + break; + case PendingAction::Push: + pushScene(std::move(pending_scene_)); + break; + default: + break; + } + + pending_action_ = PendingAction::None; +} + +void SceneManager::pushScene(std::unique_ptr&& scene) { + if (!scene) { + spdlog::warn("尝试将空场景压入栈。"); + return; + } + spdlog::debug("正在将场景 '{}' 压入栈。", scene->getName()); + + // 初始化新场景 + if (!scene->isInitialized()) { // 确保只初始化一次 + scene->init(); + } + + // 将新场景移入栈顶 + scene_stack_.push_back(std::move(scene)); +} + +void SceneManager::popScene() { + if (scene_stack_.empty()) { + spdlog::warn("尝试从空场景栈中弹出。"); + return; + } + spdlog::debug("正在从栈中弹出场景 '{}' 。", scene_stack_.back()->getName()); + + // 清理并移除栈顶场景 + if (scene_stack_.back()) { + scene_stack_.back()->clean(); // 显式调用清理 + } + scene_stack_.pop_back(); +} + +void SceneManager::replaceScene(std::unique_ptr&& scene) { + if (!scene) { + spdlog::warn("尝试用空场景替换。"); + return; + } + spdlog::debug("正在用场景 '{}' 替换场景 '{}' 。", scene->getName(), scene_stack_.back()->getName()); + + // 清理并移除场景栈中所有场景 + while (!scene_stack_.empty()) { + if (scene_stack_.back()) { + scene_stack_.back()->clean(); + } + scene_stack_.pop_back(); + } + + // 初始化新场景 + if (!scene->isInitialized()) { + scene->init(); + } + + // 将新场景压入栈顶 + scene_stack_.push_back(std::move(scene)); +} + +} // namespace engine::scene \ No newline at end of file diff --git a/src/engine/scene/scene_manager.h b/src/engine/scene/scene_manager.h new file mode 100644 index 0000000..5e53b80 --- /dev/null +++ b/src/engine/scene/scene_manager.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#include + +// 前置声明 +namespace engine::core { + class Context; +} +namespace engine::scene { + class Scene; +} + +namespace engine::scene { + +/** + * @brief 管理游戏中的场景栈,处理场景切换和生命周期。 + */ +class SceneManager final { +private: + engine::core::Context& context_; ///< @brief 引擎上下文引用 + std::vector> scene_stack_; ///< @brief 场景栈 + + enum class PendingAction { None, Push, Pop, Replace }; ///< @brief 待处理的动作 + PendingAction pending_action_ = PendingAction::None; ///< @brief 待处理的动作 + std::unique_ptr pending_scene_; ///< @brief 待处理场景 + +public: + explicit SceneManager(engine::core::Context& context); + ~SceneManager(); + + // 禁止拷贝和移动 + SceneManager(const SceneManager&) = delete; + SceneManager& operator=(const SceneManager&) = delete; + SceneManager(SceneManager&&) = delete; + SceneManager& operator=(SceneManager&&) = delete; + + // 延时切换场景 + void requestPushScene(std::unique_ptr&& scene); ///< @brief 请求压入一个新场景。 + void requestPopScene(); ///< @brief 请求弹出当前场景。 + void requestReplaceScene(std::unique_ptr&& scene); ///< @brief 请求替换当前场景。 + + // getters + Scene* getCurrentScene() const; ///< @brief 获取当前活动场景(栈顶场景)的指针。 + engine::core::Context& getContext() const { return context_; } ///< @brief 获取引擎上下文引用。 + + // 核心循环函数 + void update(float delta_time); + void render(); + void handleInput(); + void close(); + +private: + void processPendingActions(); ///< @brief 处理挂起的场景操作(每轮更新最后调用)。 + // 直接切换场景 + void pushScene(std::unique_ptr&& scene); ///< @brief 将一个新场景压入栈顶,使其成为活动场景。 + void popScene(); ///< @brief 移除栈顶场景。 + void replaceScene(std::unique_ptr&& scene); ///< @brief 清理场景栈所有场景,将此场景设为栈顶场景。 + +}; + +} // namespace engine::scene \ No newline at end of file diff --git a/src/game/scene/game_scene.cpp b/src/game/scene/game_scene.cpp new file mode 100644 index 0000000..09c90e7 --- /dev/null +++ b/src/game/scene/game_scene.cpp @@ -0,0 +1,56 @@ +#include "game_scene.h" +#include "../../engine/core/context.h" +#include "../../engine/object/game_object.h" +#include "../../engine/component/transform_component.h" +#include "../../engine/component/sprite_component.h" +#include +#include + +namespace game::scene { + +// 构造函数:调用基类构造函数 +GameScene::GameScene(std::string name, engine::core::Context& context, engine::scene::SceneManager& scene_manager) + : Scene(name, context, scene_manager) { + spdlog::trace("GameScene 构造完成。"); +} + +void GameScene::init() { + // 创建 test_object + createTestObject(); + + Scene::init(); + spdlog::trace("GameScene 初始化完成。"); +} + +void GameScene::update(float delta_time) { + Scene::update(delta_time); +} + +void GameScene::render() { + Scene::render(); +} + +void GameScene::handleInput() { + Scene::handleInput(); +} + +void GameScene::clean() { + Scene::clean(); +} + +// --- 私有方法 --- + +void GameScene::createTestObject() { + spdlog::trace("在 GameScene 中创建 test_object..."); + auto test_object = std::make_unique("test_object"); + + // 添加组件 + test_object->addComponent(glm::vec2(100.0f, 100.0f)); + test_object->addComponent("assets/textures/Props/big-crate.png", context_.getResourceManager()); + + // 将创建好的 GameObject 添加到场景中 (一定要用std::move,否则传递的是左值) + addGameObject(std::move(test_object)); + spdlog::trace("test_object 创建并添加到 GameScene 中。"); +} + +} // namespace game::scene \ No newline at end of file diff --git a/src/game/scene/game_scene.h b/src/game/scene/game_scene.h new file mode 100644 index 0000000..c054890 --- /dev/null +++ b/src/game/scene/game_scene.h @@ -0,0 +1,32 @@ +#pragma once +#include "../../engine/scene/scene.h" +#include + +// 前置声明 +namespace engine::object { + class GameObject; +} + +namespace game::scene { + +/** + * @brief 主要的游戏场景,包含玩家、敌人、关卡元素等。 + */ +class GameScene final: public engine::scene::Scene { + +public: + GameScene(std::string name, engine::core::Context& context, engine::scene::SceneManager& scene_manager); + + // 覆盖场景基类的核心方法 + void init() override; + void update(float delta_time) override; + void render() override; + void handleInput() override; + void clean() override; + +private: + // 测试函数 + void createTestObject(); +}; + +} // namespace game::scene \ No newline at end of file