修复了退出场景时仍执行定时器、监听器、动画的bug

This commit is contained in:
Nomango 2017-10-06 02:32:33 +08:00
parent e8659b96f4
commit 65494fb0e3
16 changed files with 205 additions and 58 deletions

View File

@ -4,7 +4,8 @@
Action::Action() :
m_bRunning(true),
m_bStop(false),
m_pParent(nullptr)
m_pTargetSprite(nullptr),
m_pParentScene(nullptr)
{
// 默认动作 15ms 运行一次
setInterval(15);

View File

@ -37,7 +37,7 @@ bool ActionFrames::_exec(LARGE_INTEGER nNow)
{
// 用求余的方法重新记录时间
m_nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % m_nAnimationInterval.QuadPart);
m_pParent->setImage(m_vFrames[m_nFrameIndex]);
m_pTargetSprite->setImage(m_vFrames[m_nFrameIndex]);
m_nFrameIndex++;
// 判断动作是否结束
if (m_nFrameIndex == m_vFrames.size())

View File

@ -13,7 +13,7 @@ ActionMoveBy::~ActionMoveBy()
void ActionMoveBy::_init()
{
Animation::_init();
m_BeginPos = m_pParent->getPos();
m_BeginPos = m_pTargetSprite->getPos();
}
bool ActionMoveBy::_exec(LARGE_INTEGER nNow)
@ -26,7 +26,7 @@ bool ActionMoveBy::_exec(LARGE_INTEGER nNow)
// 计算移动位置
float scale = float(m_nDuration) / m_nTotalDuration;
// 移动 Sprite
m_pParent->setPos(int(m_BeginPos.x + m_MoveVector.x * scale),
m_pTargetSprite->setPos(int(m_BeginPos.x + m_MoveVector.x * scale),
int(m_BeginPos.y + m_MoveVector.y * scale));
// 判断动作是否结束
if (_isEnd())

View File

@ -18,7 +18,7 @@ ActionNeverStop * ActionNeverStop::copy() const
void ActionNeverStop::_init()
{
m_Action->m_pParent = m_pParent;
m_Action->m_pTargetSprite = m_pTargetSprite;
m_Action->_init();
}

View File

@ -13,7 +13,7 @@ ActionOpacityBy::~ActionOpacityBy()
void ActionOpacityBy::_init()
{
Animation::_init();
m_nBeginVal = m_pParent->getOpacity();
m_nBeginVal = m_pTargetSprite->getOpacity();
}
bool ActionOpacityBy::_exec(LARGE_INTEGER nNow)
@ -26,7 +26,7 @@ bool ActionOpacityBy::_exec(LARGE_INTEGER nNow)
// 计算移动位置
float scale = float(m_nDuration) / m_nTotalDuration;
// 移动 Sprite
m_pParent->setOpacity(m_nBeginVal + m_nVariation * scale);
m_pTargetSprite->setOpacity(m_nBeginVal + m_nVariation * scale);
// 判断动作是否结束
if (_isEnd())
{

View File

@ -14,8 +14,8 @@ ActionScaleBy::~ActionScaleBy()
void ActionScaleBy::_init()
{
Animation::_init();
m_nBeginScaleX = m_pParent->getScaleX();
m_nBeginScaleY = m_pParent->getScaleY();
m_nBeginScaleX = m_pTargetSprite->getScaleX();
m_nBeginScaleY = m_pTargetSprite->getScaleY();
}
bool ActionScaleBy::_exec(LARGE_INTEGER nNow)
@ -28,7 +28,7 @@ bool ActionScaleBy::_exec(LARGE_INTEGER nNow)
// 计算移动位置
float scale = float(m_nDuration) / m_nTotalDuration;
// 移动 Sprite
m_pParent->setScale(m_nBeginScaleX + m_nVariationX * scale, m_nBeginScaleX + m_nVariationX * scale);
m_pTargetSprite->setScale(m_nBeginScaleX + m_nVariationX * scale, m_nBeginScaleX + m_nVariationX * scale);
// 判断动作是否结束
if (_isEnd())
{

View File

@ -33,7 +33,7 @@ void ActionSequence::_init()
{
for (auto action : m_vActions)
{
action->m_pParent = m_pParent;
action->m_pTargetSprite = m_pTargetSprite;
}
m_vActions[0]->_init();
}

View File

@ -34,8 +34,8 @@ ActionTwo * ActionTwo::reverse(bool actionReverse) const
void ActionTwo::_init()
{
m_FirstAction->m_pParent = m_pParent;
m_SecondAction->m_pParent = m_pParent;
m_FirstAction->m_pTargetSprite = m_pTargetSprite;
m_SecondAction->m_pTargetSprite = m_pTargetSprite;
m_FirstAction->_init();
}

View File

@ -14,8 +14,8 @@ static int originX = 0;
static int originY = 0;
App::App() :
m_CurrentScene(nullptr),
m_NextScene(nullptr),
m_pCurrentScene(nullptr),
m_pNextScene(nullptr),
m_bRunning(false),
m_nWindowMode(0)
{
@ -152,23 +152,23 @@ void App::_initGraph()
void App::_mainLoop()
{
// 下一场景指针不为空时,切换场景
if (m_NextScene)
if (m_pNextScene)
{
// 执行当前场景的 onExit 函数
if (m_CurrentScene)
if (m_pCurrentScene)
{
m_CurrentScene->onExit();
m_pCurrentScene->onExit();
}
// 进入下一场景
_enterNextScene();
// 执行当前场景的 onEnter 函数
m_CurrentScene->onEnter();
m_pCurrentScene->onEnter();
}
// 断言当前场景非空
assert(m_CurrentScene);
assert(m_pCurrentScene);
cleardevice(); // 清空画面
m_CurrentScene->_onDraw(); // 绘制当前场景
m_pCurrentScene->_onDraw(); // 绘制当前场景
FlushBatchDraw(); // 刷新画面
// 其他执行程序
@ -267,7 +267,7 @@ void App::close()
void App::enterScene(Scene * scene, bool save)
{
// 保存下一场景的指针
s_pInstance->m_NextScene = scene;
s_pInstance->m_pNextScene = scene;
// 切换场景时,是否保存当前场景
s_pInstance->m_bSaveScene = save;
}
@ -275,7 +275,7 @@ void App::enterScene(Scene * scene, bool save)
void App::backScene()
{
// 从栈顶取出场景指针,作为下一场景
s_pInstance->m_NextScene = s_pInstance->m_SceneStack.top();
s_pInstance->m_pNextScene = s_pInstance->m_SceneStack.top();
// 不保存当前场景
s_pInstance->m_bSaveScene = false;
}
@ -309,22 +309,22 @@ void App::setBkColor(COLORREF color)
void App::_enterNextScene()
{
// 若下一场景处于栈顶,说明正在返回上一场景
if (m_SceneStack.size() && m_NextScene == m_SceneStack.top())
if (m_SceneStack.size() && m_pNextScene == m_SceneStack.top())
{
m_SceneStack.pop(); // 删除栈顶场景
}
if (m_bSaveScene)
{
m_SceneStack.push(m_CurrentScene); // 若要保存当前场景,把它的指针放到栈顶
m_SceneStack.push(m_pCurrentScene); // 若要保存当前场景,把它的指针放到栈顶
}
else
{
SafeDelete(m_CurrentScene); // 删除当前场景
SafeDelete(m_pCurrentScene); // 删除当前场景
}
m_CurrentScene = m_NextScene; // 切换场景
m_NextScene = nullptr; // 下一场景置空
m_pCurrentScene = m_pNextScene; // 切换场景
m_pNextScene = nullptr; // 下一场景置空
}
void App::quit()
@ -348,7 +348,14 @@ void App::reset()
Scene * App::getCurrentScene()
{
// 获取当前场景的指针
return s_pInstance->m_CurrentScene;
if (s_pInstance->m_pCurrentScene)
{
return s_pInstance->m_pCurrentScene;
}
else
{
return s_pInstance->m_pNextScene;
}
}
void App::setFPS(DWORD fps)
@ -372,8 +379,8 @@ int App::getHeight()
void App::free()
{
// 释放场景内存
SafeDelete(m_CurrentScene);
SafeDelete(m_NextScene);
SafeDelete(m_pCurrentScene);
SafeDelete(m_pNextScene);
// 清空场景栈
while (m_SceneStack.size())
{

View File

@ -37,10 +37,20 @@ 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

@ -80,10 +80,11 @@ const VK_KEY KeyMsg::F12 = VK_F12;
static VK_KEY convert(int ascii);
KeyMsg::KeyMsg(TString name, const KEY_CALLBACK & callback)
KeyMsg::KeyMsg(TString name, const KEY_CALLBACK & callback) :
m_sName(name),
m_callback(callback),
m_pParentScene(nullptr)
{
m_sName = name;
m_callback = callback;
}
KeyMsg::~KeyMsg()
@ -112,6 +113,7 @@ void KeyMsg::addListener(TString name, const KEY_CALLBACK & callback)
{
// 创建新的监听对象
auto key = new KeyMsg(name, callback);
key->m_pParentScene = App::getCurrentScene();
// 添加新的按键回调函数
s_vKeyMsg.push_back(key);
}
@ -136,6 +138,34 @@ bool KeyMsg::delListener(TString name)
return false;
}
void KeyMsg::bindListenersWithScene(Scene * scene)
{
for (auto k : s_vKeyMsg)
{
if (!k->m_pParentScene)
{
k->m_pParentScene = App::getCurrentScene();
}
}
}
void KeyMsg::clearAllSceneListeners(Scene * scene)
{
// 创建迭代器
std::vector<KeyMsg*>::iterator iter;
// 循环遍历所有监听器
for (iter = s_vKeyMsg.begin(); iter != s_vKeyMsg.end(); iter++)
{
// 查找相同名称的监听器
if ((*iter)->m_pParentScene == scene)
{
// 删除该定时器
delete (*iter);
s_vKeyMsg.erase(iter);
}
}
}
void KeyMsg::clearAllListeners()
{
// 删除所有监听器

View File

@ -24,14 +24,17 @@ void MouseMsg::__exec()
}
}
MouseMsg::MouseMsg()
MouseMsg::MouseMsg() :
m_callback([]() {}),
m_pParentScene(nullptr)
{
}
MouseMsg::MouseMsg(TString name, const MOUSE_CALLBACK & callback)
MouseMsg::MouseMsg(TString name, const MOUSE_CALLBACK & callback) :
m_sName(name),
m_callback(callback),
m_pParentScene(nullptr)
{
m_sName = name;
m_callback = callback;
}
MouseMsg::~MouseMsg()
@ -47,6 +50,7 @@ void MouseMsg::addListener(TString name, const MOUSE_CALLBACK & callback)
{
// 创建新的监听对象
auto mouse = new MouseMsg(name, callback);
mouse->m_pParentScene = App::getCurrentScene();
// 添加新的按键回调函数
s_vMouseMsg.push_back(mouse);
}
@ -71,6 +75,34 @@ bool MouseMsg::delListener(TString name)
return false;
}
void MouseMsg::bindListenersWithScene(Scene * scene)
{
for (auto m : s_vMouseMsg)
{
if (!m->m_pParentScene)
{
m->m_pParentScene = App::getCurrentScene();
}
}
}
void MouseMsg::clearAllSceneListeners(Scene * scene)
{
// 创建迭代器
std::vector<MouseMsg*>::iterator iter;
// 循环遍历所有监听器
for (iter = s_vMouseMsg.begin(); iter != s_vMouseMsg.end(); iter++)
{
// 查找相同名称的监听器
if ((*iter)->m_pParentScene == scene)
{
// 删除该定时器
delete (*iter);
s_vMouseMsg.erase(iter);
}
}
}
void MouseMsg::clearAllListeners()
{
// 删除所有监听器

View File

@ -68,7 +68,7 @@ void Sprite::addAction(Action * action)
if (action)
{
// 将动作与 Sprite 绑定
action->m_pParent = this;
action->m_pTargetSprite = this;
// 将动作加入动作管理器,管理器会处理这个动作
ActionManager::addAction(action);
}

View File

@ -31,8 +31,31 @@ void ActionManager::addAction(Action * action)
assert(a != action);
}
#endif
s_vActions.push_back(action);
action->m_pParentScene = App::getCurrentScene();
action->_init();
s_vActions.push_back(action);
}
}
void ActionManager::bindActionsWithScene(Scene * scene)
{
for (auto action : s_vActions)
{
if (!action->m_pParentScene)
{
action->m_pParentScene = App::getCurrentScene();
}
}
}
void ActionManager::stopAllSceneActions(Scene * scene)
{
for (auto action : s_vActions)
{
if (action->m_pParentScene == scene)
{
action->stop();
}
}
}
@ -83,7 +106,7 @@ void ActionManager::resumeSpriteAllActions(Sprite * sprite)
{
for (auto action : s_vActions)
{
if (action->m_pParent == sprite)
if (action->m_pTargetSprite == sprite)
{
action->resume();
}
@ -94,7 +117,7 @@ void ActionManager::pauseSpriteAllActions(Sprite * sprite)
{
for (auto action : s_vActions)
{
if (action->m_pParent == sprite)
if (action->m_pTargetSprite == sprite)
{
action->pause();
}
@ -105,7 +128,7 @@ void ActionManager::stopSpriteAllActions(Sprite * sprite)
{
for (auto action : s_vActions)
{
if (action->m_pParent == sprite)
if (action->m_pTargetSprite == sprite)
{
action->stop();
}

View File

@ -1,12 +1,13 @@
#include "..\easy2d.h"
// 储存所有定时器的容器
static std::vector<Timer*> s_nTimers;
static std::vector<Timer*> s_vTimers;
Timer::Timer(TString name, UINT ms, const TIMER_CALLBACK & callback) :
m_sName(name),
m_bRunning(false),
m_callback(callback)
m_callback(callback),
m_pParentScene(nullptr)
{
setInterval(ms); // 设置定时器的时间间隔
}
@ -66,7 +67,7 @@ TString Timer::getName() const
void Timer::__exec()
{
// 定时器容器为空
if (!s_nTimers.size())
if (!s_vTimers.size())
{
return;
}
@ -74,7 +75,7 @@ void Timer::__exec()
static LARGE_INTEGER nNow;
QueryPerformanceCounter(&nNow);
// 循环遍历所有的定时器
for (auto timer : s_nTimers)
for (auto timer : s_vTimers)
{
// 若定时器未运行,跳过这个定时器
if (!timer->m_bRunning)
@ -96,8 +97,9 @@ void Timer::addTimer(Timer * timer)
{
// 启动定时器
timer->start();
timer->m_pParentScene = App::getCurrentScene();
// 将该定时器放入容器
s_nTimers.push_back(timer);
s_vTimers.push_back(timer);
}
void Timer::addTimer(TString name, UINT ms, const TIMER_CALLBACK & callback)
@ -111,7 +113,7 @@ void Timer::addTimer(TString name, UINT ms, const TIMER_CALLBACK & callback)
Timer * Timer::getTimer(TString name)
{
// 查找是否有相同名称的定时器
for (auto timer : s_nTimers)
for (auto timer : s_vTimers)
{
if (timer->m_sName == name)
{
@ -156,14 +158,14 @@ bool Timer::delTimer(TString name)
// 创建迭代器
std::vector<Timer*>::iterator iter;
// 循环遍历所有定时器
for (iter = s_nTimers.begin(); iter != s_nTimers.end(); iter++)
for (iter = s_vTimers.begin(); iter != s_vTimers.end(); iter++)
{
// 查找相同名称的定时器
if ((*iter)->m_sName == name)
{
// 删除该定时器
delete (*iter);
s_nTimers.erase(iter);
s_vTimers.erase(iter);
return true;
}
}
@ -174,10 +176,32 @@ bool Timer::delTimer(TString name)
void Timer::clearAllTimers()
{
// 删除所有定时器
for (auto t : s_nTimers)
for (auto t : s_vTimers)
{
delete t;
}
// 清空容器
s_nTimers.clear();
s_vTimers.clear();
}
void Timer::bindTimersWithScene(Scene * scene)
{
for (auto t : s_vTimers)
{
if (!t->m_pParentScene)
{
t->m_pParentScene = App::getCurrentScene();
}
}
}
void Timer::stopAllSceneTimers(Scene * scene)
{
for (auto t : s_vTimers)
{
if (t->m_pParentScene == scene)
{
t->stop();
}
}
}

View File

@ -182,8 +182,8 @@ public:
protected:
TString m_sTitle;
TString m_sAppName;
Scene* m_CurrentScene;
Scene* m_NextScene;
Scene* m_pCurrentScene;
Scene* m_pNextScene;
std::stack<Scene*> m_SceneStack;
LARGE_INTEGER m_nAnimationInterval;
CSize m_Size;
@ -271,6 +271,10 @@ public:
static bool delListener(TString name);
// 删除所有键盘监听
static void clearAllListeners();
// 将未绑定的监听器绑定在场景上
static void bindListenersWithScene(Scene* scene);
// 停止绑定在场景上的所有监听器
static void clearAllSceneListeners(Scene* scene);
// 左键是否按下
static bool isLButtonDown();
// 右键是否按下
@ -316,6 +320,7 @@ private:
protected:
TString m_sName;
MOUSE_CALLBACK m_callback;
Scene * m_pParentScene;
protected:
// 执行回调函数
@ -325,7 +330,6 @@ protected:
class KeyMsg
{
friend App;
public:
KeyMsg(TString name, const KEY_CALLBACK& callback);
~KeyMsg();
@ -339,6 +343,10 @@ public:
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);
@ -360,6 +368,7 @@ private:
protected:
TString m_sName;
KEY_CALLBACK m_callback;
Scene * m_pParentScene;
};
class FontStyle :
@ -1050,7 +1059,8 @@ public:
protected:
bool m_bRunning;
bool m_bStop;
Sprite * m_pParent;
Sprite * m_pTargetSprite;
Scene * m_pParentScene;
UINT m_nMilliSeconds;
LARGE_INTEGER m_nLast;
LARGE_INTEGER m_nAnimationInterval;
@ -1399,7 +1409,6 @@ public:
class Timer
{
friend App;
public:
Timer(TString name, UINT ms, const TIMER_CALLBACK & callback);
~Timer();
@ -1436,6 +1445,11 @@ public:
// 删除所有定时器
static void clearAllTimers();
// 将未绑定的定时器绑定在场景上
static void bindTimersWithScene(Scene* scene);
// 停止绑定在场景上的所有定时器
static void stopAllSceneTimers(Scene* scene);
protected:
bool m_bRunning;
TString m_sName;
@ -1443,6 +1457,7 @@ protected:
LARGE_INTEGER m_nLast;
LARGE_INTEGER m_nAnimationInterval;
UINT m_nMilliSeconds;
Scene * m_pParentScene;
private:
static void __exec();
@ -1482,6 +1497,11 @@ public:
// 删除当前存在的所有动作
static void clearAllActions();
// 将未绑定的动作绑定在场景上
static void bindActionsWithScene(Scene* scene);
// 停止绑定在场景上的动作
static void stopAllSceneActions(Scene* scene);
private:
static void __exec();
// 将一个动作添加进动作管理器