MainLoop–遊戲主循環
簡單的程序主要分爲兩個線程,一個線程負責處理界面刷新(一般需要較高FPS),另一個線程負責處理程序邏輯(刷新頻率較低),此篇文章主要介紹遊戲的邏輯線程,我稱之爲GameMainLoop(以下簡稱ML)。
基本的ML很簡單,定義邏輯刷新頻率,定義刷新執行事件,我們直接來看代碼
MainLoop.h
//headers...
typedef std::function<void()> MainLoopFunc;
class MainLoop: public Singleton<MainLoop>
{
public:
#define MAIN_LOOP_FPS 1
MainLoop();
~MainLoop();
protected:
MainLoopFunc _loopfuncCallBack;
public:
void loopFunc();
void beginLoop();
bool bindfunc(MainLoopFunc);
private:
static unsigned int _currentTimeTick;
static unsigned int _begainTimeTick;
vector<MainLoopFunc> _taskArg;
};
#define mainLoop MainLoop::instance()
以及實現
MainLoop.cpp
unsigned int MainLoop::_currentTimeTick = clock();
unsigned int MainLoop::_begainTimeTick = clock();
MainLoop::MainLoop()
{
_loopfuncCallBack = std::bind(&MainLoop::loopFunc, this);
}
MainLoop::~MainLoop()
{
}
void MainLoop::loopFunc()
{
while (1)
{
unsigned int time = clock();
if (time > _currentTimeTick + 1 / MAIN_LOOP_FPS*CLOCKS_PER_SEC)
{
for_each(_taskArg.cbegin(), _taskArg.cend(), [](MainLoopFunc func)
{
func();
});
_currentTimeTick = time;
}
}
}
bool MainLoop::bindfunc(MainLoopFunc func)
{
if (func)
{
_taskArg.push_back(func);
return true;
}
else
return false;
}
void MainLoop::beginLoop()
{
std::thread th(_loopfuncCallBack);
th.join();
return;
}
基本的主循環很簡單,無非就是添加一個線程,然後每隔一段時間去執行邏輯更新函數,此處使用了bindfunc()函數來綁定新的回調事件,我們可以在後續製作中把新的邏輯都添加到函數數組中,而不用改變類破壞其封裝。(如果對c++11不瞭解,推薦搜索關鍵字:thread,function,回調函數)
此處Singleton類模板爲單例設計,所有的單例類都將繼承此類,網絡上關於單例的講解非常多,我在此不加贅述,這裏有一個優秀的單例模板:
Singleton.h
template <class T>
class Singleton
{
public:
//獲取類的唯一實例
static T* instance();
//釋放類的唯一實例
void release();
protected:
Singleton(void){}
~Singleton(void){}
static T* _instance;
};
template<class T>
T* Singleton<T>::_instance = NULL;
template <class T>
T* Singleton<T>::instance()
{
if (NULL == _instance){
_instance = new T;
}
return _instance;
}
template <class T>
void Singleton<T>::release()
{
if (!_instance)
return;
delete _instance;
_instance = 0;
}
//cpp文件中需要先聲明靜態變量
#define DECLARE_SINGLETON_MEMBER(_Ty) \
template <> _Ty* Singleton<_Ty>::_instance = NULL;