add Ticker & EventTicker

This commit is contained in:
Nomango 2020-05-20 00:47:46 +08:00
parent fed74ddb0a
commit 1805c016f8
13 changed files with 531 additions and 138 deletions

View File

@ -17,6 +17,7 @@
<ClInclude Include="..\..\src\kiwano\core\Cloneable.h" />
<ClInclude Include="..\..\src\kiwano\core\Common.h" />
<ClInclude Include="..\..\src\kiwano\core\Director.h" />
<ClInclude Include="..\..\src\kiwano\core\EventTicker.h" />
<ClInclude Include="..\..\src\kiwano\core\event\Event.h" />
<ClInclude Include="..\..\src\kiwano\core\event\EventType.h" />
<ClInclude Include="..\..\src\kiwano\core\event\KeyEvent.h" />
@ -31,6 +32,7 @@
<ClInclude Include="..\..\src\kiwano\core\Serializable.h" />
<ClInclude Include="..\..\src\kiwano\core\Singleton.h" />
<ClInclude Include="..\..\src\kiwano\core\String.h" />
<ClInclude Include="..\..\src\kiwano\core\Ticker.h" />
<ClInclude Include="..\..\src\kiwano\core\Time.h" />
<ClInclude Include="..\..\src\kiwano\core\Timer.h" />
<ClInclude Include="..\..\src\kiwano\core\Xml.h" />
@ -124,6 +126,7 @@
<ClCompile Include="..\..\src\kiwano\2d\TextActor.cpp" />
<ClCompile Include="..\..\src\kiwano\2d\Transition.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Allocator.cpp" />
<ClCompile Include="..\..\src\kiwano\core\EventTicker.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Module.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Director.cpp" />
<ClCompile Include="..\..\src\kiwano\core\EventDispatcher.cpp" />
@ -139,6 +142,7 @@
<ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Resource.cpp" />
<ClCompile Include="..\..\src\kiwano\core\String.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Ticker.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Time.cpp" />
<ClCompile Include="..\..\src\kiwano\core\Task.cpp" />
<ClCompile Include="..\..\src\kiwano\core\TaskManager.cpp" />

View File

@ -330,6 +330,12 @@
<ClInclude Include="..\..\src\kiwano\core\Timer.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\Ticker.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\core\EventTicker.h">
<Filter>core</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
@ -545,6 +551,12 @@
<ClCompile Include="..\..\src\kiwano\core\Timer.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\core\Ticker.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kiwano\core\EventTicker.cpp">
<Filter>core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="suppress_warning.ruleset" />

View File

@ -0,0 +1,57 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <kiwano/core/EventTicker.h>
namespace kiwano
{
TickEvent::TickEvent()
: Event(KGE_EVENT(TickEvent))
, ticker_(nullptr)
{
}
EventTickerPtr EventTicker::Create(Duration interval, int times)
{
EventTickerPtr ptr = memory::New<EventTicker>();
if (ptr)
{
ptr->SetInterval(interval);
ptr->SetTotalTickTimes(times);
}
return ptr;
}
bool EventTicker::Tick(Duration dt)
{
if (Ticker::Tick(dt))
{
TickEventPtr evt = new TickEvent;
evt->delta_time_ = GetDeltaTime();
evt->ticker_ = this;
DispatchEvent(evt.Get());
return true;
}
return false;
}
} // namespace kiwano

View File

@ -0,0 +1,69 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <kiwano/core/Ticker.h>
#include <kiwano/core/EventDispatcher.h>
#include <kiwano/core/event/Event.h>
namespace kiwano
{
KGE_DECLARE_SMART_PTR(TickEvent);
KGE_DECLARE_SMART_PTR(EventTicker);
/**
* \addtogroup Events
* @{
*/
/// \~chinese
/// @brief 报时时间
class KGE_API TickEvent : public Event
{
public:
TickEvent();
EventTicker* ticker_;
Duration delta_time_;
};
/**
* @}
*/
/// \~chinese
/// @brief 事件报时器
class KGE_API EventTicker
: public Ticker
, public EventDispatcher
{
public:
/// \~chinese
/// @brief 创建事件报时器
/// @param interval 报时间隔
/// @param times 报时次数(设 -1 为永久)
static EventTickerPtr Create(Duration interval, int times = -1);
bool Tick(Duration dt) override;
};
} // namespace kiwano

View File

@ -22,75 +22,74 @@
namespace kiwano
{
TaskPtr Task::Create(const Callback& cb, Duration interval, int times)
TaskPtr Task::Create(const Callback& cb, TickerPtr ticker)
{
TaskPtr ptr = memory::New<Task>();
if (ptr)
{
ptr->SetCallback(cb);
ptr->SetInterval(interval);
ptr->SetTotalRunTimes(times);
ptr->SetTicker(ticker);
}
return ptr;
}
TaskPtr Task::Create(const String& name, const Callback& cb, Duration interval, int times)
TaskPtr Task::Create(const String& name, const Callback& cb, TickerPtr ticker)
{
TaskPtr ptr = memory::New<Task>();
TaskPtr ptr = Task::Create(cb, ticker);
if (ptr)
{
ptr->SetName(name);
ptr->SetCallback(cb);
ptr->SetInterval(interval);
ptr->SetTotalRunTimes(times);
}
return ptr;
}
TaskPtr Task::Create(const Callback& cb, Duration interval, int times)
{
TickerPtr ticker = Ticker::Create(interval, times);
return Task::Create(cb, ticker);
}
TaskPtr Task::Create(const String& name, const Callback& cb, Duration interval, int times)
{
TickerPtr ticker = Ticker::Create(interval, times);
return Task::Create(name, cb, ticker);
}
Task::Task()
: running_(true)
, removeable_(false)
, run_times_(0)
, total_times_(0)
, interval_(0)
, elapsed_(0)
, callback_()
{
}
void Task::Update(Duration dt)
{
if (total_times_ == 0)
if (!ticker_)
{
Remove();
return;
}
if (IsRunning())
if (ticker_->GetTotalTickTimes() == 0)
{
if (!interval_.IsZero())
{
elapsed_ += dt;
if (elapsed_ < interval_)
return;
}
Remove();
return;
}
if (ticker_->Tick(dt))
{
if (callback_)
callback_(this, elapsed_);
callback_(this, ticker_->GetDeltaTime());
++run_times_;
elapsed_ = 0;
if (run_times_ == total_times_)
if (ticker_->GetTickedTimes() == ticker_->GetTotalTickTimes())
Remove();
}
}
void Task::Reset()
{
elapsed_ = 0;
run_times_ = 0;
if (ticker_)
ticker_->Reset();
}
} // namespace kiwano

View File

@ -19,8 +19,7 @@
// THE SOFTWARE.
#pragma once
#include <kiwano/core/ObjectBase.h>
#include <kiwano/core/Time.h>
#include <kiwano/core/Ticker.h>
#include <kiwano/core/IntrusiveList.h>
namespace kiwano
@ -47,9 +46,22 @@ public:
/// \~chinese
/// @brief 任务回调函数
/// @details
/// 回调函数第一个参数是任务自身,第二个参数是距离上次执行任务的时间间隔
/// 回调函数第一个参数是任务自身,第二个参数是时间增量
using Callback = Function<void(Task* /* self */, Duration /* dt */)>;
/// \~chinese
/// @brief 创建任务
/// @param cb 回调函数
/// @param 报时器
static TaskPtr Create(const Callback& cb, TickerPtr ticker);
/// \~chinese
/// @brief 创建任务
/// @param name 名称
/// @param cb 回调函数
/// @param 报时器
static TaskPtr Create(const String& name, const Callback& cb, TickerPtr ticker);
/// \~chinese
/// @brief 创建任务
/// @param cb 回调函数
@ -89,26 +101,6 @@ public:
/// @brief 任务是否可移除
bool IsRemoveable() const;
/// \~chinese
/// @brief 获取任务执行过回调函数的次数
int GetRunTimes() const;
/// \~chinese
/// @brief 获取任务执行回调函数的总次数
int GetTotalRunTimes() const;
/// \~chinese
/// @brief 设置任务执行回调函数的总次数
void SetTotalRunTimes(int times);
/// \~chinese
/// @brief 获取任务执行时间间隔
Duration GetInterval() const;
/// \~chinese
/// @brief 设置任务执行时间间隔
void SetInterval(Duration interval);
/// \~chinese
/// @brief 获取任务回调函数
Callback GetCallback() const;
@ -117,6 +109,14 @@ public:
/// @brief 设置任务回调函数
void SetCallback(const Callback& callback);
/// \~chinese
/// @brief 获取任务的报时器
TickerPtr GetTicker() const;
/// \~chinese
/// @brief 设置任务的报时器
void SetTicker(TickerPtr ticker);
private:
/// \~chinese
/// @brief 更新任务
@ -127,13 +127,10 @@ private:
void Reset();
private:
bool running_;
bool removeable_;
int run_times_;
int total_times_;
Duration interval_;
Duration elapsed_;
Callback callback_;
bool running_;
bool removeable_;
TickerPtr ticker_;
Callback callback_;
};
inline void Task::Start()
@ -161,29 +158,14 @@ inline bool Task::IsRemoveable() const
return removeable_;
}
inline int Task::GetRunTimes() const
inline TickerPtr Task::GetTicker() const
{
return run_times_;
return ticker_;
}
inline int Task::GetTotalRunTimes() const
inline void Task::SetTicker(TickerPtr ticker)
{
return total_times_;
}
inline void Task::SetTotalRunTimes(int times)
{
total_times_ = times;
}
inline Duration Task::GetInterval() const
{
return interval_;
}
inline void Task::SetInterval(Duration interval)
{
interval_ = interval;
ticker_ = ticker;
}
inline Task::Callback Task::GetCallback() const

View File

@ -40,17 +40,6 @@ void TaskManager::UpdateTasks(Duration dt)
}
}
Task* TaskManager::AddTask(const Task::Callback& cb, Duration interval, int times)
{
return AddTask(String(), cb, interval, times);
}
Task* TaskManager::AddTask(const String& name, const Task::Callback& cb, Duration interval, int times)
{
TaskPtr task = Task::Create(name, cb, interval, times);
return AddTask(task);
}
Task* TaskManager::AddTask(TaskPtr task)
{
KGE_ASSERT(task && "AddTask failed, NULL pointer exception");

View File

@ -30,21 +30,6 @@ namespace kiwano
class KGE_API TaskManager
{
public:
/// \~chinese
/// @brief 添加任务
/// @param cb 回调函数
/// @param interval 时间间隔
/// @param times 执行次数(设 -1 为永久执行)
Task* AddTask(const Task::Callback& cb, Duration interval, int times = -1);
/// \~chinese
/// @brief 添加任务
/// @param name 任务名称
/// @param cb 回调函数
/// @param interval 时间间隔
/// @param times 执行次数(设 -1 为永久执行)
Task* AddTask(const String& name, const Task::Callback& cb, Duration interval, int times = -1);
/// \~chinese
/// @brief Ìí¼ÓÈÎÎñ
Task* AddTask(TaskPtr task);

100
src/kiwano/core/Ticker.cpp Normal file
View File

@ -0,0 +1,100 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <kiwano/core/Ticker.h>
namespace kiwano
{
TickerPtr Ticker::Create(Duration interval, int times)
{
TickerPtr ptr = memory::New<Ticker>();
if (ptr)
{
ptr->SetInterval(interval);
ptr->SetTotalTickTimes(times);
}
return ptr;
}
Ticker::Ticker()
: ticked_times_(0)
, total_times_(0)
{
}
bool Ticker::Tick()
{
if (!timer_)
timer_ = Timer::Create();
if (timer_->IsPausing())
return false;
timer_->Tick();
return this->Tick(timer_->GetDeltaTime());
}
bool Ticker::Tick(Duration dt)
{
if (ticked_times_ == total_times_)
return false;
elapsed_time_ += dt;
if (elapsed_time_ + error_time_ > interval_)
{
delta_time_ = elapsed_time_;
error_time_ = (elapsed_time_ + error_time_) - interval_;
elapsed_time_ = 0;
++ticked_times_;
return true;
}
return false;
}
Duration Ticker::GetDeltaTime()
{
return delta_time_;
}
TimerPtr Ticker::GetTimer()
{
return timer_;
}
void Ticker::SetTimer(TimerPtr timer)
{
timer_ = timer;
}
void Ticker::Reset()
{
if (timer_)
timer_->Reset();
elapsed_time_ = 0;
delta_time_ = 0;
error_time_ = 0;
ticked_times_ = 0;
}
} // namespace kiwano

156
src/kiwano/core/Ticker.h Normal file
View File

@ -0,0 +1,156 @@
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <kiwano/core/Timer.h>
namespace kiwano
{
KGE_DECLARE_SMART_PTR(Ticker);
/// \~chinese
/// @brief 报时器
class KGE_API Ticker
: public ObjectBase
{
public:
/// \~chinese
/// @brief 创建报时器
/// @param interval 报时间隔
/// @param times 报时次数(设 -1 为永久)
static TickerPtr Create(Duration interval, int times = -1);
Ticker();
/// \~chinese
/// @brief 计时
/// @return 是否达到报时时长
virtual bool Tick();
/// \~chinese
/// @brief 计时
/// @param dt 时间增量
/// @return 是否达到报时时长
virtual bool Tick(Duration dt);
/// \~chinese
/// @brief 获取时间增量
Duration GetDeltaTime();
/// \~chinese
/// @brief 获取暂停状态
bool IsPausing() const;
/// \~chinese
/// @brief 暂停报时器
void Pause();
/// \~chinese
/// @brief 继续报时器
void Resume();
/// \~chinese
/// @brief 获取报时器报时次数
int GetTickedTimes() const;
/// \~chinese
/// @brief 获取报时器总报时次数
int GetTotalTickTimes() const;
/// \~chinese
/// @brief 设置报时器总报时次数
void SetTotalTickTimes(int times);
/// \~chinese
/// @brief 获取报时间隔
Duration GetInterval() const;
/// \~chinese
/// @brief 设置报时间隔
void SetInterval(Duration interval);
/// \~chinese
/// @brief 获取计时器
TimerPtr GetTimer();
/// \~chinese
/// @brief 设置计时器
void SetTimer(TimerPtr timer);
/// \~chinese
/// @brief 重置报时器
void Reset();
private:
int ticked_times_;
int total_times_;
Duration interval_;
Duration elapsed_time_;
Duration delta_time_;
Duration error_time_;
TimerPtr timer_;
};
inline void Ticker::Pause()
{
KGE_ASSERT(timer_);
timer_->Pause();
}
inline void Ticker::Resume()
{
KGE_ASSERT(timer_);
timer_->Resume();
}
inline bool Ticker::IsPausing() const
{
if (timer_)
return timer_->IsPausing();
return true;
}
inline int Ticker::GetTickedTimes() const
{
return ticked_times_;
}
inline int Ticker::GetTotalTickTimes() const
{
return total_times_;
}
inline void Ticker::SetTotalTickTimes(int times)
{
total_times_ = times;
}
inline Duration Ticker::GetInterval() const
{
return interval_;
}
inline void Ticker::SetInterval(Duration interval)
{
interval_ = interval;
}
} // namespace kiwano

View File

@ -19,13 +19,21 @@
// THE SOFTWARE.
#include <kiwano/core/Timer.h>
#include <kiwano/core/Allocator.h>
namespace kiwano
{
Timer::Timer()
: is_stopped_(false)
TimerPtr Timer::Create()
{
TimerPtr ptr = memory::New<Timer>();
return ptr;
}
Timer::Timer()
: is_paused_(false)
{
Reset();
}
Timer::~Timer() {}
@ -37,42 +45,19 @@ Duration Timer::GetDeltaTime() const
Duration Timer::GetTotalTime() const
{
if (is_stopped_)
if (is_paused_)
return paused_time_ - start_time_ - total_idle_time_;
return current_time_ - start_time_ - total_idle_time_;
}
void Timer::Start()
bool Timer::IsPausing() const
{
if (is_stopped_)
{
const auto now = Time::Now();
// add the duration of the pause to the total idle time
total_idle_time_ += (now - paused_time_);
// set the previous time to the current time
previous_time_ = now;
paused_time_ = Time();
is_stopped_ = false;
}
}
void Timer::Stop()
{
if (!is_stopped_)
{
const auto now = Time::Now();
paused_time_ = now;
is_stopped_ = true;
}
return is_paused_;
}
void Timer::Tick()
{
if (is_stopped_)
if (is_paused_)
{
delta_time_ = 0;
return;
@ -91,14 +76,44 @@ void Timer::Tick()
delta_time_ = 0;
}
void Timer::Resume()
{
if (is_paused_)
{
const auto now = Time::Now();
// add the duration of the pause to the total idle time
total_idle_time_ += (now - paused_time_);
// set the previous time to the current time
previous_time_ = now;
paused_time_ = Time();
is_paused_ = false;
}
}
void Timer::Pause()
{
if (!is_paused_)
{
const auto now = Time::Now();
paused_time_ = now;
is_paused_ = true;
}
}
void Timer::Reset()
{
const auto now = Time::Now();
start_time_ = now;
current_time_ = now;
previous_time_ = now;
paused_time_ = Time();
is_stopped_ = false;
delta_time_ = 0;
is_paused_ = false;
}
} // namespace kiwano

View File

@ -27,28 +27,50 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(Timer);
class Timer
/// \~chinese
/// @brief 计时器
class KGE_API Timer
: public ObjectBase
{
public:
/// \~chinese
/// @brief 创建计时器
static TimerPtr Create();
Timer();
virtual ~Timer();
/// \~chinese
/// @brief 获取时间增量
Duration GetDeltaTime() const;
/// \~chinese
/// @brief 获取总时长
Duration GetTotalTime() const;
void Start();
void Stop();
/// \~chinese
/// @brief 获取暂停状态
bool IsPausing() const;
/// \~chinese
/// @brief 计时
void Tick();
/// \~chinese
/// @brief 继续计时
void Resume();
/// \~chinese
/// @brief 暂停计时
void Pause();
/// \~chinese
/// @brief 重置计时器
void Reset();
private:
bool is_stopped_;
bool is_paused_;
Time start_time_;
Time paused_time_;
Time current_time_;

View File

@ -52,6 +52,9 @@
#include <kiwano/core/Resource.h>
#include <kiwano/core/SmartPtr.hpp>
#include <kiwano/core/Time.h>
#include <kiwano/core/Timer.h>
#include <kiwano/core/Ticker.h>
#include <kiwano/core/EventTicker.h>
#include <kiwano/core/Task.h>
#include <kiwano/core/TaskManager.h>
#include <kiwano/core/event/Event.h>