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

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

【TravelShooting JP】衛星オブジェクトを持つボスのモーションの作り方

夏までに完成しなかったTravelShooting JPに新しいボスを追加しました。
スペハリで言うところのシュラのようにボス本体の回りに衛星のように別のオブジェクトが回るタイプのボスです。

動画で見るとわかりやすいと思います。

なお、スプライトのテクスチャーは他のボスの物を借りているので本番では変わります。

ボス本体の動きとボスの周囲のオブジェクトの動きのアルゴリズムは全く同じで、X方向、Y方向、Z方向をSin関数で振動させ、それを合成しています。

これはボス本体の方ですが、X_CENTER, Y_CENTER, Z_CENTERという固定点を中心にX_AMPLITUDE, Y_AMPLITUDE, Z_AMPLITUDEの振幅で振動します。
X_PHASE, Y_PHASEは0なので中心位置からのスタートとなります。
Z_PHASEはπ/2なのでcosineと一緒で一番値の大きい位置、このゲームでは一番奥からのスタートになります。
Y方向の振動はY_TIME_FACTORで振動数を調整し、この値の設定により回転軸の傾きがずれて行くようにしています。

#define X_CENTER 0.0
#define Y_CENTER 500.0
#define Z_CENTER 600.0
#define X_AMPLITUDE 1500.0
#define Y_AMPLITUDE 300.0
#define Z_AMPLITUDE 250.0
#define X_PHASE 0.0
#define Y_PHASE 0.0
#define Z_PHASE M_PI_2
#define Y_TIME_FACTOR 1.5

        _time += TIME_INCREMENT;
        pos3D.position.x = sin(_time+X_PHASE) * X_AMPLITUDE + X_CENTER;
        pos3D.position.y = sin(_time * Y_TIME_FACTOR + Y_PHASE) * Y_AMPLITUDE + Y_CENTER;
        pos3D.z = sin(_time+Z_PHASE) * Z_AMPLITUDE + Z_CENTER;


周囲を回るオブジェクトは_initialTimeというインスタンス毎に「2π/オブジェクト数」ずつ位相をずらし値を加え、円周上に均等に分散させます。また、固定点ではなく、ボス本体の位置を毎フレーム受け取り、それを中心に自分の位置を計算します。

    myPos3D.position.x = sin(time + _initialTime + X_PHASE) * X_AMPLITUDE + pos3D.position.x;
    myPos3D.position.y = sin(time * Y_TIME_FACTOR +_initialTime + Y_PHASE) * Y_AMPLITUDE + pos3D.position.y;
    myPos3D.z = sin(time+_initialTime + Z_PHASE) * Z_AMPLITUDE + pos3D.z;

なお、このゲームでは周囲のオブジェクトではcocos2dのscheduleUpdateを動かさず、ボス本体のupdateメソッドから周囲の各オブジェクトの位置更新メソッドを呼び出すようにしています。
scheduleUpdateでバラバラにupdateされている場合は、恐らく本体のupdateの前にupdateされたオブジェクトと、後にupdateされたオブジェクトで座標が1フレーム分ずれると思います。
cocos2dのノードツリーの親子の関係であれば問題ないのかもしれませんが、このゲームでは1つのノードに全てのスプライトをぶら下げていて、zオーダーも毎フレーム入れ替えているので、どういう順番でupdateが呼ばれるのか良くわからないのでそのようにしています。
https://itunes.apple.com/jp/app/travelshooting-jp-toraberushutingu/id917570972?mt=8&uo=4&at=10laCt