add Application::Pause & Application::Resume

This commit is contained in:
Nomango 2020-05-25 16:48:40 +08:00
parent 6d1cf35730
commit 1af108df90
9 changed files with 86 additions and 44 deletions

View File

@ -23,6 +23,7 @@
namespace kiwano namespace kiwano
{ {
/** /**
* \addtogroup Actions * \addtogroup Actions
* @{ * @{

View File

@ -24,6 +24,7 @@
#include <regex> #include <regex>
#include <unordered_map> #include <unordered_map>
#include <chrono> #include <chrono>
#include <thread>
namespace kiwano namespace kiwano
{ {
@ -231,6 +232,17 @@ float Duration::Hours() const
return static_cast<float>(hour) + static_cast<float>(ms) / (60 * 60 * 1000.f); return static_cast<float>(hour) + static_cast<float>(ms) / (60 * 60 * 1000.f);
} }
void Duration::Sleep() const
{
using std::chrono::milliseconds;
using std::this_thread::sleep_for;
if (milliseconds_)
{
sleep_for(milliseconds(milliseconds_));
}
}
String Duration::ToString() const String Duration::ToString() const
{ {
if (IsZero()) if (IsZero())

View File

@ -96,6 +96,10 @@ struct KGE_API Duration
/// @param hours 小时数 /// @param hours 小时数
void SetHours(float hours); void SetHours(float hours);
/// \~chinese
/// @brief ÐÝÃß
void Sleep() const;
/// \~chinese /// \~chinese
/// @brief 转为字符串 /// @brief 转为字符串
String ToString() const; String ToString() const;

View File

@ -30,7 +30,7 @@ typedef IntrusiveList<EventListenerPtr> ListenerList;
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
class KGE_API EventDispatcher class KGE_API EventDispatcher
{ {

View File

@ -36,11 +36,15 @@ int GetVersion()
Application::Application() Application::Application()
: running_(false) : running_(false)
, is_paused_(false)
, time_scale_(1.f) , time_scale_(1.f)
{ {
Use(Renderer::GetInstance()); Use(Renderer::GetInstance());
Use(Input::GetInstance()); Use(Input::GetInstance());
Use(Director::GetInstance()); Use(Director::GetInstance());
ticker_ = Ticker::Create(0);
ticker_->Tick();
} }
Application::~Application() Application::~Application()
@ -52,8 +56,8 @@ void Application::Run(RunnerPtr runner, bool debug)
{ {
KGE_ASSERT(runner); KGE_ASSERT(runner);
runner_ = runner; runner_ = runner;
timer_ = Timer::Create();
running_ = true; running_ = true;
is_paused_ = false;
// Setup all modules // Setup all modules
for (auto c : modules_) for (auto c : modules_)
@ -72,15 +76,34 @@ void Application::Run(RunnerPtr runner, bool debug)
while (running_) while (running_)
{ {
timer_->Tick(); if (ticker_->Tick())
{
if (!runner->MainLoop(timer_->GetDeltaTime())) if (!runner->MainLoop(ticker_->GetDeltaTime()))
running_ = false; running_ = false;
}
} }
this->Destroy(); this->Destroy();
} }
void Application::Pause()
{
is_paused_ = true;
if (ticker_)
{
ticker_->Pause();
}
}
void Application::Resume()
{
is_paused_ = false;
if (ticker_)
{
ticker_->Resume();
}
}
void Application::Quit() void Application::Quit()
{ {
running_ = false; running_ = false;
@ -130,7 +153,7 @@ void Application::DispatchEvent(EventPtr evt)
void Application::DispatchEvent(Event* evt) void Application::DispatchEvent(Event* evt)
{ {
if (!running_) if (!running_ /* Dispatch events even if application is paused */)
return; return;
for (auto comp : modules_) for (auto comp : modules_)
@ -144,7 +167,7 @@ void Application::DispatchEvent(Event* evt)
void Application::Update(Duration dt) void Application::Update(Duration dt)
{ {
if (!running_) if (!running_ || is_paused_)
return; return;
// Before update // Before update
@ -198,7 +221,7 @@ void Application::Update(Duration dt)
void Application::Render() void Application::Render()
{ {
if (!running_) if (!running_ /* Render even if application is paused */)
return; return;
Renderer& renderer = Renderer::GetInstance(); Renderer& renderer = Renderer::GetInstance();

View File

@ -27,7 +27,7 @@
#include <kiwano/event/Event.h> #include <kiwano/event/Event.h>
#include <kiwano/platform/Runner.h> #include <kiwano/platform/Runner.h>
#include <kiwano/platform/Window.h> #include <kiwano/platform/Window.h>
#include <kiwano/utils/Timer.h> #include <kiwano/utils/Ticker.h>
namespace kiwano namespace kiwano
{ {
@ -60,6 +60,18 @@ public:
*/ */
void Run(RunnerPtr runner, bool debug = false); void Run(RunnerPtr runner, bool debug = false);
/**
* \~chinese
* @brief
*/
void Pause();
/**
* \~chinese
* @brief
*/
void Resume();
/** /**
* \~chinese * \~chinese
* @brief ÖÕÖ¹Ó¦ÓóÌÐò * @brief ÖÕÖ¹Ó¦ÓóÌÐò
@ -80,15 +92,15 @@ public:
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
TimerPtr GetTimer() const; TickerPtr GetTicker() const;
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/ */
bool IsRunning() const; bool IsPaused() const;
/** /**
* \~chinese * \~chinese
@ -151,9 +163,10 @@ public:
private: private:
bool running_; bool running_;
bool is_paused_;
float time_scale_; float time_scale_;
RunnerPtr runner_; RunnerPtr runner_;
TimerPtr timer_; TickerPtr ticker_;
List<Module*> modules_; List<Module*> modules_;
std::mutex perform_mutex_; std::mutex perform_mutex_;
Queue<Function<void()>> functions_to_perform_; Queue<Function<void()>> functions_to_perform_;
@ -170,14 +183,14 @@ inline WindowPtr Application::GetMainWindow() const
return runner_->GetMainWindow(); return runner_->GetMainWindow();
} }
inline TimerPtr Application::GetTimer() const inline TickerPtr Application::GetTicker() const
{ {
return timer_; return ticker_;
} }
inline bool Application::IsRunning() const inline bool Application::IsPaused() const
{ {
return running_; return is_paused_;
} }
} // namespace kiwano } // namespace kiwano

View File

@ -21,6 +21,8 @@
#include <kiwano/platform/Runner.h> #include <kiwano/platform/Runner.h>
#include <kiwano/platform/Application.h> #include <kiwano/platform/Application.h>
#define KGE_MAX_SKIP_FRAMES 10
namespace kiwano namespace kiwano
{ {
@ -95,6 +97,12 @@ bool Runner::MainLoop(Duration dt)
} }
app.Render(); app.Render();
if (app.IsPaused())
{
// Slow down when the application is paused
Duration(5).Sleep();
}
return true; return true;
} }

View File

@ -573,11 +573,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
is_minimized_ = true; is_minimized_ = true;
// Pause game when window is minimized // Pause game when window is minimized
if (Application::GetInstance().IsRunning()) Application::GetInstance().Pause();
{
TimerPtr timer = Application::GetInstance().GetTimer();
timer->Pause();
}
} }
else if (SIZE_MAXIMIZED == wparam) else if (SIZE_MAXIMIZED == wparam)
{ {
@ -586,11 +582,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
if (is_minimized_) if (is_minimized_)
{ {
is_minimized_ = false; is_minimized_ = false;
if (Application::GetInstance().IsRunning()) Application::GetInstance().Resume();
{
TimerPtr timer = Application::GetInstance().GetTimer();
timer->Resume();
}
} }
} }
else if (wparam == SIZE_RESTORED) else if (wparam == SIZE_RESTORED)
@ -601,11 +593,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
// the window was restored and was previously minimized // the window was restored and was previously minimized
is_minimized_ = false; is_minimized_ = false;
if (Application::GetInstance().IsRunning()) Application::GetInstance().Resume();
{
TimerPtr timer = Application::GetInstance().GetTimer();
timer->Resume();
}
} }
else if (is_resizing_) else if (is_resizing_)
{ {
@ -630,22 +618,14 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
case WM_ENTERSIZEMOVE: case WM_ENTERSIZEMOVE:
{ {
is_resizing_ = true; is_resizing_ = true;
if (Application::GetInstance().IsRunning()) Application::GetInstance().Pause();
{
TimerPtr timer = Application::GetInstance().GetTimer();
timer->Pause();
}
return 0; return 0;
} }
case WM_EXITSIZEMOVE: case WM_EXITSIZEMOVE:
{ {
is_resizing_ = false; is_resizing_ = false;
if (Application::GetInstance().IsRunning()) Application::GetInstance().Resume();
{
TimerPtr timer = Application::GetInstance().GetTimer();
timer->Resume();
}
// Send window resized event when client size changed // Send window resized event when client size changed
RECT client_rect = { 0 }; RECT client_rect = { 0 };

View File

@ -23,6 +23,7 @@
namespace kiwano namespace kiwano
{ {
void TaskScheduler::Update(Duration dt) void TaskScheduler::Update(Duration dt)
{ {
if (tasks_.IsEmpty()) if (tasks_.IsEmpty())