<戻る

ソフトウェア編
その6 指定の場所へ移動するアルゴリズム


 テクニクビートでは位置の移動が決め手となります。ここでは、8方向レバーである位置から別の位置へ最短に移動するアルゴリズムを実装してみます。動きの最適化については「その5」ですでに述べております。

 次のようなステージを想定します。

 升目の大きさはv、マスの数がnであるステージです。キャラクタは境界線の交点上にぴったり止まるようにします。左下を(0,0)としておきます。このようにしたのは、設定がしやすいためです。「次は(15,12)」のような指定をしたいわけですね。

 vの大きさを変えると、ステージの大きさを調節することが出来ます。ある程度細かいnで分割しておいて、あとはvでキャラクタ(ニッティ)の移動時間を調節する。そういう感じになるでしょうか。



@ 2つの座標間を移動するためにボタンを押す時間

 キャラクタは最初の位置から連続的に座標を変えていきます。キャラクタがいる位置を(x1, y1)とし、次に動く予定の位置を(x2, y2)とします。(x1, y1)から最初に斜めに移動して、x2もしくはy2に座標があった時点で、縦横方向の移動に切り替えます。

 まず、左右方向の差をとります。X = x1-x2としてこれが正だった場合は左方向への移動、負の時は右方向への移動になります。同様にY = y1-y2が正なら下方向、負なら上方向の移動となります。次に、XとYの絶対値の差Z = |X| - |Y|を計算します。Zが正なら|Y|分だけ斜めに移動した後|Z|分だけ左右方向の移動があります。Zが負なら|X|分だけ斜めに移動した後|Z|分上下の移動があります。

 文字で書くと何が何やらですので、例題(テスト)で考えます。

 (4,10)から(8,2)へ移動するとします。最初に左右方向の差をとります。X = 4 - 8 = -4。負なので右方向の移動であることがわかります(BTN_RIGHTの決定)。上下方向の差を見ます。Y = 10 - 2 = 8。正なので下方向の移動となります(BTN_DOWNの決定)。次にXとYの絶対値の差を算出。Z = |-4| - |8| = -4。Zが負なので|X|=4分だけ右下(斜め方向)を押した後、|Z|=4だけ下方向がさらに押されます。

 斜め方向の押す時間は1.414(ルート2)だけ伸ばす必要があります。上の例の場合、

  右: 4 * 1.414 * v = 5.656v
  下: (4 * 1.414 + 4) * v = 9.656v

だけボタンを押す事になります。この計算を行うCalcNextTimeメンバ関数をCCalcPositionクラス内に定義します。

CCalcPosition.cpp
// 次の位置に移動するための時間を計算
void CCalcPosition::CalcNextTime(
int x2, int y2,
DWORD &LR, DWORD &UD,
double &LRTime, double &UDTime
)
{
   // ボタンフラグを初期化
   LR = UD = BTN_NO;

   // 押すボタンを決定
   int X = m_x1 - x2;
   int Y = m_y1 - y2;

   LR = (X>=0)? BTN_LEFT : BTN_RIGHT;
   UD = (Y>=0)? BTN_DOWN : BTN_UP;

   // 斜め移動時間の算出
   int Z = (int)(fabs(X) - fabs(Y));
   double CrossTime = sqrt(2) * ( (Z>=0)?fabs(Y):fabs(X));

   // 縦横移動時間の算出
   int XYTime = (int)fabs(Z);

   // 左右、上下ボタンの時間を算出
   LRTime = UDTime = CrossTime * m_dUnitTime;
   if(Z>=0)
      // 左右方向が多い
      LRTime += XYTime * m_dUnitTime;
   else
      // 上下方向が多い
      UDTime += XYTime * m_dUnitTime;

   // キャラクタの位置を更新
   m_x1 = x2;
   m_y1 = y2;
}

 実はこれだけです(笑)。第3引数以降に結果を一気に返します。最初に各ボタンを押さない状況(BTN_NO)に初期化してから、後はアルゴリズムに従って静々と書いただけです。m_x1、m_y1は現在のキャラクタの位置を表すメンバ変数です。またm_UnitTime1マス分進むのに必要な時間をミリ秒で表します。

 今回の章はアルゴリズムが分かっていただけに簡単でした。最適化は必要ありません。このクラスは以後ツールとして使用することになります。



A これでついに連続データを作成できます!

 ここまでで作成したクラスを組み合わせると、連続したボタン情報を作成してコントローラに登録し、実際にPS2のボタンを自動的に押すことが出来ます。次の章ではがらっと趣向を変えまして、GUIを実装していきましょう。