diff --git a/src/kiwano/2d/action/ActionScheduler.h b/src/kiwano/2d/action/ActionScheduler.h index ccbf4172..1cc4f26f 100644 --- a/src/kiwano/2d/action/ActionScheduler.h +++ b/src/kiwano/2d/action/ActionScheduler.h @@ -23,6 +23,7 @@ namespace kiwano { + /** * \addtogroup Actions * @{ diff --git a/src/kiwano/core/Time.cpp b/src/kiwano/core/Time.cpp index 969c4bee..b37c2189 100644 --- a/src/kiwano/core/Time.cpp +++ b/src/kiwano/core/Time.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace kiwano { @@ -231,6 +232,17 @@ float Duration::Hours() const return static_cast(hour) + static_cast(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 { if (IsZero()) diff --git a/src/kiwano/core/Time.h b/src/kiwano/core/Time.h index 5f86341e..39e0edd8 100644 --- a/src/kiwano/core/Time.h +++ b/src/kiwano/core/Time.h @@ -96,6 +96,10 @@ struct KGE_API Duration /// @param hours 小时数 void SetHours(float hours); + /// \~chinese + /// @brief 休眠 + void Sleep() const; + /// \~chinese /// @brief 转为字符串 String ToString() const; diff --git a/src/kiwano/event/EventDispatcher.h b/src/kiwano/event/EventDispatcher.h index 35c286d2..6e5a0861 100644 --- a/src/kiwano/event/EventDispatcher.h +++ b/src/kiwano/event/EventDispatcher.h @@ -30,7 +30,7 @@ typedef IntrusiveList ListenerList; /** * \~chinese - * @brief 事件分发系统 + * @brief 事件分发器 */ class KGE_API EventDispatcher { diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 78ac7109..52a1533f 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -36,11 +36,15 @@ int GetVersion() Application::Application() : running_(false) + , is_paused_(false) , time_scale_(1.f) { Use(Renderer::GetInstance()); Use(Input::GetInstance()); Use(Director::GetInstance()); + + ticker_ = Ticker::Create(0); + ticker_->Tick(); } Application::~Application() @@ -52,8 +56,8 @@ void Application::Run(RunnerPtr runner, bool debug) { KGE_ASSERT(runner); runner_ = runner; - timer_ = Timer::Create(); running_ = true; + is_paused_ = false; // Setup all modules for (auto c : modules_) @@ -72,15 +76,34 @@ void Application::Run(RunnerPtr runner, bool debug) while (running_) { - timer_->Tick(); - - if (!runner->MainLoop(timer_->GetDeltaTime())) - running_ = false; + if (ticker_->Tick()) + { + if (!runner->MainLoop(ticker_->GetDeltaTime())) + running_ = false; + } } 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() { running_ = false; @@ -130,7 +153,7 @@ void Application::DispatchEvent(EventPtr evt) void Application::DispatchEvent(Event* evt) { - if (!running_) + if (!running_ /* Dispatch events even if application is paused */) return; for (auto comp : modules_) @@ -144,7 +167,7 @@ void Application::DispatchEvent(Event* evt) void Application::Update(Duration dt) { - if (!running_) + if (!running_ || is_paused_) return; // Before update @@ -198,7 +221,7 @@ void Application::Update(Duration dt) void Application::Render() { - if (!running_) + if (!running_ /* Render even if application is paused */) return; Renderer& renderer = Renderer::GetInstance(); diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index 2a803e1c..10765c55 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include namespace kiwano { @@ -60,6 +60,18 @@ public: */ void Run(RunnerPtr runner, bool debug = false); + /** + * \~chinese + * @brief 暂停应用程序 + */ + void Pause(); + + /** + * \~chinese + * @brief 继续应用程序 + */ + void Resume(); + /** * \~chinese * @brief 终止应用程序 @@ -80,15 +92,15 @@ public: /** * \~chinese - * @brief 获取计时器 + * @brief 获取报时器 */ - TimerPtr GetTimer() const; + TickerPtr GetTicker() const; /** * \~chinese - * @brief 是否正在运行 + * @brief 获取暂停状态 */ - bool IsRunning() const; + bool IsPaused() const; /** * \~chinese @@ -151,9 +163,10 @@ public: private: bool running_; + bool is_paused_; float time_scale_; RunnerPtr runner_; - TimerPtr timer_; + TickerPtr ticker_; List modules_; std::mutex perform_mutex_; Queue> functions_to_perform_; @@ -170,14 +183,14 @@ inline WindowPtr Application::GetMainWindow() const 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 diff --git a/src/kiwano/platform/Runner.cpp b/src/kiwano/platform/Runner.cpp index 7417b436..045e2dd4 100644 --- a/src/kiwano/platform/Runner.cpp +++ b/src/kiwano/platform/Runner.cpp @@ -21,6 +21,8 @@ #include #include +#define KGE_MAX_SKIP_FRAMES 10 + namespace kiwano { @@ -95,6 +97,12 @@ bool Runner::MainLoop(Duration dt) } app.Render(); + + if (app.IsPaused()) + { + // Slow down when the application is paused + Duration(5).Sleep(); + } return true; } diff --git a/src/kiwano/platform/win32/WindowImpl.cpp b/src/kiwano/platform/win32/WindowImpl.cpp index 83116760..4025a954 100644 --- a/src/kiwano/platform/win32/WindowImpl.cpp +++ b/src/kiwano/platform/win32/WindowImpl.cpp @@ -573,11 +573,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA is_minimized_ = true; // Pause game when window is minimized - if (Application::GetInstance().IsRunning()) - { - TimerPtr timer = Application::GetInstance().GetTimer(); - timer->Pause(); - } + Application::GetInstance().Pause(); } else if (SIZE_MAXIMIZED == wparam) { @@ -586,11 +582,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA if (is_minimized_) { is_minimized_ = false; - if (Application::GetInstance().IsRunning()) - { - TimerPtr timer = Application::GetInstance().GetTimer(); - timer->Resume(); - } + Application::GetInstance().Resume(); } } 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 is_minimized_ = false; - if (Application::GetInstance().IsRunning()) - { - TimerPtr timer = Application::GetInstance().GetTimer(); - timer->Resume(); - } + Application::GetInstance().Resume(); } else if (is_resizing_) { @@ -630,22 +618,14 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA case WM_ENTERSIZEMOVE: { is_resizing_ = true; - if (Application::GetInstance().IsRunning()) - { - TimerPtr timer = Application::GetInstance().GetTimer(); - timer->Pause(); - } + Application::GetInstance().Pause(); return 0; } case WM_EXITSIZEMOVE: { is_resizing_ = false; - if (Application::GetInstance().IsRunning()) - { - TimerPtr timer = Application::GetInstance().GetTimer(); - timer->Resume(); - } + Application::GetInstance().Resume(); // Send window resized event when client size changed RECT client_rect = { 0 }; diff --git a/src/kiwano/utils/TaskScheduler.cpp b/src/kiwano/utils/TaskScheduler.cpp index 40030c4d..bf8ab4e3 100644 --- a/src/kiwano/utils/TaskScheduler.cpp +++ b/src/kiwano/utils/TaskScheduler.cpp @@ -23,6 +23,7 @@ namespace kiwano { + void TaskScheduler::Update(Duration dt) { if (tasks_.IsEmpty())