resorm class Transition

This commit is contained in:
Nomango 2018-04-17 01:11:56 +08:00
parent c135168491
commit 9ac4acb50e
11 changed files with 273 additions and 128 deletions

View File

@ -172,7 +172,7 @@ void e2d::Game::uninit()
s_bInitialized = false;
}
bool e2d::Game::createMutex(String sMutexName)
bool e2d::Game::createMutex(String sMutexName, String sWindowTitle)
{
// 创建进程互斥体
HANDLE m_hMutex = ::CreateMutex(NULL, TRUE, L"Easy2DApp-" + sMutexName);
@ -188,6 +188,22 @@ bool e2d::Game::createMutex(String sMutexName)
{
// 关闭进程互斥体
::CloseHandle(m_hMutex);
// 打开指定窗口
if (!sWindowTitle.isEmpty())
{
// 获取窗口句柄
HWND hProgramWnd = ::FindWindow(L"Easy2DApp", sWindowTitle);
if (hProgramWnd)
{
// 获取窗口显示状态
WINDOWPLACEMENT wpm;
::GetWindowPlacement(hProgramWnd, &wpm);
// 将运行的程序窗口还原成正常状态
wpm.showCmd = SW_SHOW;
::SetWindowPlacement(hProgramWnd, &wpm);
::SetWindowPos(hProgramWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
}
}
return false;
}
return true;

View File

@ -285,8 +285,8 @@ LRESULT e2d::Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标适当。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
auto pRenderTarget = Renderer::getRenderTarget();
if (pRenderTarget) pRenderTarget->Resize(D2D1::SizeU(width, height));
auto pRT = Renderer::getRenderTarget();
if (pRT) pRT->Resize(D2D1::SizeU(width, height));
}
break;

View File

@ -2,7 +2,7 @@
#include "..\ebase.h"
#include "..\etransition.h"
static e2d::Scene * s_pCurrentScene = nullptr;
static e2d::Scene * s_pCurrScene = nullptr;
static e2d::Scene * s_pNextScene = nullptr;
static e2d::Transition * s_pTransition = nullptr;
static std::stack<e2d::Scene*> s_SceneStack;
@ -18,24 +18,27 @@ void e2d::SceneManager::enter(Scene * scene, Transition * transition /* = nullpt
// 设置切换场景动画
if (transition)
{
if (s_pTransition)
{
s_pTransition->_stop();
s_pTransition->release();
}
s_pTransition = transition;
transition->retain();
transition->_setTarget(
s_pCurrentScene,
s_pNextScene
);
transition->_init(s_pCurrScene, s_pNextScene);
transition->_update();
}
if (s_pCurrentScene)
if (s_pCurrScene)
{
s_pCurrentScene->m_bWillSave = saveCurrentScene;
s_pCurrScene->m_bWillSave = saveCurrentScene;
}
}
void e2d::SceneManager::back(Transition * transition /* = nullptr */)
{
// 栈为空时,调用返回场景函数失败
WARN_IF(s_SceneStack.size() == 0, "Scene stack now is empty!");
WARN_IF(s_SceneStack.size() == 0, "Scene stack is empty!");
if (s_SceneStack.size() == 0) return;
// 从栈顶取出场景指针,作为下一场景
@ -43,9 +46,9 @@ void e2d::SceneManager::back(Transition * transition /* = nullptr */)
s_SceneStack.pop();
// 返回上一场景时,不保存当前场景
if (s_pCurrentScene)
if (s_pCurrScene)
{
s_pCurrentScene->m_bWillSave = false;
s_pCurrScene->m_bWillSave = false;
}
// 设置切换场景动画
@ -53,10 +56,8 @@ void e2d::SceneManager::back(Transition * transition /* = nullptr */)
{
s_pTransition = transition;
transition->retain();
transition->_setTarget(
s_pCurrentScene,
s_pNextScene
);
transition->_init(s_pCurrScene, s_pNextScene);
transition->_update();
}
}
@ -73,7 +74,7 @@ void e2d::SceneManager::clear()
e2d::Scene * e2d::SceneManager::getCurrentScene()
{
return s_pCurrentScene;
return s_pCurrScene;
}
std::stack<e2d::Scene*> e2d::SceneManager::getSceneStack()
@ -88,20 +89,16 @@ bool e2d::SceneManager::isTransitioning()
void e2d::SceneManager::__update()
{
// 更新场景内容
if (s_pCurrentScene)
{
s_pCurrentScene->_update();
}
// 正在切换场景时,执行场景切换动画
if (s_pTransition)
if (s_pTransition == nullptr)
{
// 更新场景内容
if (s_pNextScene)
if (s_pCurrScene)
{
s_pNextScene->_update();
s_pCurrScene->_update();
}
}
else
{
// 更新场景动画
s_pTransition->_update();
@ -120,37 +117,39 @@ void e2d::SceneManager::__update()
if (s_pNextScene)
{
// 执行当前场景的 onExit 函数
s_pCurrentScene->onExit();
s_pCurrScene->onExit();
// 若要保存当前场景,把它放入栈中
if (s_pCurrentScene->m_bWillSave)
if (s_pCurrScene->m_bWillSave)
{
s_SceneStack.push(s_pCurrentScene);
s_SceneStack.push(s_pCurrScene);
}
else
{
SafeRelease(&s_pCurrentScene);
SafeRelease(&s_pCurrScene);
}
// 执行下一场景的 onEnter 函数
s_pNextScene->onEnter();
s_pCurrentScene = s_pNextScene; // 切换场景
s_pCurrScene = s_pNextScene; // Çл»³¡¾°
s_pNextScene = nullptr; // 下一场景置空
}
}
void e2d::SceneManager::__render()
{
// 绘制当前场景
if (s_pCurrentScene)
if (s_pTransition)
{
s_pCurrentScene->_render();
s_pTransition->_render();
}
// 切换场景时,同时绘制两场景
if (s_pTransition && s_pNextScene)
else
{
s_pNextScene->_render();
// »æÖƵ±Ç°³¡¾°
if (s_pCurrScene)
{
s_pCurrScene->_render();
}
}
}
@ -159,8 +158,8 @@ bool e2d::SceneManager::__init()
// 若游戏初始化时场景不为空,进入该场景
if (s_pNextScene)
{
s_pCurrentScene = s_pNextScene;
s_pCurrentScene->onEnter();
s_pCurrScene = s_pNextScene;
s_pCurrScene->onEnter();
s_pNextScene = nullptr;
}
@ -172,7 +171,7 @@ bool e2d::SceneManager::__init()
void e2d::SceneManager::__uninit()
{
SafeRelease(&s_pCurrentScene);
SafeRelease(&s_pCurrScene);
SafeRelease(&s_pNextScene);
SafeRelease(&s_pTransition);
SceneManager::clear();

View File

@ -32,6 +32,7 @@ e2d::Timer* e2d::TimerManager::start(double timeOut, Function func)
{
auto t = new (std::nothrow) Timer(L"", func, timeOut, 1, false, true);
t->start();
TimerManager::add(t);
return t;
}

View File

@ -7,26 +7,104 @@ e2d::Transition::Transition(double duration)
, m_fRateOfProgress(0)
, m_pPrevScene(nullptr)
, m_pNextScene(nullptr)
, m_pPrevLayer(nullptr)
, m_pNextLayer(nullptr)
, m_sPrevLayerParam()
, m_sNextLayerParam()
{
m_fDuration = max(duration, 0);
}
e2d::Transition::~Transition()
{
SafeRelease(&m_pPrevScene);
SafeRelease(&m_pNextScene);
SafeReleaseInterface(&m_pPrevLayer);
SafeReleaseInterface(&m_pNextLayer);
}
bool e2d::Transition::isEnding()
{
return m_bEnd;
}
void e2d::Transition::_calcRateOfProgress()
void e2d::Transition::_init(Scene * prev, Scene * next)
{
// 判断时间间隔是否足够
// 创建图层
HRESULT hr = Renderer::getRenderTarget()->CreateLayer(&m_pNextLayer);
if (SUCCEEDED(hr))
{
hr = Renderer::getRenderTarget()->CreateLayer(&m_pPrevLayer);
}
if (FAILED(hr))
{
ASSERT(false, L"Create layer failed!");
}
m_fLast = Time::getTotalTime();
m_pPrevScene = prev;
m_pNextScene = next;
if (m_pPrevScene) m_pPrevScene->retain();
if (m_pNextScene) m_pNextScene->retain();
auto size = Window::getSize();
m_sPrevLayerParam = m_sNextLayerParam = D2D1::LayerParameters(
D2D1::RectF(0, 0, float(size.width), float(size.height))
);
}
void e2d::Transition::_update()
{
// 计算动画进度
if (m_fDuration == 0)
{
m_fRateOfProgress = 1;
return;
}
else
{
m_fRateOfProgress = min((Time::getTotalTime() - m_fLast) / m_fDuration, 1);
}
// 计算动画进度
m_fRateOfProgress = min((Time::getTotalTime() - m_fLast) / m_fDuration, 1);
this->_updateCustom();
// 更新场景内容
if (m_pPrevScene)
{
m_pPrevScene->_update();
}
if (m_pNextScene)
{
m_pNextScene->_update();
}
}
void e2d::Transition::_render()
{
auto pRT = Renderer::getRenderTarget();
if (m_pPrevScene)
{
pRT->SetTransform(D2D1::Matrix3x2F::Identity());
pRT->PushLayer(m_sPrevLayerParam, m_pPrevLayer);
// 渲染场景
m_pPrevScene->_render();
pRT->PopLayer();
}
if (m_pNextScene)
{
pRT->SetTransform(D2D1::Matrix3x2F::Identity());
pRT->PushLayer(m_sNextLayerParam, m_pNextLayer);
// 渲染场景
m_pNextScene->_render();
pRT->PopLayer();
}
}
void e2d::Transition::_stop()
@ -34,11 +112,3 @@ void e2d::Transition::_stop()
m_bEnd = true;
_reset();
}
void e2d::Transition::_setTarget(Scene * prev, Scene * next)
{
m_fLast = Time::getTotalTime();
m_pPrevScene = prev;
m_pNextScene = next;
_init();
}

View File

@ -6,12 +6,10 @@ e2d::TransitionEmerge::TransitionEmerge(double duration)
{
}
void e2d::TransitionEmerge::_update()
void e2d::TransitionEmerge::_updateCustom()
{
this->_calcRateOfProgress();
if (m_pPrevScene) m_pPrevScene->getRoot()->setOpacity(1 - m_fRateOfProgress);
m_pNextScene->getRoot()->setOpacity(m_fRateOfProgress);
m_sPrevLayerParam.opacity = float(1 - m_fRateOfProgress);
m_sNextLayerParam.opacity = float(m_fRateOfProgress);
if (m_fRateOfProgress >= 1)
{
@ -19,14 +17,13 @@ void e2d::TransitionEmerge::_update()
}
}
void e2d::TransitionEmerge::_init()
void e2d::TransitionEmerge::_init(Scene * prev, Scene * next)
{
if (m_pPrevScene) m_pPrevScene->getRoot()->setOpacity(1);
m_pNextScene->getRoot()->setOpacity(0);
Transition::_init(prev, next);
m_sPrevLayerParam.opacity = 1;
m_sNextLayerParam.opacity = 0;
}
void e2d::TransitionEmerge::_reset()
{
if (m_pPrevScene) m_pPrevScene->getRoot()->setOpacity(1);
m_pNextScene->getRoot()->setOpacity(1);
}

View File

@ -1,32 +1,37 @@
#include "..\etransition.h"
#include "..\enode.h"
e2d::TransitionFade::TransitionFade(double fadeOutDuration, double fadeInDuration)
e2d::TransitionFade::TransitionFade(double duration)
: Transition(0)
, m_fFadeOutDuration(fadeOutDuration)
, m_fFadeInDuration(fadeInDuration)
, m_fFadeOutDuration(max(duration / 2, 0))
, m_fFadeInDuration(max(duration / 2, 0))
, m_bFadeOutTransioning(true)
{
m_fDuration = max(m_fFadeOutDuration, 0);
}
void e2d::TransitionFade::_update()
e2d::TransitionFade::TransitionFade(double fadeOutDuration, double fadeInDuration)
: Transition(0)
, m_fFadeOutDuration(max(fadeOutDuration, 0))
, m_fFadeInDuration(max(fadeInDuration, 0))
, m_bFadeOutTransioning(true)
{
this->_calcRateOfProgress();
}
void e2d::TransitionFade::_updateCustom()
{
if (m_bFadeOutTransioning)
{
m_pPrevScene->getRoot()->setOpacity(1 - m_fRateOfProgress);
m_sPrevLayerParam.opacity = float(1 - m_fRateOfProgress);
if (m_fRateOfProgress >= 1)
{
m_bFadeOutTransioning = false;
m_fDuration = max(m_fFadeInDuration, 0);
m_fDuration = m_fFadeInDuration;
m_fLast = Time::getTotalTime();
}
}
else
{
m_pNextScene->getRoot()->setOpacity(m_fRateOfProgress);
m_sNextLayerParam.opacity = float(m_fRateOfProgress);
if (m_fRateOfProgress >= 1)
{
this->_stop();
@ -34,23 +39,23 @@ void e2d::TransitionFade::_update()
}
}
void e2d::TransitionFade::_init()
void e2d::TransitionFade::_init(Scene * prev, Scene * next)
{
Transition::_init(prev, next);
if (m_pPrevScene)
{
m_bFadeOutTransioning = true;
m_pPrevScene->getRoot()->setOpacity(1);
m_fDuration = m_fFadeOutDuration;
}
else
{
m_bFadeOutTransioning = false;
m_fDuration = m_fFadeInDuration;
}
m_pNextScene->getRoot()->setOpacity(0);
m_sPrevLayerParam.opacity = 1;
m_sNextLayerParam.opacity = 0;
}
void e2d::TransitionFade::_reset()
{
if (m_pPrevScene) m_pPrevScene->getRoot()->setOpacity(1);
m_pNextScene->getRoot()->setOpacity(1);
}

View File

@ -1,18 +1,40 @@
#include "..\etransition.h"
#include "..\enode.h"
e2d::TransitionMove::TransitionMove(double duration, MOVE_DIRECT direct)
e2d::TransitionMove::TransitionMove(double duration, int direct)
: Transition(duration)
, m_Direct(direct)
{
}
void e2d::TransitionMove::_update()
void e2d::TransitionMove::_updateCustom()
{
this->_calcRateOfProgress();
if (m_pPrevScene)
{
auto root = m_pPrevScene->getRoot();
root->setPos(m_Vector * m_fRateOfProgress);
if (m_pPrevScene) m_pPrevScene->getRoot()->setPos(m_Vec * m_fRateOfProgress);
m_pNextScene->getRoot()->setPos(m_NextPos + m_Vec * m_fRateOfProgress);
Point pos = root->getPos();
m_sPrevLayerParam.contentBounds = D2D1::RectF(
float(max(pos.x, 0)),
float(max(pos.y, 0)),
float(min(pos.x + m_WindowSize.width, m_WindowSize.width)),
float(min(pos.y + m_WindowSize.height, m_WindowSize.height))
);
}
if (m_pNextScene)
{
auto root = m_pNextScene->getRoot();
root->setPos(m_NextPos + m_Vector * m_fRateOfProgress);
Point pos = root->getPos();
m_sNextLayerParam.contentBounds = D2D1::RectF(
float(max(pos.x, 0)),
float(max(pos.y, 0)),
float(min(pos.x + m_WindowSize.width, m_WindowSize.width)),
float(min(pos.y + m_WindowSize.height, m_WindowSize.height))
);
}
if (m_fRateOfProgress >= 1)
{
@ -20,27 +42,32 @@ void e2d::TransitionMove::_update()
}
}
void e2d::TransitionMove::_init()
void e2d::TransitionMove::_init(Scene * prev, Scene * next)
{
if (m_Direct == TransitionMove::UP)
Transition::_init(prev, next);
m_WindowSize = Window::getSize();
double width = m_WindowSize.width;
double height = m_WindowSize.height;
if (m_Direct == Direct::UP)
{
m_Vec = Vector(0, -Window::getHeight());
m_NextPos = Point(0, Window::getHeight());
m_Vector = Vector(0, -height);
m_NextPos = Point(0, height);
}
else if (m_Direct == TransitionMove::DOWN)
else if (m_Direct == Direct::DOWN)
{
m_Vec = Vector(0, Window::getHeight());
m_NextPos = Point(0, -Window::getHeight());
m_Vector = Vector(0, height);
m_NextPos = Point(0, -height);
}
else if (m_Direct == TransitionMove::LEFT)
else if (m_Direct == Direct::LEFT)
{
m_Vec = Vector(-Window::getWidth(), 0);
m_NextPos = Point(Window::getWidth(), 0);
m_Vector = Vector(-width, 0);
m_NextPos = Point(width, 0);
}
else if (m_Direct == TransitionMove::RIGHT)
else if (m_Direct == Direct::RIGHT)
{
m_Vec = Vector(Window::getWidth(), 0);
m_NextPos = Point(-Window::getWidth(), 0);
m_Vector = Vector(width, 0);
m_NextPos = Point(-width, 0);
}
if (m_pPrevScene) m_pPrevScene->getRoot()->setPos(0, 0);

View File

@ -37,7 +37,8 @@ public:
// ´´½¨½ø³Ì»¥³âÌå
static bool createMutex(
String sMutexName /* »¥³âÌåÃû³Æ */
String sMutexName, /* »¥³âÌåÃû³Æ */
String sWindowTitle = L"" /* ´°¿Ú±êÌâ */
);
// »ñÈ¡ÓÎÏ·Ãû³Æ

View File

@ -381,6 +381,20 @@ public:
};
// 方向
class Direct
{
public:
enum : int
{
UP, /* 上 */
DOWN, /* 下 */
LEFT, /* 左 */
RIGHT /* 右 */
};
};
// 碰撞体交集关系
class Relation
{
@ -561,12 +575,14 @@ protected:
class Node;
class SceneManager;
class Transition;
// 场景
class Scene :
public Object
{
friend SceneManager;
friend Transition;
public:
Scene();

View File

@ -15,15 +15,26 @@ class Transition :
public:
Transition(double duration);
virtual ~Transition();
// 场景切换动画是否结束
bool isEnding();
protected:
// 更新场景动画
virtual void _update() = 0;
// 初始化场景动画
virtual void _init() = 0;
virtual void _init(
Scene * prev,
Scene * next
);
// 更新场景动画
virtual void _update();
// 更新场景动画
virtual void _updateCustom() = 0;
// 渲染场景动画
virtual void _render();
// 重置场景动画
virtual void _reset() = 0;
@ -31,15 +42,6 @@ protected:
// 停止场景动画
virtual void _stop();
// 计算场景动画进度
void _calcRateOfProgress();
// 保存当前场景和下一场景的指针
void _setTarget(
Scene * prev,
Scene * next
);
protected:
bool m_bEnd;
double m_fLast;
@ -47,6 +49,10 @@ protected:
double m_fRateOfProgress;
Scene * m_pPrevScene;
Scene * m_pNextScene;
ID2D1Layer * m_pPrevLayer;
ID2D1Layer * m_pNextLayer;
D2D1_LAYER_PARAMETERS m_sPrevLayerParam;
D2D1_LAYER_PARAMETERS m_sNextLayerParam;
};
@ -54,6 +60,11 @@ class TransitionFade :
public Transition
{
public:
// 创建淡入淡出式的场景切换动画
TransitionFade(
double duration /* 动画持续时长 */
);
// 创建淡入淡出式的场景切换动画
TransitionFade(
double fadeOutDuration, /* 前一场景淡出动画持续时长 */
@ -62,9 +73,12 @@ public:
protected:
// 更新动画
virtual void _update() override;
virtual void _updateCustom() override;
virtual void _init() override;
virtual void _init(
Scene * prev,
Scene * next
) override;
virtual void _reset() override;
@ -86,9 +100,12 @@ public:
protected:
// 更新动画
virtual void _update() override;
virtual void _updateCustom() override;
virtual void _init() override;
virtual void _init(
Scene * prev,
Scene * next
) override;
virtual void _reset() override;
};
@ -98,32 +115,28 @@ class TransitionMove :
public Transition
{
public:
enum MOVE_DIRECT
{
UP,
DOWN,
LEFT,
RIGHT
};
// 创建移动式的场景切换动画
TransitionMove(
double moveDuration, /* 场景移动动画持续时长 */
MOVE_DIRECT direct = LEFT /* 场景移动方向 */
int direct = Direct::LEFT /* 场景移动方向 */
);
protected:
// 更新动画
virtual void _update() override;
virtual void _updateCustom() override;
virtual void _init() override;
virtual void _init(
Scene * prev,
Scene * next
) override;
virtual void _reset() override;
protected:
MOVE_DIRECT m_Direct;
Vector m_Vec;
int m_Direct;
Vector m_Vector;
Point m_NextPos;
Size m_WindowSize;
};
}