重整了场景切换时的流程

This commit is contained in:
Nomango 2017-10-06 16:40:10 +08:00
parent 2fabef19dd
commit 64aa61a554
8 changed files with 322 additions and 155 deletions

View File

@ -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
{
SafeDelete(m_pCurrentScene); // 删除当前场景
// 不保存场景时,停止当前场景上运行的所有定时器,并删除当前场景
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
{
m_pCurrentScene->init(); // 进入一个新场景时,执行它的 init 函数
}
m_pCurrentScene->onEnter(); // 执行下一场景的 onEnter 函数
}
void App::quit()

View File

@ -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)

View File

@ -3,7 +3,7 @@
#include <conio.h>
// 按键监听回调函数的容器
static std::vector<KeyMsg*> s_vKeyMsg;
static std::vector<KeyMsg*> 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<KeyMsg*>::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<KeyMsg*>::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)

View File

@ -2,7 +2,7 @@
#include "..\EasyX\easyx.h"
// 鼠标监听回调函数的容器
static std::vector<MouseMsg*> s_vMouseMsg;
static std::vector<MouseMsg*> 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<MouseMsg*>::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()
{
if (!m->m_pParentScene)
m_bRunning = false;
}
void MouseMsg::clearAllListeners()
{
m->m_pParentScene = App::getCurrentScene();
// 删除所有监听器
for (auto l : s_vListeners)
{
delete l;
}
// 清空容器
s_vListeners.clear();
}
void MouseMsg::startAllSceneListeners(Scene * scene)
{
for (auto l : s_vListeners)
{
if (l->m_pParentScene == scene)
{
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<MouseMsg*>::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;

View File

@ -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())

View File

@ -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();
}
}
}

View File

@ -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)
{
// 若找到,返回该定时器的指针
return timer;
}
}
// 若未找到,返回空指针
return nullptr;
}
bool Timer::startTimer(TString name)
{
// 启动指定名称的定时器,先找到该定时器
auto t = getTimer(name);
if (t)
if (timer->m_sName == name && timer->m_pParentScene == App::getCurrentScene())
{
// 启动定时器
t->start();
return true;
timer->start();
}
}
// 若未找到同样名称的定时器,返回 false
return false;
}
bool Timer::stopTimer(TString name)
void Timer::stopTimer(TString name)
{
// 停止指定名称的定时器,先找到该定时器
auto t = getTimer(name);
if (t)
// 查找名称相同的定时器
for (auto timer : s_vTimers)
{
if (timer->m_sName == name && timer->m_pParentScene == App::getCurrentScene())
{
// 停止定时器
t->stop();
return true;
timer->stop();
}
}
// 若未找到同样名称的定时器,返回 false
return false;
}
bool Timer::delTimer(TString name)
void Timer::delTimer(TString name)
{
// 创建迭代器
std::vector<Timer*>::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<Timer*>::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++;
}
}
}

View File

@ -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);