日記

cocos2d-x v3.0 時間を取得する

ちょっと前まではv3.0についてググってもあんまり日本語の情報がなかったんですが、最近ちょっと増えてきましたね。


だいぶ前からの変更点ですが、v3.0ではv2.xにあったCCTimeクラスに代わるクラスはありません。
“cocos2d::CCTime::gettimeofdayCocos2d()”は”cocos2d::gettimeofday()”になっています。
使い方は前と一緒です。

double getSec(){
	timeval tv;
	gettimeofday(&tv, nullptr);
	return (tv.tv_sec) + (tv.tv_usec) * 1e-6;
}

これで起動してからの時間(秒)が取得できます。
ゲームスタートからの経過時間を調べるには、スタート時の時間を保持しておいて、
現在の時間 – スタート時の時間
で計算できますね。

他の方法として、”void update(float delta)”を使う方法もあるので、一応紹介しておきます。
この関数はSpriteやLayerなどの継承元にあるNodeクラスに定義されているので、これをオーバーライドして使います。

bool HelloWorldScene::init(){
	if ( !Layer::init() ) return false;
	scheduleUpdate();
	return true;
}

この”scheduleUpdate();”で”update()”関数が毎フレーム呼ばれるようになります。
そして、その時引数の(float delta)には前のフレームで呼ばれてから今のフレームまでの時間が渡されます。
これを利用して、この値をどんどん加算していけば経過時間がわかります。
gettimeofday()を使う方法と比べて簡単でお手軽なのですが、ちょっとだけ問題があります。

試しに↓のようなコードで計測してみました。

bool HelloWorldScene::init(){
	if ( !Layer::init() ) return false;
	scheduleUpdate();
	_startTime = Helper::getSec();
	_updateTime = 0;
	return true;
}

void HelloWorldScene::update(float delta){
	double currentTime = Helper::getSec() - _startTime;
	_updateTime += delta;
	log("gettimeofday() : %f \nupdate() : %f", currentTime,_updateTime);
}

getSec()は私の環境ではHelper名前空間に置いてますので”Helper::getSec();”になってます。
“_startTime”と” _updateTime”はdouble型のメンバ変数です。
これで約1分ほど計測してみたところ↓の結果になりました。

gettimeofday() : 59.999193
update() : 60.000305

update()の方がちょっぴり多いですね。この差は時間が経つにつれどんどん大きくなっていきます。
原因はfloat型の丸めによる誤差とかだと思います。
1分程度なら正直気にするほどの大きさでもないような気がしますが、厳密にやるのであればgettimeofday()の方が確実ですね。

……と言いたいところですが、スマホの場合ホーム画面に戻ってから復帰した時の問題があります。
gettimeofday()で時間を取得していた場合はホーム画面にいる間も時間が進んじゃうんですね。
これを回避するには、
AppDelegate::applicationDidEnterBackground()
AppDelegate::applicationWillEnterForeground()
を使えばいいです。AppDelegate.cppの下の方にあります。
これらは、ホーム画面に移った時と復帰した時にそれぞれ呼ばれます。ホームに移った時間を記憶しておけば、戻った時に何秒間待機していたかがわかるので、その値をスタート時の時間に足してあげれば大丈夫です。

2014/03/31



CAPTCHA