タイマーイベントってなに?
一言で言うならば、「時限発火式のイベント」です。
これだけじゃあんまりなのでもう少し詳しく説明すると、
あらかじめ時間(秒)を指定してタイマーをスタートしておく。その時間が経過することで発生するのがタイマーイベントです。
発生したタイマーイベントは、いつものos.pullEvent()で拾います。
さあ具体例を挙げましょう。
timer_id = os.startTimer(30) ename, tid = os.pullEvent("timer") if ename == "timer" and tid == timer_id then print("FIRE!!") else print("ERROR") end
- まず、os.startTimer(秒数)でタイマーをスタートします。
- ここでは、30秒後にタイマーが発火するようにしかけています。
- またこのとき、os.startTimer()はタイマーID(数値)を返します。
- 複数のタイマーが同時に動いているときにはこのIDで区別をつけましょう。
- ここでは、タイマーIDを変数timer_idに入れています。
- os.pullEvent("timer")でタイマーイベントを拾います。
- 返し値は、イベントネームと、そのタイマーイベントのIDです。
- IF文で、そのイベントがタイマーイベントであること、そしてタイマーIDが間違いなく、最初にセットしたタイマーのものであることを確かめたら"FIRE!!"しています。
sleep()の理解
さあこれで、今回のテーマであるsleep()関数が理解できますね。
function sleep( _nTime ) local timer = os.startTimer( _nTime ) repeat local sEvent, param = os.pullEvent( "timer" ) until param == timer end
- 変数_nTime秒後に発火するようにタイマーをスタートしておく
- このタイマーのIDは、変数timerに代入
- pullEventでタイマーイベントを拾い
- 拾ったタイマーイベントのIDをいれた変数paramが、最初に設定したタイマーIDと同じ場合に、repeatループを抜けて、sleep関数も終了。
- なお、repeat~untilでわざわざループさせている理由は、他の場所で設置されたタイマーが不幸にもこのタイミングで発火したとき、pullEvent()が間違えてそれを拾ってしまう可能性があるからです。その場合は、repeat構文の条件式で「このタイマーじゃないし!」と否定(false)されるので、再度repeatループを続けることになります。
- このようにして、正しいIDのタイマーにのみ反応するよう、sleepは作られています。
- 変数宣言の頭についている「local」って何?
- そういえば、これまで何度も使っているのに説明をしていませんでした。良い機会ですので、Luaにおける変数の取り扱いについて別記事で説明しましょう。
まとめ
sleepってつまり、なにやっている関数なの?
指定した秒数のタイマーをしかけて、それが発火するまで待機する関数です。
あぁぁぁぁ、長々と連載してきて、まとめるとこれだけなんですよね*1・・・・・・。
でも、ここまでの記事を読んでくれたら、イベントについての理解はかなり深まったはず。たぶん。
*1:本当は、coroutineの話とかしてtoo long without yieldingの話もしたいけど、さすがに話が脱線しすぎるし。それはまた別の機会かな。