ダンジョン探索プログラム - 萌えJava超入門
最終章 超入門まとめ

Sample24_01のメソッド
その二

Sample24_01のrotatePosCellメソッドを説明しましょう。



目次

1. rotatePosCellメソッドのコード


rotatePosCellメソッドは、rotatePosメソッドと、xytoRCメソッドという 2つの privateメソッドと、
Cellクラスの rotateCellメソッドで成り立っています。

rotatePosCellメソッド
  //RotateCell
  public Cell rotatePosCell(int x0, int y0){
    //(x0, y0) is relative position.
    int[] xy = rotatePos(x0, y0, direction);
    int[] RC = xytoRC(posX + xy[0], posY + xy[1]);

    Cell cell = null;
    try {
      cell = new Cell(map3D[floor][RC[0]][RC[1]]);
      return cell.rotateCell(direction);
    }catch(java.lang.ArrayIndexOutOfBoundsException e) {
      return cell;
    }
  }



2. rotatePosメソッド


rotatePosメソッドはコマンドライン版では引数が常に(0, 0)になっているので
あっても無くても構わないメソッドです。
ただ、GUI版で使用しますので一応説明させていただきます。

rotatePosメソッドはstaticメソッドです。
引数には、int x0, int y0, int direction(0~3の北東南西)の
3つを取ります。
座標(x0, y0) を、座標(0, 0)を中心に directionの方向に回転した座標を返します。
回転結果のx座標、y座標 は、int配列にして戻り値とします。

コード自体は簡単なものだ。
rotatePosメソッド
  private static int[] rotatePos(int x0, int y0, int direction) {
    int x;
    int y;

    switch(direction) {
    case NORTH:
      x = x0;
      y = y0;
      break;
    case EAST:
      x = y0;
      y = -x0;
      break;
    case SOUTH:
      x = -x0;
      y = -y0;
      break;
    case WEST:
      x = -y0;
      y = x0;
      break;
    default:
      x = x0;
      y = y0;
    }
    int[] xy = {x, y};
    return xy;
  }



例えば、
座標(-2, 1) を、東に90度回転した座標は、(1, 2)という感じです。
逆に、東を向いて、右に-2 前に1 進んだ座標は、(1, 2)とも言えます。

分かりにくいから
図で説明しよう。
図の上の方が進行方向として、着色部分が自分から見えているとします。
それぞれのマスに、マップのどのマスが当てはまるかは、
進行方向によって変わりますね。
先ほどの例と同じく、相対座標(-2, 1) に注目してみましょう。
自分の位置から見える範囲

座標(-2, 1)を北向きに回転した。
元々北向きのマップだから
変わらないな。
rotatePosメソッド 引数が北(direction == 0)

あ! 変わりました。
マヤ先輩からは(-2, 1)の場所に
(1, 2)が見えてるんですね。
rotatePosメソッド 引数が東(direction == 1)

なるほど。
だいたい分かったわ。
rotatePosメソッド 引数が南(direction == 2)

まあこんな感じだ。
主観でどのマスがどこに見えるか
導くメソッドだ。
rotatePosメソッド 引数が西(direction == 3)



3. xytoRCメソッド


xytoRCメソッドは、ダンジョンのXY座標を配列のインデックスに置き換えるメソッドです。

xytoRCメソッド
  private int[] xytoRC(int x, int y){
    //(x, y) to Row and Columns
    int[] RC = new int[2];
    RC[0]=map3D[floor].length - 1 - y; //Row
    RC[1]=x; //Columns
    return RC;
  }


ダンジョンのXY座標と
配列のインデックスの違いを
確認しよう。
ダンジョンのXY座標

ダンジョンのXY座標は
y軸が降順ですね。
配列のインデックス
配列のインデックスは
縦軸を左、横軸を右に書くのね。
その通り。


下の map配列の宣言では、ダンジョンの地図と配列の位置関係が同じになるよう記載しています。
ダンジョンの地図は一般的に左下が(0, 0)ですから、配列のインデックスと一致しないんです。
座標系が異なるデータって結構多いんですよね。
ちなみに、ディスプレイのドットの座標は左上が(0, 0)で、
数学的なメソッドでは左下が(0, 0)として演算されます。

地図での座標と配列のインデックス




4. Cell#.rotateCellメソッドで壁の位置も回転する


Cellクラスでも紹介した通り、向いている方向で、見える壁の位置も変わっています。
下の図で確認してみて下さい。

自分の位置から見える壁の位置

自分の位置から見える壁の位置 北向き(direction == 0)

自分の位置から見える壁の位置 東向き(direction == 1)

相対座標(-2, 1) に見えるのは、地図の(1, 2)です。
これに加えて東を向いている時は、正面に見える壁も東側の壁になります。

壁の位置を回転させるから
Cell#.rotateCellメソッド
なんですね。
南向きのときは
南の壁が正面かぁ。
自分の位置から見える壁の位置 南向き(direction == 2)

こんな風に
「マップ」と「壁」の両方を
回転させているんだ。
自分の位置から見える壁の位置 西向き(direction == 3)



5. rotatePosCellメソッド


rotatePosCellメソッドのコードを改めて確認してみましょう。

rotatePosCellメソッド
  //RotateCell
  public Cell rotatePosCell(int x0, int y0){
    //(x0, y0) is relative position.
    int[] xy = rotatePos(x0, y0, direction); // ← 1
    int[] RC = xytoRC(posX + xy[0], posY + xy[1]); // ← 2

    Cell cell = null;
    try {
      cell = new Cell(map3D[floor][RC[0]][RC[1]]);
      return cell.rotateCell(direction); // ← 3
    }catch(java.lang.ArrayIndexOutOfBoundsException e) {
      return cell;
    }
  }

  1. rotatePosメソッドでマスの見える位置を算出
  2. xytoRCメソッドで配列のインデックスに変換
  3. Cell#.rotateCellメソッドで壁の位置を回転
回転した値をCellクラスのインスタンスにして戻り値にしています。



お疲れ様でした。



© 2019 awasekagami