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

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

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

【TravelShooting JP】スペハリ風移動アルゴリズムを試すも不採用に

TravelShooting JP スペースハリアー cocos2d

セガ3D復刻アーカイブスを買って以来スペハリをやりまくっていますが、ハリアーの移動に若干の違和感を感じました。
円を描くように操作しているつもりなのですが、ハリアーは菱形に移動してしまいます。
試しにプレステ3版を起動して試しましたが、結果は同じでした。

よーく動きを観察してみると、どうやらハリアー君は自分のいる位置からコントローラーのスティックが示す位置へ最短距離で移動するのではなく、まず斜め45度に移動し、Y座標が合致した場合はそこからから水平、X座標が合致した場合はそこから垂直に移動しているようです。
そして、斜め45度に移動しているときは上下左右に動いているときよりスピードが速くなります。

一方、TravelShooting JPのキャラクターは自分のいる位置からタッチ操作やジャイロ操作で示す位置へ最短距離で移動します。また、移動速度は方向に関わらず一定になるよう制御しています。

図で示すとこのような違いとなります。
f:id:takujidev:20141227133439j:plain
キャラクターが赤い点(コントロール操作で入力した座標)に向かって移動しようとするとき、スペースハリアーは赤い線で示した動き、TravelShooting JPは青い線で示した動きとなります。

TravelShooting JPのキャラクター移動プログラムはこのように実装しています。

    // 移動ベクトル = タッチ位置 - プレイヤースプライトの位置
    CGPoint worldPosition = [self.parent convertToWorldSpace:self.position];

    CGPoint moveVector = ccpSub(touchPosition, worldPosition);

    // 移動ベクトルの大きさをSPEED_LIMITに制限する
    if (ccpLength(moveVector) > SPEED_LIMIT) {
        moveVector = ccpMult(ccpNormalize(moveVector), SPEED_LIMIT);
    }

重要なのは移動ベクトルの大きさをSPEED_LIMITに制限しているところです。
cocos2dというゲーム用フレームワークが提供するベクトル演算用関数を使用しているため見た目はスッキリしていますが、ベクトルの長さを求める処理やベクトルの長さを1にするノーマライズの処理では内部的に平方根の計算が実行されています。
平方根の計算は相当重いらしいので、恐らくスペースハリアーのアーケード版がリリースされた約30年前は避けるべき処理だったのでしょう。

試しにスペハリで実装されているであろう処理をTraveShooting JPに組み込んでみました。
移動速度の制限をしている部分の行数は先ほどより増えていますが、比較と代入だけの非常に軽い処理で実装されています。

    // 移動ベクトル = タッチ位置 - プレイヤースプライトの位置
    CGPoint worldPosition = [self.parent convertToWorldSpace:self.position];

    CGPoint moveVector = ccpSub(touchPosition, worldPosition);

    // 移動ベクトルの大きさをSPEED_LIMITに制限する。ただしx, y独立して制御
    if (moveVector.x > SPEED_LIMIT) {
        moveVector.x = SPEED_LIMIT;
    } else if (moveVector.x < -SPEED_LIMIT) {
        moveVector.x = -SPEED_LIMIT;
    }
    
    if (moveVector.y > SPEED_LIMIT) {
        moveVector.y = SPEED_LIMIT;
    } else if (moveVector.y < -SPEED_LIMIT) {
        moveVector.y = -SPEED_LIMIT;
    }

この処理を組み込んだTravelShooting JPで円を描くように操作すると見事にスペハリのように菱形に動くようになりました。

しかし、ユーザーからしてみるとこれはかえって操作しにくくなるだけなので、残念ながら不採用となりました。