diff --git a/core/Base/GC.cpp b/core/Base/GC.cpp index e79ee259..8de1a327 100644 --- a/core/Base/GC.cpp +++ b/core/Base/GC.cpp @@ -42,7 +42,6 @@ e2d::GC::~GC() // 删除所有单例 Timer::destroyInstance(); - SceneManager::destroyInstance(); ActionManager::destroyInstance(); CollisionManager::destroyInstance(); } @@ -72,7 +71,7 @@ void e2d::GC::clear() { _cleanup = true; - SceneManager::getInstance()->clear(); + Game::getInstance()->clearAllScenes(); Timer::getInstance()->clearAllTasks(); ActionManager::getInstance()->clearAll(); diff --git a/core/Base/Game.cpp b/core/Base/Game.cpp index f86f030d..987c30a7 100644 --- a/core/Base/Game.cpp +++ b/core/Base/Game.cpp @@ -1,4 +1,6 @@ #include "..\e2dbase.h" +#include "..\e2dnode.h" +#include "..\e2dtransition.h" #include "..\e2dmanager.h" #include "..\e2dtool.h" #include @@ -11,6 +13,10 @@ e2d::Game::Game() , _window(nullptr) , _input(nullptr) , _renderer(nullptr) + , _currScene(nullptr) + , _nextScene(nullptr) + , _transition(nullptr) + , _scenes() { CoInitialize(nullptr); @@ -49,7 +55,7 @@ void e2d::Game::start() ::ShowWindow(hWnd, SW_SHOWNORMAL); ::UpdateWindow(hWnd); _window->poll(); - SceneManager::getInstance()->update(); + updateScene(); while (!_quit) { @@ -62,8 +68,8 @@ void e2d::Game::start() _input->update(); Timer::getInstance()->update(); ActionManager::getInstance()->update(); - SceneManager::getInstance()->update(); - _renderer->render(); + updateScene(); + drawScene(); _window->poll(); GC::getInstance()->flush(); } @@ -123,8 +129,183 @@ void e2d::Game::quit() _quit = true; } -void e2d::Game::cleanup() +void e2d::Game::pushScene(Scene * scene, bool saveCurrentScene) { - GC::getInstance()->clear(); - Image::clearCache(); + if (!scene) + return; + + // 保存下一场景的指针 + if (_nextScene) _nextScene->release(); + _nextScene = scene; + _nextScene->retain(); + + if (saveCurrentScene && _currScene) + { + _scenes.push(_currScene); + } +} + +void e2d::Game::pushScene(Transition * transition, bool saveCurrentScene) +{ + if (!transition) + return; + + pushScene(transition->_inScene, saveCurrentScene); + + if (_transition) + { + _transition->_stop(); + _transition->release(); + } + _transition = transition; + _transition->retain(); + + // 初始化场景切换动画 + if (!_transition->_init(_currScene)) + { + WARN("Transition initialize failed!"); + _transition->release(); + _transition = nullptr; + } +} + +e2d::Scene* e2d::Game::popScene() +{ + // 栈为空时,调用返回场景函数失败 + if (_scenes.size() == 0) + { + WARN("Scene stack is empty!"); + return nullptr; + } + + _nextScene = _scenes.top(); + _nextScene->release(); + _scenes.pop(); + + return _nextScene; +} + +e2d::Scene * e2d::Game::popScene(Transition * transition) +{ + if (!transition) + return nullptr; + + auto scene = popScene(); + if (scene) + { + if (_transition) + { + _transition->_stop(); + _transition->release(); + } + _transition = transition; + _transition->retain(); + + _transition->_inScene = scene; + _transition->_inScene->retain(); + + // 初始化场景切换动画 + if (!_transition->_init(_currScene)) + { + WARN("Transition initialize failed!"); + _transition->release(); + _transition = nullptr; + } + } + + return scene; +} + +void e2d::Game::clearAllScenes() +{ + while (!_scenes.empty()) + { + _scenes.top()->release(); + _scenes.pop(); + } +} + +e2d::Scene * e2d::Game::getCurrentScene() +{ + return _currScene; +} + +const std::stack& e2d::Game::getSceneStack() +{ + return _scenes; +} + +bool e2d::Game::isTransitioning() const +{ + return _transition != nullptr; +} + +void e2d::Game::updateScene() +{ + if (_transition) + { + _transition->_update(); + + if (_transition->isDone()) + { + _transition->release(); + _transition = nullptr; + } + else + { + return; + } + } + + if (_nextScene) + { + if (_currScene) + { + _currScene->onExit(); + if (_scenes.empty() || _scenes.top() != _currScene) + { + _currScene->release(); + } + } + + _nextScene->onEnter(); + + _currScene = _nextScene; + _nextScene = nullptr; + } +} + +void e2d::Game::drawScene() +{ + // 渲染画面 + _renderer->beginDraw(); + { + if (_transition) + { + _transition->_render(); + } + else if (_currScene) + { + _currScene->visit(_renderer); + + if (_config.isOutlineVisible()) + { + auto brush = _renderer->getSolidColorBrush(); + brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f)); + brush->SetOpacity(1.f); + _currScene->drawOutline(_renderer); + } + if (_config.isColliderVisible()) + { + _renderer->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); + _currScene->drawCollider(); + } + } + + if (_config.isFpsShow()) + { + _renderer->drawFps(); + } + } + _renderer->endDraw(); } diff --git a/core/Base/Renderer.cpp b/core/Base/Renderer.cpp index d608a74c..13d992ef 100644 --- a/core/Base/Renderer.cpp +++ b/core/Base/Renderer.cpp @@ -112,22 +112,16 @@ void e2d::Renderer::init(Window * window) ); } -void e2d::Renderer::render() +void e2d::Renderer::beginDraw() { // 开始渲染 _renderTarget->BeginDraw(); // 使用背景色清空屏幕 _renderTarget->Clear(_clearColor); +} - // 渲染场景 - SceneManager::getInstance()->render(); - - // 渲染 FPS - if (Game::getInstance()->getConfig().isFpsShow()) - { - _renderFps(); - } - +void e2d::Renderer::endDraw() +{ // 终止渲染 HRESULT hr = _renderTarget->EndDraw(); @@ -150,7 +144,7 @@ void e2d::Renderer::render() } } -void e2d::Renderer::_renderFps() +void e2d::Renderer::drawFps() { int duration = (Time::now() - _lastRenderTime).milliseconds(); diff --git a/core/Base/Window.cpp b/core/Base/Window.cpp index e3867ac8..1aa52929 100644 --- a/core/Base/Window.cpp +++ b/core/Base/Window.cpp @@ -50,7 +50,7 @@ e2d::Window::Window(const String & title, int width, int height, int iconID) Rect clientRect = __adjustWindow(_width, _height); // 创建窗口 - HWND hWnd = ::CreateWindowEx( + _hWnd = ::CreateWindowEx( NULL, REGISTER_CLASS, (LPCTSTR)_title, @@ -65,7 +65,7 @@ e2d::Window::Window(const String & title, int width, int height, int iconID) this ); - if (hWnd) + if (_hWnd) { // 禁用输入法 setTypewritingEnabled(false); @@ -77,7 +77,7 @@ e2d::Window::Window(const String & title, int width, int height, int iconID) ::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND); } // 获取 DPI - _dpi = static_cast(::GetDpiForWindow(hWnd)); + _dpi = static_cast(::GetDpiForWindow(_hWnd)); } else { @@ -409,7 +409,14 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_MOUSEMOVE: case WM_MOUSEWHEEL: { - SceneManager::getInstance()->dispatch(MouseEvent(hWnd, uMsg, wParam, lParam, window->_dpi)); + auto game = Game::getInstance(); + if (game->isTransitioning()) + break; + + if (game->getCurrentScene()) + { + game->getCurrentScene()->dispatch(MouseEvent(hWnd, uMsg, wParam, lParam, window->_dpi), false); + } } result = 0; hasHandled = true; @@ -419,7 +426,14 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_KEYDOWN: case WM_KEYUP: { - SceneManager::getInstance()->dispatch(KeyEvent(hWnd, uMsg, wParam, lParam)); + auto game = Game::getInstance(); + if (game->isTransitioning()) + break; + + if (game->getCurrentScene()) + { + game->getCurrentScene()->dispatch(KeyEvent(hWnd, uMsg, wParam, lParam), false); + } } result = 0; hasHandled = true; @@ -469,8 +483,7 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) // 重绘窗口 case WM_PAINT: { - auto renderer = Game::getInstance()->getRenderer(); - renderer->render(); + Game::getInstance()->drawScene(); ValidateRect(hWnd, nullptr); } result = 0; @@ -480,10 +493,11 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) // 窗口关闭消息 case WM_CLOSE: { - e2d::Scene * pCurrentScene = e2d::SceneManager::getInstance()->getCurrentScene(); - if (!pCurrentScene || pCurrentScene->onCloseWindow()) + auto game = Game::getInstance(); + auto currScene = game->getCurrentScene(); + if (!currScene || currScene->onCloseWindow()) { - e2d::Game::getInstance()->quit(); + game->quit(); } } result = 0; diff --git a/core/Manager/CollisionManager.cpp b/core/Manager/CollisionManager.cpp index 0fd8db44..08d21728 100644 --- a/core/Manager/CollisionManager.cpp +++ b/core/Manager/CollisionManager.cpp @@ -45,9 +45,10 @@ void e2d::CollisionManager::__removeCollider(Collider * collider) void e2d::CollisionManager::__updateCollider(Collider* collider) { - if (Game::getInstance()->isPaused() || - !Game::getInstance()->getConfig().isCollisionEnabled() || - SceneManager::getInstance()->isTransitioning()) + auto game = Game::getInstance(); + if (game->isPaused() || + !game->getConfig().isCollisionEnabled() || + game->isTransitioning()) return; std::vector currColliders; diff --git a/core/Manager/SceneManager.cpp b/core/Manager/SceneManager.cpp deleted file mode 100644 index c4fbaf48..00000000 --- a/core/Manager/SceneManager.cpp +++ /dev/null @@ -1,230 +0,0 @@ -#include "..\e2dmanager.h" -#include "..\e2devent.h" -#include "..\e2dnode.h" -#include "..\e2dtransition.h" - - -e2d::SceneManager * e2d::SceneManager::_instance = nullptr; - -e2d::SceneManager * e2d::SceneManager::getInstance() -{ - if (!_instance) - _instance = new (std::nothrow) SceneManager; - return _instance; -} - -void e2d::SceneManager::destroyInstance() -{ - if (_instance) - { - delete _instance; - _instance = nullptr; - } -} - -e2d::SceneManager::SceneManager() - : _currScene(nullptr) - , _nextScene(nullptr) - , _transition(nullptr) - , _scenes() -{ -} - -e2d::SceneManager::~SceneManager() -{ -} - -void e2d::SceneManager::push(Scene * scene, bool saveCurrentScene) -{ - if (!scene) - return; - - // 保存下一场景的指针 - if (_nextScene) _nextScene->release(); - _nextScene = scene; - _nextScene->retain(); - - if (saveCurrentScene && _currScene) - { - _scenes.push(_currScene); - } -} - -void e2d::SceneManager::push(Transition * transition, bool saveCurrentScene) -{ - if (!transition) - return; - - SceneManager::push(transition->_inScene, saveCurrentScene); - - if (_transition) - { - _transition->_stop(); - _transition->release(); - } - _transition = transition; - _transition->retain(); - - // 初始化场景切换动画 - if (!_transition->_init(_currScene)) - { - WARN("Transition initialize failed!"); - _transition->release(); - _transition = nullptr; - } -} - -e2d::Scene* e2d::SceneManager::pop() -{ - // 栈为空时,调用返回场景函数失败 - if (_scenes.size() == 0) - { - WARN("Scene stack is empty!"); - return nullptr; - } - - _nextScene = _scenes.top(); - _nextScene->release(); - _scenes.pop(); - - return _nextScene; -} - -e2d::Scene * e2d::SceneManager::pop(Transition * transition) -{ - if (!transition) - return nullptr; - - auto scene = SceneManager::pop(); - if (scene) - { - if (_transition) - { - _transition->_stop(); - _transition->release(); - } - _transition = transition; - _transition->retain(); - - _transition->_inScene = scene; - _transition->_inScene->retain(); - - // 初始化场景切换动画 - if (!_transition->_init(_currScene)) - { - WARN("Transition initialize failed!"); - _transition->release(); - _transition = nullptr; - } - } - - return scene; -} - -void e2d::SceneManager::clear() -{ - while (!_scenes.empty()) - { - _scenes.top()->release(); - _scenes.pop(); - } -} - -e2d::Scene * e2d::SceneManager::getCurrentScene() -{ - return _currScene; -} - -const std::stack& e2d::SceneManager::getSceneStack() -{ - return _scenes; -} - -bool e2d::SceneManager::isTransitioning() -{ - return _transition != nullptr; -} - -void e2d::SceneManager::update() -{ - if (_transition) - { - _transition->_update(); - - if (_transition->isDone()) - { - _transition->release(); - _transition = nullptr; - } - else - { - return; - } - } - - if (_nextScene) - { - if (_currScene) - { - _currScene->onExit(); - if (_scenes.empty() || _scenes.top() != _currScene) - { - _currScene->release(); - } - } - - _nextScene->onEnter(); - - _currScene = _nextScene; - _nextScene = nullptr; - } -} - -void e2d::SceneManager::render() -{ - if (_transition) - { - _transition->_render(); - } - else if (_currScene) - { - auto renderer = Game::getInstance()->getRenderer(); - _currScene->visit(renderer); - - auto& config = Game::getInstance()->getConfig(); - if (config.isOutlineVisible()) - { - auto brush = renderer->getSolidColorBrush(); - brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.6f)); - brush->SetOpacity(1.f); - _currScene->drawOutline(renderer); - } - if (config.isColliderVisible()) - { - renderer->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); - _currScene->drawCollider(); - } - } -} - -void e2d::SceneManager::dispatch(const MouseEvent & e) -{ - if (_transition != nullptr) - return; - - if (_currScene) - { - _currScene->dispatch(e, false); - } -} - -void e2d::SceneManager::dispatch(const KeyEvent & e) -{ - if (_transition != nullptr) - return; - - if (_currScene) - { - _currScene->dispatch(e, false); - } -} diff --git a/core/e2dbase.h b/core/e2dbase.h index 9e8d3caa..17539ea2 100644 --- a/core/e2dbase.h +++ b/core/e2dbase.h @@ -265,9 +265,6 @@ public: Color color ); - // 渲染游戏画面 - void render(); - // 获取文字渲染器 TextRenderer * getTextRenderer() const { return _textRenderer; } @@ -300,9 +297,14 @@ public: Window * window ); -private: + // 开始渲染 + void beginDraw(); + + // 结束渲染 + void endDraw(); + // 渲染 FPS - void _renderFps(); + void drawFps(); private: int _renderTimes; @@ -322,6 +324,9 @@ private: }; +class Scene; +class Transition; + // 游戏 class Game { @@ -329,6 +334,28 @@ public: // 获取 Game 实例 static Game * getInstance(); + // 获取窗体 + Window * getWindow() const { return _window; } + + // 获取输入设备 + Input * getInput() const { return _input; } + + // 获取图形设备 + Renderer * getRenderer() const { return _renderer; } + + // 获取游戏配置 + const Config& getConfig() const; + + // 设置窗体 + void setWindow( + Window * window + ); + + // 修改游戏配置 + void setConfig( + const Config& config + ); + // 启动游戏 void start(); @@ -341,33 +368,46 @@ public: // 结束游戏 void quit(); - // 清理资源 - void cleanup(); - // 游戏是否暂停 bool isPaused(); - // 修改游戏配置 - void setConfig( - const Config& config + // 场景入栈 + void pushScene( + Scene * scene, /* 下一个场景的指针 */ + bool saveCurrentScene = true /* 是否保存当前场景 */ ); - // 获取游戏配置 - const Config& getConfig() const; - - // 设置窗体 - void setWindow( - Window * window + // 场景入栈 + void pushScene( + Transition * transition, /* 场景动画 */ + bool saveCurrentScene = true /* 是否保存当前场景 */ ); - // 获取窗体 - Window * getWindow() const { return _window; } + // 场景出栈 + Scene* popScene(); - // 获取输入设备 - Input * getInput() const { return _input; } + // 场景出栈 + Scene* popScene( + Transition * transition /* 场景动画 */ + ); - // 获取图形设备 - Renderer * getRenderer() const { return _renderer; } + // 清空保存的所有场景 + void clearAllScenes(); + + // 获取当前场景 + Scene * getCurrentScene(); + + // 获取场景栈 + const std::stack& getSceneStack(); + + // 是否正在进行场景动画 + bool isTransitioning() const; + + // 更新场景内容 + void updateScene(); + + // 渲染场景画面 + void drawScene(); protected: Game(); @@ -380,10 +420,13 @@ private: bool _quit; bool _paused; Config _config; - Window * _window; - Input * _input; - Renderer * _renderer; - + Window* _window; + Input* _input; + Renderer* _renderer; + Scene* _currScene; + Scene* _nextScene; + Transition* _transition; + std::stack _scenes; }; diff --git a/core/e2dmanager.h b/core/e2dmanager.h index edf626fe..57dcfa93 100644 --- a/core/e2dmanager.h +++ b/core/e2dmanager.h @@ -7,87 +7,7 @@ namespace e2d class Node; -class Scene; class Action; -class KeyEvent; -class MouseEvent; -class Transition; - - -// 场景管理器 -class SceneManager -{ -public: - // 获取场景管理器实例 - static SceneManager * getInstance(); - - // 销毁实例 - static void destroyInstance(); - - // 场景入栈 - void push( - Scene * scene, /* 下一个场景的指针 */ - bool saveCurrentScene = true /* 是否保存当前场景 */ - ); - - // 场景入栈 - void push( - Transition * transition, /* 场景动画 */ - bool saveCurrentScene = true /* 是否保存当前场景 */ - ); - - // 场景出栈 - Scene* pop(); - - // 场景出栈 - Scene* pop( - Transition * transition /* 场景动画 */ - ); - - // 清空保存的所有场景 - void clear(); - - // 获取当前场景 - Scene * getCurrentScene(); - - // 获取场景栈 - const std::stack& getSceneStack(); - - // 是否正在进行转场动作 - bool isTransitioning(); - - // 更新场景内容 - void update(); - - // 渲染场景画面 - void render(); - - // 分发鼠标消息 - void dispatch( - const MouseEvent& e - ); - - // 分发按键消息 - void dispatch( - const KeyEvent& e - ); - -private: - SceneManager(); - - ~SceneManager(); - - E2D_DISABLE_COPY(SceneManager); - -private: - Scene * _currScene; - Scene * _nextScene; - Transition * _transition; - std::stack _scenes; - - static SceneManager * _instance; -}; - // 动作管理器 class ActionManager diff --git a/core/e2dtransition.h b/core/e2dtransition.h index 50fa4208..75348c9c 100644 --- a/core/e2dtransition.h +++ b/core/e2dtransition.h @@ -5,14 +5,14 @@ namespace e2d { +class Game; class Scene; -class SceneManager; // 场景过渡 class Transition : public Ref { - friend class SceneManager; + friend class Game; public: explicit Transition( diff --git a/project/vs2012/Easy2D.vcxproj b/project/vs2012/Easy2D.vcxproj index 4c3acdcb..1ff56162 100644 --- a/project/vs2012/Easy2D.vcxproj +++ b/project/vs2012/Easy2D.vcxproj @@ -79,7 +79,6 @@ - diff --git a/project/vs2012/Easy2D.vcxproj.filters b/project/vs2012/Easy2D.vcxproj.filters index b22b002a..39cdad0d 100644 --- a/project/vs2012/Easy2D.vcxproj.filters +++ b/project/vs2012/Easy2D.vcxproj.filters @@ -160,9 +160,6 @@ Manager - - Manager - Node diff --git a/project/vs2013/Easy2D.vcxproj b/project/vs2013/Easy2D.vcxproj index 27272915..12e0a26a 100644 --- a/project/vs2013/Easy2D.vcxproj +++ b/project/vs2013/Easy2D.vcxproj @@ -223,7 +223,6 @@ - diff --git a/project/vs2013/Easy2D.vcxproj.filters b/project/vs2013/Easy2D.vcxproj.filters index 27f5d73f..49e106d8 100644 --- a/project/vs2013/Easy2D.vcxproj.filters +++ b/project/vs2013/Easy2D.vcxproj.filters @@ -160,9 +160,6 @@ Manager - - Manager - Node diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index b3bf34d2..7cc4a6c2 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -243,7 +243,6 @@ - diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index 544586ce..44bca1b5 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -69,9 +69,6 @@ Base - - Manager - Base