SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void* param)
interval | callbackを呼ぶまでの時間(ミリ秒) |
callback | 指定のintervalが経過した後に呼ばれる関数 |
param | callbackに渡されるポインタ |
/* タイマを開始する; 下のコールバックは時間が経過すると実行される */
Uint32 delay = (33 / 10) * 10; /* 10ミリ秒単位で切り捨てる */
SDL_TimerID my_timer_id = SDL_AddTimer(delay, my_callbackfunc, my_callback_param);
...
Uint32 my_callbackfunc(Uint32 interval, void *param)
{
SDL_Event event;
SDL_UserEvent userevent;
/* この例では, コールバックでSDL_USEREVENTイベントをキューに入れている.
このコールバック関数は一定の周期で再び呼ばれる */
userevent.type = SDL_USEREVENT;
userevent.code = 0;
userevent.data1 = NULL;
userevent.data2 = NULL;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent(&event);
return(interval);
}
userevent.data1に実行する関数のアドレス, userevent.data2にその引数を与え, イベントループでそれを扱うと, SDLのマルチスレッドの問題を避けられる.
/* 上のコードと同じ */
Uint32 my_callbackfunc(Uint32 interval, void *param)
{
SDL_Event event;
SDL_UserEvent userevent;
/* この例では, コールバックでSDL_USEREVENTイベントをキューに入れている.
このコールバック関数は一定の周期で再び呼ばれる */
userevent.type = SDL_USEREVENT;
userevent.code = 0;
userevent.data1 = &my_function;
userevent.data2 = param;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent(&event);
return(interval);
}
/* イベントループ */
SDL_Event event;
while (SDL_PollEvent (&event))
{
switch(event.type)
{
case SDL_USEREVENT: {
/* タイマでこの関数を呼びたいところだが, マルチスレッドの問題のためできない */
void (*p) (void*) = event.user.data1;
p(event.user.data2);
break;
}
/* ... */
}
}
この関数を使う場合, SDL_Init()にSDL_INIT_TIMERを渡している必要がある.
コールバック関数は, 第1引数にSDL_AddTimer()で設定したintervalを, 第2引数にparamを取る. そして, 戻り値(Uint32)は次に呼ぶまでの時間(ミリ秒)である. コールバック関数が0を戻すと, タイマはキャンセルされる.
コールバック関数は別スレッドで実行される. メインスレッドでタイマコールバックを処理する方法が必要ならばサンプルコードを参照すること.