ブログBlog
「一定の時間ごとに、何かをするプログラム」
投稿日:2014年09月22日
こんにちは。平野洋平です。
最近、昼間は暑いけど、夜は寒い。
そんな日が続いています。
体調管理に気を付けたいですね。
今回の話題は、最近プログラムを書いていてで悩んだ問題です。
例えば、10秒ごとに文字を表示させたい、というとき、
気を付けないといけないことがあります。
いま、cocos2d-x・C++で、ゲームアプリを作っているのですが、
このようなゲームでは、基本的に約「1秒間に60回」画面を書き換える、ということをしています。
別の言い方をすると「1/60秒ごとに(1フレームごとに)、1回」書き換える、です。
その結果として、画面上のキャラクターが動いているように見えたりするわけです。
しかし、この約「1秒間に60回」というのが、実は曲者です。
サクサクと、ゲームが動いていてくれる時はいいのですが。
重いデータ(画像など)を扱うときや、何回も同じ処理を繰り返す時などは、
この「1秒間に60回」がズレてきてしまいます。
例えば、「1秒間に40回」しか書き換えない、などという事態が起こります。
そこをうまくするのが、フレーム制御、というものです。
最初、そんなことは知らず、この「1秒間に60回」から逆算して、
「10秒ごとに文字を表示するには、画面の書き換え回数をカウントし、
それが600回になったら、10秒たった」とするプログラムを書いていました。
しかし、これだと、先ほどのズレが生じていますから上手くいきません。
そこで、今回私がとった方法は、1フレームつまり1回ごとに経過秒数(約1/60秒)を数えていく、というやり方です。
60回、ではなく、1フレームつまり1回ごとの経過秒数(約1/60秒)を数えて、
その和が1秒になったら、「時間が1秒たった」とする、というものです。
そして、プログラム上は以下の fDelta という値が、1回ごとの経過秒数(約1/60秒)に当たります。
void GameScene::measureTime(float fDelta)
{
m_time += fDelta;
}
この関数が、1フレームごとに呼び出されています。
(先ほどのズレは、この経過秒数がまちまちなために起こっています。)
そして、この関数を呼び出すのと同じところで、fDelta:経過秒数 を数えます。
this->schedule(schedule_selector(GameScene::measureTime));
if(m_count_1_Second < 0.0f) m_count_1_Second = 1.0f;
else m_count_1_Second -= dt;
やっているのは、フレームが呼ばれるたびに、fDelta(dt)を1.0秒から引いていきます。
そして、マイナスの値になったら、「時間が1秒たった」とし、
数えていたものをリセットして、また1.0秒から引いていきます。
一方「時間」は、fDelta を単純に足したものです。
そして、この「時間が1秒たった」と「時間」を組み合わせて、「10秒ごとに文字を表示する」を行います。
例えば、
if((m_count_1_Second < 0.0f) && ((m_time % d_time) == 0))
のようにすれば、「 d_time ごとに何かをする」ことができます。