SDL2系列教程12-類封裝SDL_Timer
為方便使用SDL的定時器,實現了類封裝:
程式碼如下
time.h:
#pragma once
#include <map> #include <string> #include <SDL.h>
class timer { timer(Uint64 s, Uint64 p, bool perf); ~timer();
Uint64 start; Uint64 pause; Uint64 lag; bool isPerfCounter;
friend class Time; };
class Time { public: Time(); ~Time();
bool init(); bool kill();
bool addTimer(const std::string& tID, bool startPaused = false); bool addPerfCounter(const std::string& tID, bool startPaused = false);
bool remove(const std::string& tID);
bool addCallback(Uint32(*callback)(Uint32, void*), Uint32 delay, void* param, bool save = false, const std::string& cID = ""); bool removeCallback(const std::string& cID);
bool pause(const std::string& tID); bool resume(const std::string& tID); bool reset(const std::string& tID); bool toggle(const std::string& tID);
Uint64 get(const std::string& tID);
Uint64 getPerfFreq(); Uint64 ticksSinceStart(); Uint64 perfSinceStart();
private: std::map<std::string, timer*> timers; std::map<std::string, Uint32> callbacks; bool good; };
time.cpp:
#include "time.h"
timer::timer(Uint64 s, Uint64 p, bool perf) { start = s; pause = p; isPerfCounter = perf; lag = 0; }
timer::~timer() {}
Time::Time() { good = false; }
Time::~Time() { for (auto i : timers) delete i.second; for (auto i : callbacks) removeCallback(i.first); }
bool Time::init() { if (good) { return false; }
int result = SDL_InitSubSystem(SDL_INIT_TIMER); if (result != 0) { return false; }
good = true; return true; }
bool Time::kill() {
if (!good) { return false; }
SDL_QuitSubSystem(SDL_INIT_TIMER);
good = false; return true; }
bool Time::addTimer(const std::string& tID, bool startPaused) { if (timers.find(tID) != timers.end()) { return false; }
Uint64 currentTime = ticksSinceStart(); timer* newT = new timer(currentTime, startPaused ? currentTime : 0, false); timers.insert({tID, newT}); return true; }
bool Time::addPerfCounter(const std::string& tID, bool startPaused) {
if (timers.find(tID) != timers.end()) { return false; }
Uint64 currentTime = perfSinceStart(); timer* newPC = new timer(currentTime, startPaused ? currentTime : 0, true); timers.insert({tID, newPC}); return true; }
bool Time::remove(const std::string& tID) {
auto entry = timers.find(tID); if (entry == timers.end()) { return false; }
delete entry->second; timers.erase(entry); return true; }
bool Time::addCallback(Uint32(*callback)(Uint32, void*), Uint32 delay, void* param, bool save, const std::string& tID) {
if (save && tID == "") { return false; }
if (save && callbacks.find(tID) != callbacks.end()) { return false; }
SDL_TimerID result = SDL_AddTimer(delay,(SDL_TimerCallback)callback,param); if (result == 0) { return false; }
if (save) { callbacks.insert({tID, result}); } return true; }
bool Time::removeCallback(const std::string& tID) {
auto entry = callbacks.find(tID); if (entry == callbacks.end()) { return false; }
int result = SDL_RemoveTimer(entry->second); callbacks.erase(entry); if (result == 0) { return false; }
return true; }
bool Time::pause(const std::string& tID) { auto entry = timers.find(tID); if (entry == timers.end()) { return false; }
if (entry->second->pause) { return false; }
if (entry->second->isPerfCounter) entry->second->pause = perfSinceStart() - entry->second->pause - entry->second->start; else entry->second->pause = ticksSinceStart() - entry->second->pause - entry->second->start;
return true; }
bool Time::resume(const std::string& tID) {
auto entry = timers.find(tID); if (entry == timers.end()) { return false; }
if (!entry->second->pause) { return false; }
if (entry->second->isPerfCounter) entry->second->lag = perfSinceStart() - entry->second->pause - entry->second->start; else entry->second->lag = ticksSinceStart() - entry->second->pause - entry->second->start; entry->second->pause = 0; return true; }
bool Time::reset(const std::string& tID) {
auto entry = timers.find(tID); if (entry == timers.end()) { return false; }
if (entry->second->isPerfCounter) entry->second->start = perfSinceStart(); else entry->second->start = ticksSinceStart();
entry->second->pause = 0; entry->second->lag = 0; return true; }
bool Time::toggle(const std::string& tID) {
auto entry = timers.find(tID); if (entry == timers.end()) { return false; }
if (entry->second->pause) resume(tID); else pause(tID);
return true; }
Uint64 Time::get(const std::string& tID) {
auto entry = timers.find(tID); if (entry == timers.end()) { return -1; }
if (entry->second->pause) return entry->second->pause;
if (entry->second->isPerfCounter) return perfSinceStart() - entry->second->start - entry->second->lag; else return ticksSinceStart() - entry->second->start - entry->second->lag; }
Uint64 Time::getPerfFreq() { return SDL_GetPerformanceFrequency(); }
Uint64 Time::ticksSinceStart() { return SDL_GetTicks(); }
Uint64 Time::perfSinceStart() { return SDL_GetPerformanceCounter(); }