読者です 読者をやめる 読者になる 読者になる

夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【cocos2d】scheduleUpdateでプライオリティを指定するのは超重要

cocos2d TravelShooting JP

久々にハマりました。
例によってTravelShooting JPというスペハリ風擬似3Dシューティングゲームの開発をしていまが、新たなボスキャラを実装し、それを満足げに眺めているうちに嫌なことに気がついてしまいました。

このゲームでは自キャラが上下に動くとそれにつれて地平線が上下に動くのですが、地平線が下に動くと敵キャラの影の動きが遅れて地平線の上にはみ出てしまっています。

結論から言うと、cocos2dのscheduleUpdateでプライオリティを適切にしていませんでした。

通常はプライオリティ指定無しのscheduleUpdateメソッドで十分なのですが、他のノードが参照する座標を操作するノードはscheduleUpdateWithPriprity:メソッドを使用してプライオリティを適切に設定してあげる必要があります。
なお、プライオリティとして指定する値が小さいほど先にupdateメソッドが呼ばれ、大きいほど後で呼ばれます。
scheduleUpdateで普通にスケジュールを掛けた場合はプライオリティとして0を指定した場合と同じですので、マイナスの値を指定すれば通常のノードより先、プラスの値を指定すれば後に呼ばれることになります。

このゲームで、はタッチ入力やモーション入力に応じてBGNodeというノードが地平線の座標を更新します。各スプライトは毎フレームupdateメソッド内で地平線の座標を参照し、3D空間内自分の座標を画面上の2Dの座標に変換します。
BGノードが地平線の座標を更新する前にスプライトが自分の座標を更新する場合、参照する地平線の座標は前のフレームの位置になってしまいます。こうなるとスプライトの動きが地平線の動きより1フレーム分遅れてしまいます。
従って、BGNodeのスケジュールのプライオリティを通常のノードより上げ、明示的に先に座標の更新をしてあげる必要があります。
これはすぐに修正できたのですが、問題は影です。
影は相変わらず地平線より遅れて動いています。

このゲームでは複数の半透明の影が重なったときに重複部分の色が濃くならないようにCCRenderTextureを継承したノードに不透明の影のスプライトを書き込み、その後、レンダーテクスチャーのopracityを下げて表示するという方法をとっています。

この方法について詳しくはこちらの記事をご参照下さい。

【偽スペースハリアー】CCRenderTextureで影の重なりが濃くなるのを防ぐ - 夏までにiPhone アプリつくってみっか!

ここが問題でした。レンダーテクスチャーのupdateで影スプライトを描き込むのですが、このupdateが影スプライトのupdateより先に動き、前のフレームのスプライトの座標を参照していました。
そこで、ScheduleUpdateWithPriority:メソッドでプラスのプライオリティ値を指定し、他のノードより明示的に後にupdateを動かしてみました。

その結果、ようやく全てのスプライトが地平線の上下にピッタリ同期して動くようになりました。