计时功能优化

This commit is contained in:
Nomango 2018-08-02 00:27:45 +08:00
parent d1ad592df7
commit c7115a1162
22 changed files with 297 additions and 341 deletions

View File

@ -6,7 +6,6 @@ e2d::Action::Action()
, _done(false)
, _initialized(false)
, _target(nullptr)
, _last(0)
{
ActionManager::getInstance()->__add(this);
}
@ -24,7 +23,6 @@ bool e2d::Action::isRunning()
void e2d::Action::resume()
{
_running = true;
_last = Game::getInstance()->getTotalDuration().seconds();
}
void e2d::Action::pause()
@ -56,7 +54,7 @@ void e2d::Action::reset()
{
_initialized = false;
_done = false;
_last = Game::getInstance()->getTotalDuration().seconds();
_started = Time::now();
}
bool e2d::Action::_isDone()
@ -74,7 +72,7 @@ void e2d::Action::_startWithTarget(Node* target)
void e2d::Action::_init()
{
_initialized = true;
_last = Game::getInstance()->getTotalDuration().seconds();
_started = Time::now();
}
void e2d::Action::_update()

View File

@ -56,8 +56,7 @@ void e2d::Animate::_update()
return;
}
auto game = Game::getInstance();
while ((game->getTotalDuration().seconds() - _last) >= _animation->getInterval())
while ((Time::now() - _started).seconds() >= _animation->getInterval())
{
auto& frames = _animation->getFrames();
auto target = dynamic_cast<Sprite*>(_target);
@ -67,7 +66,7 @@ void e2d::Animate::_update()
target->open(frames[_frameIndex]);
}
_last += _animation->getInterval();
_started += Duration(_animation->getInterval());
++_frameIndex;
if (_frameIndex == frames.size())
@ -81,7 +80,6 @@ void e2d::Animate::_update()
void e2d::Animate::_resetTime()
{
Action::_resetTime();
_last = Game::getInstance()->getTotalDuration().seconds();
}
void e2d::Animate::reset()

View File

@ -31,7 +31,7 @@ void e2d::Delay::_update()
{
Action::_update();
_delta = Game::getInstance()->getTotalDuration().seconds() - _last;
_delta = (Time::now() - _started).seconds();
if (_delta >= _delay)
{
@ -42,5 +42,5 @@ void e2d::Delay::_update()
void e2d::Delay::_resetTime()
{
Action::_resetTime();
_last = Game::getInstance()->getTotalDuration().seconds() - _delta;
_started = Time::now() - Duration(_delta);
}

View File

@ -28,7 +28,7 @@ void e2d::FiniteTimeAction::_update()
}
else
{
_delta = std::min((Game::getInstance()->getTotalDuration().seconds() - _last) / _duration, 1.f);
_delta = std::min((Time::now() - _started).seconds() / _duration, 1.f);
if (_delta >= 1)
{
@ -40,5 +40,5 @@ void e2d::FiniteTimeAction::_update()
void e2d::FiniteTimeAction::_resetTime()
{
Action::_resetTime();
_last = Game::getInstance()->getTotalDuration().seconds() - _delta * _duration;
_started = Time::now() - Duration(_delta * _duration);
}

View File

@ -12,8 +12,6 @@ e2d::Game::Game()
, _config()
{
CoInitialize(nullptr);
_start = _last = _now = Time::now();
}
e2d::Game::~Game()
@ -39,26 +37,25 @@ void e2d::Game::destroyInstance()
void e2d::Game::start()
{
SceneManager::getInstance()->update();
_quit = false;
const int minInterval = 5;
Time last = Time::now();
HWND hWnd = Window::getInstance()->getHWnd();
::ShowWindow(hWnd, SW_SHOWNORMAL);
::UpdateWindow(hWnd);
Window::getInstance()->poll();
_quit = false;
_last = _now = Time::now();
const Duration minInterval(15);
SceneManager::getInstance()->update();
while (!_quit)
{
_now = Time::now();
Duration interval = _now - _last;
auto now = Time::now();
auto dur = now - last;
if (minInterval < interval)
if (dur.milliseconds() > minInterval)
{
_last = _now;
last = now;
Input::getInstance()->update();
Timer::getInstance()->update();
ActionManager::getInstance()->update();
@ -72,7 +69,7 @@ void e2d::Game::start()
// ID2D1HwndRenderTarget 在渲染时会等待显示器刷新,即开启了垂直同步,
// 它起到了非常稳定的延时作用,所以大部分时候不需要手动挂起线程进行延时。
// 下面的代码仅在一些情况下(例如窗口最小化时)挂起线程,防止占用过高 CPU 。
int wait = (minInterval - interval).milliseconds();
int wait = minInterval - dur.milliseconds();
if (wait > 1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(wait));
@ -90,7 +87,6 @@ void e2d::Game::resume()
{
if (_paused && !_quit)
{
_last = _now = Time::now();
Timer::getInstance()->updateTime();
ActionManager::getInstance()->updateTime();
}
@ -120,11 +116,6 @@ const e2d::Config& e2d::Game::getConfig()
return _config;
}
e2d::Duration e2d::Game::getTotalDuration() const
{
return std::move(_now - _start);
}
void e2d::Game::quit()
{
_quit = true;

View File

@ -107,15 +107,14 @@ void e2d::Renderer::render()
void e2d::Renderer::_renderFps()
{
++_renderTimes;
int duration = (Time::now() - _lastRenderTime).milliseconds();
auto& now = Time::now();
int duration = (now - _lastRenderTime).milliseconds();
++_renderTimes;
if (duration >= 100)
{
String fpsText = String::format(L"FPS: %.1f", (1000.f / duration * _renderTimes));
_renderTimes = 0;
_lastRenderTime = now;
String fpsText = String::format(L"FPS: %.1f", (1000.f / duration * _renderTimes));
_lastRenderTime = Time::now();
_renderTimes = 0;
auto writeFactory = Renderer::getWriteFactory();
if (!_fpsFormat)

View File

@ -3,6 +3,9 @@
#include <imm.h>
#pragma comment (lib ,"imm32.lib")
#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME
#define REGISTER_CLASS L"Easy2DApp"
e2d::Window * e2d::Window::_instance = nullptr;
@ -51,9 +54,7 @@ bool e2d::Window::createMutex(const String & mutex)
if (mutex.isEmpty())
return false;
// 创建进程互斥体
String fullMutexName = L"Easy2DApp-" + mutex;
HANDLE hMutex = ::CreateMutex(nullptr, TRUE, (LPCWSTR)fullMutexName);
HANDLE hMutex = ::CreateMutex(nullptr, TRUE, LPCWSTR(L"Easy2DApp-" + mutex));
if (hMutex == nullptr)
{
@ -68,7 +69,7 @@ bool e2d::Window::createMutex(const String & mutex)
if (!this->_title.isEmpty())
{
// 获取窗口句柄
HWND hProgramWnd = ::FindWindow(L"Easy2DApp", (LPCTSTR)this->_title);
HWND hProgramWnd = ::FindWindow(REGISTER_CLASS, (LPCTSTR)_title);
if (hProgramWnd)
{
// 获取窗口显示状态
@ -85,79 +86,59 @@ bool e2d::Window::createMutex(const String & mutex)
return true;
}
HWND e2d::Window::__create()
HWND e2d::Window::__registerWindow()
{
// 注册窗口类
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = L"Easy2DApp";
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = Window::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = nullptr;
wcex.lpszMenuName = nullptr;
wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = REGISTER_CLASS;
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = Window::WndProc;
wcex.hIcon = nullptr;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = nullptr;
wcex.lpszMenuName = nullptr;
wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
if (this->_iconID != 0)
if (_iconID != 0)
{
wcex.hIcon = (HICON)::LoadImage(
HINST_THISCOMPONENT,
MAKEINTRESOURCE(this->_iconID),
MAKEINTRESOURCE(_iconID),
IMAGE_ICON,
0,
0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
);
}
else
{
wcex.hIcon = nullptr;
}
// 注册窗口类
RegisterClassEx(&wcex);
// 因为 CreateWindow 函数使用的是像素大小,获取系统的 DPI 以使它
// 适应窗口缩放
float dpiScaleX = 0.f, dpiScaleY = 0.f;
Renderer::getFactory()->GetDesktopDpi(&dpiScaleX, &dpiScaleY);
int nWidth = static_cast<int>(ceil(_size.width * dpiScaleX / 96.f));
int nHeight = static_cast<int>(ceil(_size.height * dpiScaleY / 96.f));
// 计算窗口大小
DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME;
RECT wr = { 0, 0, static_cast<LONG>(nWidth), static_cast<LONG>(nHeight) };
::AdjustWindowRectEx(&wr, dwStyle, FALSE, NULL);
// 获取新的宽高
nWidth = static_cast<int>(wr.right - wr.left);
nHeight = static_cast<int>(wr.bottom - wr.top);
// 获取屏幕分辨率
int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
Rect wRect = __adjustWindow(int(_size.width), int(_size.height));
// 创建窗口
HWND hWnd = ::CreateWindowEx(
NULL,
L"Easy2DApp",
REGISTER_CLASS,
(LPCTSTR)_title,
dwStyle,
(screenWidth - nWidth) / 2, (screenHeight - nHeight) / 2,
nWidth, nHeight,
WINDOW_STYLE,
int(wRect.origin.x),
int(wRect.origin.y),
int(wRect.size.width),
int(wRect.size.height),
nullptr,
nullptr,
HINST_THISCOMPONENT,
nullptr
);
HRESULT hr = hWnd ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
if (hWnd)
{
// 禁用输入法
this->setTypewritingEnabled(false);
setTypewritingEnabled(false);
// 禁用控制台关闭按钮
HWND consoleHWnd = ::GetConsoleWindow();
if (consoleHWnd)
@ -170,11 +151,35 @@ HWND e2d::Window::__create()
}
else
{
::UnregisterClass(L"Easy2DApp", HINST_THISCOMPONENT);
::UnregisterClass(REGISTER_CLASS, HINST_THISCOMPONENT);
}
return hWnd;
}
e2d::Rect e2d::Window::__adjustWindow(int width, int height)
{
float dpiScaleX = 0.f, dpiScaleY = 0.f;
Renderer::getFactory()->GetDesktopDpi(&dpiScaleX, &dpiScaleY);
Rect result;
RECT wRECT = { 0, 0, LONG(ceil(width * dpiScaleX / 96.f)), LONG(ceil(height * dpiScaleY / 96.f)) };
int maxWidth = ::GetSystemMetrics(SM_CXSCREEN);
int maxHeight = ::GetSystemMetrics(SM_CYSCREEN);
// 计算合适的窗口大小
::AdjustWindowRectEx(&wRECT, WINDOW_STYLE, FALSE, NULL);
width = static_cast<int>(wRECT.right - wRECT.left);
height = static_cast<int>(wRECT.bottom - wRECT.top);
// 当输入的窗口大小比分辨率大时,给出警告
WARN_IF(maxWidth < width || maxHeight < height, "The window is larger than screen!");
width = std::min(width, maxWidth);
height = std::min(height, maxHeight);
float x = float((maxWidth - width) / 2), y = float((maxHeight - height) / 2);
return std::move(Rect(x, y, float(width), float(height)));
}
void e2d::Window::poll()
{
while (::PeekMessage(&_msg, nullptr, 0, 0, PM_REMOVE))
@ -213,7 +218,7 @@ HWND e2d::Window::getHWnd()
{
if (!_hWnd)
{
_hWnd = this->__create();
_hWnd = __registerWindow();
if (_hWnd == nullptr)
{
throw SystemException(L"注册窗口失败");
@ -224,37 +229,24 @@ HWND e2d::Window::getHWnd()
void e2d::Window::setSize(int width, int height)
{
this->_size = Size(static_cast<float>(width), static_cast<float>(height));
_size = Size(static_cast<float>(width), static_cast<float>(height));
if (_hWnd)
{
float dpiScaleX = 0.f, dpiScaleY = 0.f;
Renderer::getFactory()->GetDesktopDpi(&dpiScaleX, &dpiScaleY);
width = static_cast<int>(ceil(width * dpiScaleX / 96.f));
height = static_cast<int>(ceil(height * dpiScaleY / 96.f));
// 计算窗口大小
DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME;
RECT wr = { 0, 0, static_cast<LONG>(width), static_cast<LONG>(height) };
::AdjustWindowRectEx(&wr, dwStyle, FALSE, NULL);
// 获取新的宽高
width = static_cast<int>(wr.right - wr.left);
height = static_cast<int>(wr.bottom - wr.top);
// 获取屏幕分辨率
int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
// 当输入的窗口大小比分辨率大时,给出警告
WARN_IF(screenWidth < width || screenHeight < height, "The window is larger than screen!");
// 取最小值
width = std::min(width, screenWidth);
height = std::min(height, screenHeight);
// 修改窗口大小,并设置窗口在屏幕居中
::MoveWindow(_hWnd, (screenWidth - width) / 2, (screenHeight - height) / 2, width, height, TRUE);
Rect wRect = __adjustWindow(width, height);
::MoveWindow(
_hWnd,
int(wRect.origin.x),
int(wRect.origin.y),
int(wRect.size.width),
int(wRect.size.height),
TRUE
);
}
}
void e2d::Window::setTitle(const String& title)
{
this->_title = title;
_title = title;
if (_hWnd)
{
::SetWindowText(_hWnd, (LPCWSTR)title);

View File

@ -7,13 +7,8 @@ e2d::Duration::Duration()
{
}
e2d::Duration::Duration(int ms)
: _ms(ms)
{
}
e2d::Duration::Duration(const std::chrono::milliseconds& ms)
: _ms(ms)
e2d::Duration::Duration(float seconds)
: _ms(static_cast<long long>(seconds * 1000.f))
{
}
@ -59,12 +54,16 @@ bool e2d::Duration::operator<=(const Duration & other) const
e2d::Duration e2d::Duration::operator+(Duration const & other) const
{
return std::move(Duration(_ms + other._ms));
Duration d;
d._ms = _ms + other._ms;
return std::move(d);
}
e2d::Duration e2d::Duration::operator-(Duration const & other) const
{
return std::move(Duration(_ms - other._ms));
Duration d;
d._ms = _ms - other._ms;
return std::move(d);
}
e2d::Duration & e2d::Duration::operator+=(Duration const &other)

View File

@ -7,11 +7,6 @@ e2d::Time::Time()
{
}
e2d::Time::Time(const steady_clock::time_point& time)
: _timePoint(time)
{
}
time_t e2d::Time::getTimeStamp() const
{
auto& duration = time_point_cast<milliseconds>(_timePoint).time_since_epoch();
@ -25,7 +20,16 @@ bool e2d::Time::isZero() const
e2d::Time e2d::Time::operator+(Duration const & other) const
{
return std::move(Time(_timePoint + milliseconds(other.milliseconds())));
Time t;
t._timePoint = _timePoint + milliseconds(other.milliseconds());
return std::move(t);
}
e2d::Time e2d::Time::operator-(Duration const & other) const
{
Time t;
t._timePoint = _timePoint - milliseconds(other.milliseconds());
return std::move(t);
}
e2d::Time & e2d::Time::operator+=(Duration const & other)
@ -34,11 +38,6 @@ e2d::Time & e2d::Time::operator+=(Duration const & other)
return (*this);
}
e2d::Time e2d::Time::operator-(Duration const & other) const
{
return std::move(Time(_timePoint - milliseconds(other.milliseconds())));
}
e2d::Time & e2d::Time::operator-=(Duration const &other)
{
_timePoint -= milliseconds(other.milliseconds());
@ -47,11 +46,13 @@ e2d::Time & e2d::Time::operator-=(Duration const &other)
e2d::Duration e2d::Time::operator-(Time const & other) const
{
auto& ms = duration_cast<milliseconds>(_timePoint - other._timePoint);
return std::move(Duration(ms));
auto ms = duration_cast<milliseconds>(_timePoint - other._timePoint).count();
return std::move(Duration(static_cast<float>(ms) / 1000.f));
}
e2d::Time e2d::Time::now()
{
return std::move(Time(steady_clock::now()));
Time t;
t._timePoint = steady_clock::now();
return std::move(t);
}

View File

@ -22,8 +22,7 @@ void e2d::SceneManager::destroyInstance()
}
e2d::SceneManager::SceneManager()
: _saveCurrScene(true)
, _currScene(nullptr)
: _currScene(nullptr)
, _nextScene(nullptr)
, _transition(nullptr)
, _scenes()
@ -34,7 +33,7 @@ e2d::SceneManager::~SceneManager()
{
}
void e2d::SceneManager::push(Scene * scene, Transition * transition /* = nullptr */, bool saveCurrentScene /* = true */)
void e2d::SceneManager::push(Scene * scene, bool saveCurrentScene)
{
if (!scene)
return;
@ -44,58 +43,59 @@ void e2d::SceneManager::push(Scene * scene, Transition * transition /* = nullptr
_nextScene = scene;
_nextScene->retain();
// 设置切换场景动作
if (transition)
// 初始化场景切换动画
if (_transition && !_transition->init(_currScene, _nextScene))
{
if (_transition)
{
_transition->_stop();
_transition->release();
}
_transition = transition;
transition->retain();
transition->_init(_currScene, _nextScene);
transition->_update();
WARN("Transition initialize failed!");
_transition->release();
_transition = nullptr;
}
if (_currScene)
if (saveCurrentScene && _currScene)
{
_saveCurrScene = saveCurrentScene;
_scenes.push(_currScene);
}
}
void e2d::SceneManager::pop(Transition * transition /* = nullptr */)
e2d::Scene* e2d::SceneManager::pop()
{
// 栈为空时,调用返回场景函数失败
if (_scenes.size() == 0)
{
WARN("Scene stack is empty!");
return;
return nullptr;
}
// 从栈顶取出场景指针,作为下一场景
_nextScene = _scenes.top();
_scenes.pop();
// 返回上一场景时,不保存当前场景
if (_currScene)
// 初始化场景切换动画
if (_transition && !_transition->init(_currScene, _nextScene))
{
_saveCurrScene = false;
WARN("Transition initialize failed!");
_transition->release();
_transition = nullptr;
}
// 设置切换场景动作
return _nextScene;
}
void e2d::SceneManager::setTransition(Transition * transition)
{
if (transition)
{
transition->retain();
transition->_init(_currScene, _nextScene);
transition->_update();
if (_transition)
{
_transition->stop();
_transition->release();
}
_transition = transition;
_transition->retain();
}
}
void e2d::SceneManager::clear()
{
// 清空场景栈
while (!_scenes.empty())
{
_scenes.top()->release();
@ -108,7 +108,7 @@ e2d::Scene * e2d::SceneManager::getCurrentScene()
return _currScene;
}
std::stack<e2d::Scene*> e2d::SceneManager::getSceneStack()
const std::stack<e2d::Scene*>& e2d::SceneManager::getSceneStack()
{
return _scenes;
}
@ -120,18 +120,12 @@ bool e2d::SceneManager::isTransitioning()
void e2d::SceneManager::update()
{
if (_transition == nullptr)
if (_currScene) _currScene->update();
if (_nextScene) _nextScene->update();
if (_transition)
{
// 更新场景内容
if (_currScene)
{
_currScene->update();
}
}
else
{
// 更新场景动作
_transition->_update();
_transition->update();
if (_transition->isDone())
{
@ -144,26 +138,17 @@ void e2d::SceneManager::update()
}
}
// 下一场景指针不为空时,切换场景
if (_nextScene)
{
if (_currScene)
{
// 执行当前场景的 onExit 函数
_currScene->onExit();
// 若要保存当前场景,把它放入栈中
if (_saveCurrScene)
{
_scenes.push(_currScene);
}
else
if (_scenes.empty() || _scenes.top() != _currScene)
{
_currScene->release();
}
}
// 执行下一场景的 onEnter 函数
_nextScene->onEnter();
_currScene = _nextScene;
@ -175,15 +160,11 @@ void e2d::SceneManager::render()
{
if (_transition)
{
_transition->_render();
_transition->render();
}
else
else if (_currScene)
{
// 绘制当前场景
if (_currScene)
{
_currScene->render();
}
_currScene->render();
}
}

View File

@ -6,8 +6,7 @@ e2d::Task::Task(const Function & func, const String & name)
, _stopped(false)
, _runTimes(0)
, _totalTimes(-1)
, _delay(0.f)
, _lastTime(0.f)
, _delay()
, _callback(func)
, _name(name)
{
@ -17,9 +16,8 @@ e2d::Task::Task(const Function & func, float delay, int times, const String & na
: _running(true)
, _stopped(false)
, _runTimes(0)
, _totalTimes(times)
, _delay(std::max(delay, 0.f))
, _lastTime(0.f)
, _totalTimes(times)
, _callback(func)
, _name(name)
{
@ -38,17 +36,24 @@ void e2d::Task::resume()
void e2d::Task::update()
{
if (_callback)
if (_totalTimes == 0)
{
_callback();
_stopped = true;
return;
}
++_runTimes;
_lastTime += _delay;
if (_callback)
{
_callback();
}
if (_runTimes == _totalTimes)
{
_stopped = true;
return;
}
}
@ -56,11 +61,11 @@ bool e2d::Task::isReady() const
{
if (_running)
{
if (_delay == 0)
if (_delay.milliseconds() == 0)
{
return true;
}
if ((Game::getInstance()->getTotalDuration().seconds() - _lastTime) >= _delay)
if (Time::now() - _lastTime >= _delay)
{
return true;
}
@ -80,5 +85,5 @@ e2d::String e2d::Task::getName() const
void e2d::Task::updateTime()
{
_lastTime = Game::getInstance()->getTotalDuration().seconds();
_lastTime = Time::now();
}

View File

@ -6,14 +6,20 @@ e2d::BoxTransition::BoxTransition(float duration)
{
}
void e2d::BoxTransition::_init(Scene * prev, Scene * next)
bool e2d::BoxTransition::init(Scene * prev, Scene * next)
{
Transition::_init(prev, next);
_inLayerParam.opacity = 0;
if (Transition::init(prev, next))
{
_inLayerParam.opacity = 0;
return true;
}
return false;
}
void e2d::BoxTransition::_updateCustom()
void e2d::BoxTransition::update()
{
Transition::update();
if (_delta <= 0.5)
{
_outLayerParam.contentBounds = D2D1::RectF(
@ -35,11 +41,11 @@ void e2d::BoxTransition::_updateCustom()
);
if (_delta >= 1)
{
this->_stop();
this->stop();
}
}
}
void e2d::BoxTransition::_reset()
void e2d::BoxTransition::reset()
{
}

View File

@ -6,24 +6,30 @@ e2d::EmergeTransition::EmergeTransition(float duration)
{
}
void e2d::EmergeTransition::_init(Scene * prev, Scene * next)
bool e2d::EmergeTransition::init(Scene * prev, Scene * next)
{
Transition::_init(prev, next);
_outLayerParam.opacity = 1;
_inLayerParam.opacity = 0;
if (Transition::init(prev, next))
{
_outLayerParam.opacity = 1;
_inLayerParam.opacity = 0;
return true;
}
return false;
}
void e2d::EmergeTransition::_updateCustom()
void e2d::EmergeTransition::update()
{
Transition::update();
_outLayerParam.opacity = 1 - _delta;
_inLayerParam.opacity = _delta;
if (_delta >= 1)
{
this->_stop();
this->stop();
}
}
void e2d::EmergeTransition::_reset()
void e2d::EmergeTransition::reset()
{
}

View File

@ -6,15 +6,21 @@ e2d::FadeTransition::FadeTransition(float duration)
{
}
void e2d::FadeTransition::_init(Scene * prev, Scene * next)
bool e2d::FadeTransition::init(Scene * prev, Scene * next)
{
Transition::_init(prev, next);
_outLayerParam.opacity = 1;
_inLayerParam.opacity = 0;
if (Transition::init(prev, next))
{
_outLayerParam.opacity = 1;
_inLayerParam.opacity = 0;
return true;
}
return false;
}
void e2d::FadeTransition::_updateCustom()
void e2d::FadeTransition::update()
{
Transition::update();
if (_delta < 0.5)
{
_outLayerParam.opacity = 1 - _delta * 2;
@ -26,11 +32,11 @@ void e2d::FadeTransition::_updateCustom()
_inLayerParam.opacity = (_delta - 0.5f) * 2;
if (_delta >= 1)
{
this->_stop();
this->stop();
}
}
}
void e2d::FadeTransition::_reset()
void e2d::FadeTransition::reset()
{
}

View File

@ -7,39 +7,44 @@ e2d::MoveTransition::MoveTransition(float duration, Direction direction)
{
}
void e2d::MoveTransition::_init(Scene * prev, Scene * next)
bool e2d::MoveTransition::init(Scene * prev, Scene * next)
{
Transition::_init(prev, next);
if (Transition::init(prev, next))
{
float width = _windowSize.width;
float height = _windowSize.height;
if (_direction == Direction::Up)
{
_posDelta = Vector2(0, -height);
_startPos = Point(0, height);
}
else if (_direction == Direction::Down)
{
_posDelta = Vector2(0, height);
_startPos = Point(0, -height);
}
else if (_direction == Direction::Left)
{
_posDelta = Vector2(-width, 0);
_startPos = Point(width, 0);
}
else if (_direction == Direction::Right)
{
_posDelta = Vector2(width, 0);
_startPos = Point(-width, 0);
}
float width = _windowSize.width;
float height = _windowSize.height;
if (_direction == Direction::Up)
{
_posDelta = Vector2(0, -height);
_startPos = Point(0, height);
if (_outScene) _outScene->getRoot()->setPos(0, 0);
_inScene->getRoot()->setPos(_startPos);
return true;
}
else if (_direction == Direction::Down)
{
_posDelta = Vector2(0, height);
_startPos = Point(0, -height);
}
else if (_direction == Direction::Left)
{
_posDelta = Vector2(-width, 0);
_startPos = Point(width, 0);
}
else if (_direction == Direction::Right)
{
_posDelta = Vector2(width, 0);
_startPos = Point(-width, 0);
}
if (_outScene) _outScene->getRoot()->setPos(0, 0);
_inScene->getRoot()->setPos(_startPos);
return false;
}
void e2d::MoveTransition::_updateCustom()
void e2d::MoveTransition::update()
{
Transition::update();
if (_outScene)
{
_outScene->getRoot()->setPos(_posDelta * _delta);
@ -51,11 +56,11 @@ void e2d::MoveTransition::_updateCustom()
if (_delta >= 1)
{
this->_stop();
this->stop();
}
}
void e2d::MoveTransition::_reset()
void e2d::MoveTransition::reset()
{
if (_outScene) _outScene->getRoot()->setPos(0, 0);
_inScene->getRoot()->setPos(0, 0);

View File

@ -4,7 +4,7 @@
e2d::Transition::Transition(float duration)
: _end(false)
, _last()
, _started()
, _delta(0)
, _outScene(nullptr)
, _inScene(nullptr)
@ -29,7 +29,7 @@ bool e2d::Transition::isDone()
return _end;
}
void e2d::Transition::_init(Scene * prev, Scene * next)
bool e2d::Transition::init(Scene * prev, Scene * next)
{
auto renderer = Renderer::getInstance();
// ´´½¨Í¼²ã
@ -42,10 +42,10 @@ void e2d::Transition::_init(Scene * prev, Scene * next)
if (FAILED(hr))
{
throw SystemException(L"场景过渡动画图层创建失败");
return false;
}
_last = Game::getInstance()->getTotalDuration();
_started = Time::now();
_outScene = prev;
_inScene = next;
if (_outScene) _outScene->retain();
@ -61,35 +61,24 @@ void e2d::Transition::_init(Scene * prev, Scene * next)
renderer->getSolidColorBrush(),
D2D1_LAYER_OPTIONS_NONE
);
return true;
}
void e2d::Transition::_update()
void e2d::Transition::update()
{
// 计算动作进度
if (_duration == 0)
{
_delta = 1;
}
else
{
_delta = (Game::getInstance()->getTotalDuration() - _last).seconds() / _duration;
_delta = (Time::now() - _started).seconds() / _duration;
_delta = std::min(_delta, 1.f);
}
this->_updateCustom();
// 更新场景内容
if (_outScene)
{
_outScene->update();
}
if (_inScene)
{
_inScene->update();
}
}
void e2d::Transition::_render()
void e2d::Transition::render()
{
auto pRT = Renderer::getInstance()->getRenderTarget();
@ -132,8 +121,8 @@ void e2d::Transition::_render()
}
}
void e2d::Transition::_stop()
void e2d::Transition::stop()
{
_end = true;
_reset();
reset();
}

View File

@ -85,7 +85,7 @@ protected:
bool _done;
bool _initialized;
Node * _target;
float _last;
Time _started;
};

View File

@ -118,9 +118,6 @@ public:
// 获取游戏配置
const Config& getConfig();
// 获取游戏总时长
Duration getTotalDuration() const;
private:
Game();
@ -132,9 +129,6 @@ private:
bool _quit;
bool _paused;
Config _config;
Time _start;
Time _now;
Time _last;
static Game * _instance;
};
@ -243,7 +237,13 @@ private:
E2D_DISABLE_COPY(Window);
// 注册窗口
HWND __create();
HWND __registerWindow();
// 根据客户区大小计算合适的窗口区域
Rect __adjustWindow(
int width,
int height
);
// Win32 窗口消息回调程序
static LRESULT CALLBACK WndProc(
@ -342,12 +342,6 @@ public:
Color color
);
// 渲染游戏画面
void render();
// 删除设备相关资源
void discardDeviceResources();
// 获取文字渲染器
TextRenderer * getTextRenderer();
@ -357,6 +351,12 @@ public:
// 获取 ID2D1SolidColorBrush 对象
ID2D1SolidColorBrush * getSolidColorBrush();
// 渲染游戏画面
void render();
// 删除设备相关资源
void discardDeviceResources();
// 获取 ID2D1Factory 对象
static ID2D1Factory * getFactory();

View File

@ -414,11 +414,7 @@ public:
Duration();
explicit Duration(
int ms
);
explicit Duration(
const std::chrono::milliseconds& ms
float seconds
);
// 获取毫秒数
@ -451,10 +447,6 @@ class Time
public:
Time();
explicit Time(
const std::chrono::steady_clock::time_point& time
);
// 获取时间戳
time_t getTimeStamp() const;

View File

@ -25,13 +25,15 @@ public:
// 场景入栈
void push(
Scene * scene, /* 下一个场景的指针 */
Transition * transition = nullptr, /* 场景切换动作 */
bool saveCurrentScene = true /* 是否保存当前场景 */
);
// 场景出栈
void pop(
Transition * transition = nullptr /* 场景切换动作 */
Scene* pop();
// 设置场景切换动作
void setTransition(
Transition * transition /* 场景切换动作 */
);
// 清空保存的所有场景
@ -41,7 +43,7 @@ public:
Scene * getCurrentScene();
// 获取场景栈
std::stack<Scene*> getSceneStack();
const std::stack<Scene*>& getSceneStack();
// 是否正在进行转场动作
bool isTransitioning();
@ -70,7 +72,6 @@ private:
E2D_DISABLE_COPY(SceneManager);
private:
bool _saveCurrScene;
Scene * _currScene;
Scene * _nextScene;
Transition * _transition;

View File

@ -308,8 +308,8 @@ private:
bool _stopped;
int _runTimes;
int _totalTimes;
float _delay;
float _lastTime;
Duration _delay;
Time _lastTime;
String _name;
Function _callback;
};

View File

@ -5,15 +5,10 @@ namespace e2d
{
class SceneManager;
// 场景过渡
class Transition :
public Ref
{
friend class SceneManager;
public:
explicit Transition(float duration);
@ -22,36 +17,32 @@ public:
// 场景过渡动画是否结束
bool isDone();
protected:
// 初始化场景过渡动画
virtual void _init(
virtual bool init(
Scene * prev,
Scene * next
);
// 更新场景过渡动画
virtual void _update();
// 更新场景过渡动画
virtual void _updateCustom() = 0;
virtual void update();
// 渲染场景过渡动画
virtual void _render();
// 重置场景过渡动画
virtual void _reset() = 0;
virtual void render();
// 停止场景过渡动画
virtual void _stop();
virtual void stop();
// ÖØÖó¡¾°¹ý¶É¶¯»­
virtual void reset() = 0;
protected:
bool _end;
float _duration;
float _delta;
Duration _last;
Size _windowSize;
Scene * _outScene;
Scene * _inScene;
bool _end;
float _duration;
float _delta;
Time _started;
Size _windowSize;
Scene* _outScene;
Scene* _inScene;
ID2D1Layer * _outLayer;
ID2D1Layer * _inLayer;
D2D1_LAYER_PARAMETERS _outLayerParam;
@ -68,16 +59,15 @@ public:
float duration /* 动画持续时长 */
);
protected:
// 更新动画
virtual void _updateCustom() override;
virtual void update() override;
virtual void _init(
virtual bool init(
Scene * prev,
Scene * next
) override;
virtual void _reset() override;
virtual void reset() override;
};
@ -90,16 +80,15 @@ public:
float duration /* 浮现动画持续时长 */
);
protected:
// 更新动画
virtual void _updateCustom() override;
virtual void update() override;
virtual void _init(
virtual bool init(
Scene * prev,
Scene * next
) override;
virtual void _reset() override;
virtual void reset() override;
};
@ -112,16 +101,15 @@ public:
float duration /* 动画持续时长 */
);
protected:
// 更新动画
virtual void _updateCustom() override;
virtual void update() override;
virtual void _init(
virtual bool init(
Scene * prev,
Scene * next
) override;
virtual void _reset() override;
virtual void reset() override;
};
@ -135,16 +123,15 @@ public:
Direction direction = Direction::Left /* 场景移动方向 */
);
protected:
// 更新动画
virtual void _updateCustom() override;
virtual void update() override;
virtual void _init(
virtual bool init(
Scene * prev,
Scene * next
) override;
virtual void _reset() override;
virtual void reset() override;
protected:
Direction _direction;