diff --git a/Easy2D/Base/App.cpp b/Easy2D/Base/App.cpp index 80a6bb54..197c1eb6 100644 --- a/Easy2D/Base/App.cpp +++ b/Easy2D/Base/App.cpp @@ -17,7 +17,8 @@ App::App() : m_pCurrentScene(nullptr), m_pNextScene(nullptr), m_bRunning(false), - m_nWindowMode(0) + m_nWindowMode(0), + m_bSaveScene(true) { assert(!s_pInstance); // 不能同时存在两个 App 实例 s_pInstance = this; // 保存实例对象 @@ -135,15 +136,8 @@ void App::_mainLoop() // 下一场景指针不为空时,切换场景 if (m_pNextScene) { - // 执行当前场景的 onExit 函数 - if (m_pCurrentScene) - { - m_pCurrentScene->onExit(); - } // 进入下一场景 _enterNextScene(); - // 执行当前场景的 onEnter 函数 - m_pCurrentScene->onEnter(); } // 断言当前场景非空 assert(m_pCurrentScene); @@ -289,23 +283,58 @@ void App::setBkColor(COLORREF color) void App::_enterNextScene() { + bool bBackScene = false; + // 若下一场景处于栈顶,说明正在返回上一场景 if (m_SceneStack.size() && m_pNextScene == m_SceneStack.top()) { - m_SceneStack.pop(); // 删除栈顶场景 + bBackScene = true; + // 删除栈顶场景 + m_SceneStack.pop(); } - - if (m_bSaveScene && m_pCurrentScene) + + // 执行当前场景的 onExit 函数 + if (m_pCurrentScene) { - m_SceneStack.push(m_pCurrentScene); // 若要保存当前场景,把它的指针放到栈顶 + m_pCurrentScene->onExit(); + if (m_bSaveScene) + { + // 若要保存当前场景,把它放入栈中 + m_SceneStack.push(m_pCurrentScene); + // 暂停当前场景上运行的所有定时器 + Timer::stopAllSceneTimers(m_pCurrentScene); + MouseMsg::stopAllSceneListeners(m_pCurrentScene); + KeyMsg::stopAllSceneListeners(m_pCurrentScene); + ActionManager::pauseAllSceneActions(m_pCurrentScene); + } + else + { + // 不保存场景时,停止当前场景上运行的所有定时器,并删除当前场景 + Timer::clearAllSceneTimers(m_pCurrentScene); + MouseMsg::clearAllSceneListeners(m_pCurrentScene); + KeyMsg::clearAllSceneListeners(m_pCurrentScene); + ActionManager::stopAllSceneActions(m_pCurrentScene); + SafeDelete(m_pCurrentScene); + } + } + + m_pCurrentScene = m_pNextScene; // 切换场景 + m_pNextScene = nullptr; // 下一场景置空 + + if (bBackScene) + { + // 返回上一场景时,恢复场景上的定时器 + Timer::startAllSceneTimers(m_pCurrentScene); + MouseMsg::startAllSceneListeners(m_pCurrentScene); + KeyMsg::startAllSceneListeners(m_pCurrentScene); + ActionManager::startAllSceneActions(m_pCurrentScene); } else { - SafeDelete(m_pCurrentScene); // 删除当前场景 + m_pCurrentScene->init(); // 进入一个新场景时,执行它的 init 函数 } - - m_pCurrentScene = m_pNextScene; // 切换场景 - m_pNextScene = nullptr; // 下一场景置空 + + m_pCurrentScene->onEnter(); // 执行下一场景的 onEnter 函数 } void App::quit() diff --git a/Easy2D/Base/Scene.cpp b/Easy2D/Base/Scene.cpp index e95da47f..f16b175b 100644 --- a/Easy2D/Base/Scene.cpp +++ b/Easy2D/Base/Scene.cpp @@ -37,20 +37,10 @@ void Scene::_onDraw() void Scene::onEnter() { - // 将定时器与当前场景绑定 - Timer::bindTimersWithScene(this); - MouseMsg::bindListenersWithScene(this); - KeyMsg::bindListenersWithScene(this); - ActionManager::bindActionsWithScene(this); } void Scene::onExit() { - // 停止当前场景上运行的所有定时器 - Timer::stopAllSceneTimers(this); - MouseMsg::clearAllSceneListeners(this); - KeyMsg::clearAllSceneListeners(this); - ActionManager::stopAllSceneActions(this); } void Scene::add(Node * child, int zOrder) diff --git a/Easy2D/Msg/KeyMsg.cpp b/Easy2D/Msg/KeyMsg.cpp index a41a98cf..9a8f1db6 100644 --- a/Easy2D/Msg/KeyMsg.cpp +++ b/Easy2D/Msg/KeyMsg.cpp @@ -3,7 +3,7 @@ #include // 按键监听回调函数的容器 -static std::vector s_vKeyMsg; +static std::vector s_vListeners; // 虚拟键值的定义 const VK_KEY KeyMsg::A = 'A'; @@ -83,7 +83,8 @@ static VK_KEY convert(int ascii); KeyMsg::KeyMsg(TString name, const KEY_CALLBACK & callback) : m_sName(name), m_callback(callback), - m_pParentScene(nullptr) + m_pParentScene(nullptr), + m_bRunning(true) { } @@ -96,15 +97,28 @@ void KeyMsg::onKbHit(VK_KEY key) m_callback(key); } +void KeyMsg::start() +{ + m_bRunning = true; +} + +void KeyMsg::stop() +{ + m_bRunning = false; +} + void KeyMsg::__exec() { if (_kbhit()) // 检测有无按键消息 { VK_KEY key = convert(_getch()); // 获取键盘消息 - for (auto k : s_vKeyMsg) // 分发该消息 + for (auto l : s_vListeners) // 分发该消息 { - k->onKbHit(key); // 执行按键回调函数 + if (l->m_bRunning) + { + l->onKbHit(key); // 执行按键回调函数 + } } } } @@ -112,39 +126,76 @@ void KeyMsg::__exec() void KeyMsg::addListener(TString name, const KEY_CALLBACK & callback) { // 创建新的监听对象 - auto key = new KeyMsg(name, callback); - key->m_pParentScene = App::getCurrentScene(); + auto listener = new KeyMsg(name, callback); + // 绑定在场景上 + listener->m_pParentScene = App::getCurrentScene(); // 添加新的按键回调函数 - s_vKeyMsg.push_back(key); + s_vListeners.push_back(listener); } -bool KeyMsg::delListener(TString name) +void KeyMsg::startListener(TString name) +{ + // 查找名称相同的监听器 + for (auto l : s_vListeners) + { + if (l->m_sName == name && l->m_pParentScene == App::getCurrentScene()) + { + l->start(); + } + } +} + +void KeyMsg::stopListener(TString name) +{ + // 查找名称相同的监听器 + for (auto l : s_vListeners) + { + if (l->m_sName == name && l->m_pParentScene == App::getCurrentScene()) + { + l->stop(); + } + } +} + +void KeyMsg::delListener(TString name) { // 创建迭代器 std::vector::iterator iter; // 循环遍历所有监听器 - for (iter = s_vKeyMsg.begin(); iter != s_vKeyMsg.end(); iter++) + for (iter = s_vListeners.begin(); iter != s_vListeners.end();) { // 查找相同名称的监听器 - if ((*iter)->m_sName == name) + if ((*iter)->m_sName == name && (*iter)->m_pParentScene == App::getCurrentScene()) { // 删除该定时器 delete (*iter); - s_vKeyMsg.erase(iter); - return true; + iter = s_vListeners.erase(iter); + } + else + { + iter++; } } - // 若未找到同样名称的监听器,返回 false - return false; } -void KeyMsg::bindListenersWithScene(Scene * scene) +void KeyMsg::startAllSceneListeners(Scene * scene) { - for (auto k : s_vKeyMsg) + for (auto l : s_vListeners) { - if (!k->m_pParentScene) + if (l->m_pParentScene == scene) { - k->m_pParentScene = App::getCurrentScene(); + l->start(); + } + } +} + +void KeyMsg::stopAllSceneListeners(Scene * scene) +{ + for (auto l : s_vListeners) + { + if (l->m_pParentScene == scene) + { + l->stop(); } } } @@ -154,14 +205,14 @@ void KeyMsg::clearAllSceneListeners(Scene * scene) // 创建迭代器 std::vector::iterator iter; // 循环遍历所有监听器 - for (iter = s_vKeyMsg.begin(); iter != s_vKeyMsg.end(); iter++) + for (iter = s_vListeners.begin(); iter != s_vListeners.end(); iter++) { // 查找相同名称的监听器 if ((*iter)->m_pParentScene == scene) { // 删除该定时器 delete (*iter); - s_vKeyMsg.erase(iter); + s_vListeners.erase(iter); } } } @@ -169,12 +220,12 @@ void KeyMsg::clearAllSceneListeners(Scene * scene) void KeyMsg::clearAllListeners() { // 删除所有监听器 - for (auto k : s_vKeyMsg) + for (auto l : s_vListeners) { - delete k; + delete l; } // 清空容器 - s_vKeyMsg.clear(); + s_vListeners.clear(); } bool KeyMsg::isKeyDown(VK_KEY key) diff --git a/Easy2D/Msg/MouseMsg.cpp b/Easy2D/Msg/MouseMsg.cpp index 1e1cf53d..14b5d693 100644 --- a/Easy2D/Msg/MouseMsg.cpp +++ b/Easy2D/Msg/MouseMsg.cpp @@ -2,7 +2,7 @@ #include "..\EasyX\easyx.h" // 鼠标监听回调函数的容器 -static std::vector s_vMouseMsg; +static std::vector s_vListeners; // 鼠标消息 static MOUSEMSG s_mouseMsg; @@ -17,23 +17,28 @@ void MouseMsg::__exec() // 执行场景程序 App::get()->getCurrentScene()->_exec(); // 执行鼠标监听回调函数 - for (auto m : s_vMouseMsg) // 循环遍历所有的鼠标监听 + for (auto l : s_vListeners) // 循环遍历所有的鼠标监听 { - m->onMouseMsg(); // 执行回调函数 + if (l->m_bRunning) + { + l->onMouseMsg(); // 执行回调函数 + } } } } MouseMsg::MouseMsg() : m_callback([]() {}), - m_pParentScene(nullptr) + m_pParentScene(nullptr), + m_bRunning(true) { } MouseMsg::MouseMsg(TString name, const MOUSE_CALLBACK & callback) : m_sName(name), m_callback(callback), - m_pParentScene(nullptr) + m_pParentScene(nullptr), + m_bRunning(true) { } @@ -49,39 +54,97 @@ void MouseMsg::onMouseMsg() void MouseMsg::addListener(TString name, const MOUSE_CALLBACK & callback) { // 创建新的监听对象 - auto mouse = new MouseMsg(name, callback); - mouse->m_pParentScene = App::getCurrentScene(); + auto listener = new MouseMsg(name, callback); + // 绑定在场景上 + listener->m_pParentScene = App::getCurrentScene(); // 添加新的按键回调函数 - s_vMouseMsg.push_back(mouse); + s_vListeners.push_back(listener); } -bool MouseMsg::delListener(TString name) +void MouseMsg::startListener(TString name) +{ + // 查找名称相同的监听器 + for (auto l : s_vListeners) + { + if (l->m_sName == name && l->m_pParentScene == App::getCurrentScene()) + { + l->start(); + } + } +} + +void MouseMsg::stopListener(TString name) +{ + // 查找名称相同的监听器 + for (auto l : s_vListeners) + { + if (l->m_sName == name && l->m_pParentScene == App::getCurrentScene()) + { + l->stop(); + } + } +} + +void MouseMsg::delListener(TString name) { // 创建迭代器 std::vector::iterator iter; // 循环遍历所有监听器 - for (iter = s_vMouseMsg.begin(); iter != s_vMouseMsg.end(); iter++) + for (iter = s_vListeners.begin(); iter != s_vListeners.end();) { // 查找相同名称的监听器 - if ((*iter)->m_sName == name) + if ((*iter)->m_sName == name && (*iter)->m_pParentScene == App::getCurrentScene()) { // 删除该定时器 delete (*iter); - s_vMouseMsg.erase(iter); - return true; + iter = s_vListeners.erase(iter); + } + else + { + iter++; } } - // 若未找到同样名称的监听器,返回 false - return false; } -void MouseMsg::bindListenersWithScene(Scene * scene) +void MouseMsg::start() { - for (auto m : s_vMouseMsg) + m_bRunning = true; +} + +void MouseMsg::stop() +{ + m_bRunning = false; +} + +void MouseMsg::clearAllListeners() +{ + // 删除所有监听器 + for (auto l : s_vListeners) { - if (!m->m_pParentScene) + delete l; + } + // 清空容器 + s_vListeners.clear(); +} + +void MouseMsg::startAllSceneListeners(Scene * scene) +{ + for (auto l : s_vListeners) + { + if (l->m_pParentScene == scene) { - m->m_pParentScene = App::getCurrentScene(); + l->start(); + } + } +} + +void MouseMsg::stopAllSceneListeners(Scene * scene) +{ + for (auto l : s_vListeners) + { + if (l->m_pParentScene == scene) + { + l->stop(); } } } @@ -91,29 +154,18 @@ void MouseMsg::clearAllSceneListeners(Scene * scene) // 创建迭代器 std::vector::iterator iter; // 循环遍历所有监听器 - for (iter = s_vMouseMsg.begin(); iter != s_vMouseMsg.end(); iter++) + for (iter = s_vListeners.begin(); iter != s_vListeners.end(); iter++) { // 查找相同名称的监听器 if ((*iter)->m_pParentScene == scene) { // 删除该定时器 delete (*iter); - s_vMouseMsg.erase(iter); + s_vListeners.erase(iter); } } } -void MouseMsg::clearAllListeners() -{ - // 删除所有监听器 - for (auto m : s_vMouseMsg) - { - delete m; - } - // 清空容器 - s_vMouseMsg.clear(); -} - bool MouseMsg::isLButtonDown() { return s_mouseMsg.mkLButton; diff --git a/Easy2D/Object/MouseNode.cpp b/Easy2D/Object/MouseNode.cpp index 4203e484..3ef74b2d 100644 --- a/Easy2D/Object/MouseNode.cpp +++ b/Easy2D/Object/MouseNode.cpp @@ -39,7 +39,7 @@ bool MouseNode::_exec(bool active) // 状态设为 MOUSEIN _setStatus(MOUSEIN); // 若此时按下鼠标左键 - if (MouseMsg::isOnLButtonDown()) + if (MouseMsg::getMsg() == MouseMsg::LBUTTON_DOWN) { m_bTarget = true; // 取得焦点标记 _setStatus(SELECTED); // 状态设为 SELECTED @@ -55,7 +55,7 @@ bool MouseNode::_exec(bool active) else { // 节点取得焦点时鼠标左键抬起 - if (MouseMsg::isOnLButtonUp()) + if (MouseMsg::getMsg() == MouseMsg::LBUTTON_UP) { // 若左键抬起时鼠标仍在节点内 if (_isMouseIn()) diff --git a/Easy2D/Tool/ActionManager.cpp b/Easy2D/Tool/ActionManager.cpp index bea8bfeb..7c2c015e 100644 --- a/Easy2D/Tool/ActionManager.cpp +++ b/Easy2D/Tool/ActionManager.cpp @@ -37,13 +37,24 @@ void ActionManager::addAction(Action * action) } } -void ActionManager::bindActionsWithScene(Scene * scene) +void ActionManager::startAllSceneActions(Scene * scene) { for (auto action : s_vActions) { - if (!action->m_pParentScene) + if (action->m_pParentScene == scene) { - action->m_pParentScene = App::getCurrentScene(); + action->start(); + } + } +} + +void ActionManager::pauseAllSceneActions(Scene * scene) +{ + for (auto action : s_vActions) + { + if (action->m_pParentScene == scene) + { + action->pause(); } } } diff --git a/Easy2D/Tool/Timer.cpp b/Easy2D/Tool/Timer.cpp index 3ba37411..f1d77df8 100644 --- a/Easy2D/Tool/Timer.cpp +++ b/Easy2D/Tool/Timer.cpp @@ -97,6 +97,7 @@ void Timer::addTimer(Timer * timer) { // 启动定时器 timer->start(); + // 绑定在场景上 timer->m_pParentScene = App::getCurrentScene(); // 将该定时器放入容器 s_vTimers.push_back(timer); @@ -110,67 +111,51 @@ void Timer::addTimer(TString name, UINT ms, const TIMER_CALLBACK & callback) addTimer(timer); } -Timer * Timer::getTimer(TString name) +void Timer::startTimer(TString name) { - // 查找是否有相同名称的定时器 + // 查找名称相同的定时器 for (auto timer : s_vTimers) { - if (timer->m_sName == name) + if (timer->m_sName == name && timer->m_pParentScene == App::getCurrentScene()) { - // 若找到,返回该定时器的指针 - return timer; + // 启动定时器 + timer->start(); } } - // 若未找到,返回空指针 - return nullptr; } -bool Timer::startTimer(TString name) +void Timer::stopTimer(TString name) { - // 启动指定名称的定时器,先找到该定时器 - auto t = getTimer(name); - if (t) + // 查找名称相同的定时器 + for (auto timer : s_vTimers) { - // 启动定时器 - t->start(); - return true; + if (timer->m_sName == name && timer->m_pParentScene == App::getCurrentScene()) + { + // 停止定时器 + timer->stop(); + } } - // 若未找到同样名称的定时器,返回 false - return false; } -bool Timer::stopTimer(TString name) -{ - // 停止指定名称的定时器,先找到该定时器 - auto t = getTimer(name); - if (t) - { - // 停止定时器 - t->stop(); - return true; - } - // 若未找到同样名称的定时器,返回 false - return false; -} - -bool Timer::delTimer(TString name) +void Timer::delTimer(TString name) { // 创建迭代器 std::vector::iterator iter; // 循环遍历所有定时器 - for (iter = s_vTimers.begin(); iter != s_vTimers.end(); iter++) + for (iter = s_vTimers.begin(); iter != s_vTimers.end();) { // 查找相同名称的定时器 - if ((*iter)->m_sName == name) + if ((*iter)->m_sName == name && (*iter)->m_pParentScene == App::getCurrentScene()) { // 删除该定时器 delete (*iter); - s_vTimers.erase(iter); - return true; + iter = s_vTimers.erase(iter); + } + else + { + iter++; } } - // 若未找到同样名称的定时器,返回 false - return false; } void Timer::clearAllTimers() @@ -184,13 +169,13 @@ void Timer::clearAllTimers() s_vTimers.clear(); } -void Timer::bindTimersWithScene(Scene * scene) +void Timer::startAllSceneTimers(Scene * scene) { for (auto t : s_vTimers) { - if (!t->m_pParentScene) + if (t->m_pParentScene == scene) { - t->m_pParentScene = App::getCurrentScene(); + t->start(); } } } @@ -205,3 +190,24 @@ void Timer::stopAllSceneTimers(Scene * scene) } } } + +void Timer::clearAllSceneTimers(Scene * scene) +{ + // 创建迭代器 + std::vector::iterator iter; + // 循环遍历所有定时器 + for (iter = s_vTimers.begin(); iter != s_vTimers.end();) + { + // 查找相同名称的定时器 + if ((*iter)->m_pParentScene == scene) + { + // 删除该定时器 + delete (*iter); + iter = s_vTimers.erase(iter); + } + else + { + iter++; + } + } +} diff --git a/Easy2D/easy2d.h b/Easy2D/easy2d.h index ea7a206b..4881df52 100644 --- a/Easy2D/easy2d.h +++ b/Easy2D/easy2d.h @@ -216,6 +216,8 @@ public: Scene(); ~Scene(); + // 重写这个函数,初始化这个场景 + virtual void init() = 0; // 重写这个函数,它将在进入这个场景时自动执行 virtual void onEnter(); // 重写这个函数,它将在离开这个场景时自动执行 @@ -277,16 +279,11 @@ public: WHEEL // 滑动滚轮 }; - // 添加键盘监听 - static void addListener(TString name, const MOUSE_CALLBACK& callback); - // 删除键盘监听 - static bool delListener(TString name); - // 删除所有键盘监听 - static void clearAllListeners(); - // 将未绑定的监听器绑定在场景上 - static void bindListenersWithScene(Scene* scene); - // 停止绑定在场景上的所有监听器 - static void clearAllSceneListeners(Scene* scene); + // 启动监听 + void start(); + // 停止监听 + void stop(); + // 左键是否按下 static bool isLButtonDown(); // 右键是否按下 @@ -304,10 +301,28 @@ public: // 获取当前鼠标消息 static MESSAGE getMsg(); + // 添加鼠标消息监听 + static void addListener(TString name, const MOUSE_CALLBACK& callback); + // 启动鼠标消息监听 + static void startListener(TString name); + // 停止鼠标消息监听 + static void stopListener(TString name); + // 删除鼠标消息监听 + static void delListener(TString name); + // 删除所有鼠标消息监听 + static void clearAllListeners(); + // 启动绑定在场景上的所有监听器 + static void startAllSceneListeners(Scene* scene); + // 停止绑定在场景上的所有监听器 + static void stopAllSceneListeners(Scene* scene); + // 清除绑定在场景上的所有监听器 + static void clearAllSceneListeners(Scene* scene); + private: static void __exec(); protected: + bool m_bRunning; TString m_sName; MOUSE_CALLBACK m_callback; Scene * m_pParentScene; @@ -326,19 +341,29 @@ public: // 执行回调函数 void onKbHit(VK_KEY key); + // 启动监听 + void start(); + // 停止监听 + void stop(); - // 添加键盘监听 - static void addListener(TString name, const KEY_CALLBACK& callback); - // 删除键盘监听 - static bool delListener(TString name); - // 删除所有键盘监听 - static void clearAllListeners(); - // 将未绑定的监听器绑定在场景上 - static void bindListenersWithScene(Scene* scene); - // 停止绑定在场景上的所有定时器 - static void clearAllSceneListeners(Scene* scene); // 判断键是否被按下,按下返回true static bool isKeyDown(VK_KEY key); + // 添加按键监听 + static void addListener(TString name, const KEY_CALLBACK& callback); + // 启动按键监听 + static void startListener(TString name); + // 停止按键监听 + static void stopListener(TString name); + // 删除按键监听 + static void KeyMsg::delListener(TString name); + // 启动绑定在场景上的所有监听器 + static void startAllSceneListeners(Scene* scene); + // 停止绑定在场景上的所有监听器 + static void stopAllSceneListeners(Scene* scene); + // 停止绑定在场景上的所有定时器 + static void clearAllSceneListeners(Scene* scene); + // 删除所有按键监听 + static void clearAllListeners(); public: // 字母键值 @@ -356,6 +381,7 @@ private: static void __exec(); protected: + bool m_bRunning; TString m_sName; KEY_CALLBACK m_callback; Scene * m_pParentScene; @@ -1421,21 +1447,21 @@ public: static void addTimer(Timer * timer); // 添加定时器 static void addTimer(TString name, UINT ms, const TIMER_CALLBACK & callback); - // 根据名称获取定时器 - static Timer * getTimer(TString name); // 启动特定定时器 - static bool startTimer(TString name); + static void startTimer(TString name); // 停止特定定时器 - static bool stopTimer(TString name); + static void stopTimer(TString name); // 删除特定定时器 - static bool delTimer(TString name); + static void delTimer(TString name); // 删除所有定时器 static void clearAllTimers(); - // 将未绑定的定时器绑定在场景上 - static void bindTimersWithScene(Scene* scene); + // 继续绑定在场景上的所有定时器 + static void startAllSceneTimers(Scene* scene); // 停止绑定在场景上的所有定时器 static void stopAllSceneTimers(Scene* scene); + // 清除绑定在场景上的所有定时器 + static void clearAllSceneTimers(Scene* scene); protected: bool m_bRunning; @@ -1484,8 +1510,10 @@ public: // 删除当前存在的所有动作 static void clearAllActions(); - // 将未绑定的动作绑定在场景上 - static void bindActionsWithScene(Scene* scene); + // 继续绑定在场景上的动作 + static void startAllSceneActions(Scene* scene); + // 暂停绑定在场景上的动作 + static void pauseAllSceneActions(Scene* scene); // 停止绑定在场景上的动作 static void stopAllSceneActions(Scene* scene);