第7回.連載でJavaゲーム作っちゃいます弐
Masa: だー走った。走った。
ほるえ: どうしたんですか。マラソンかトライアスロンにでも出るんですか?
Masa: んなわけあるか。バグ取れない時は、ちょっとドライブに出かけるのが一番なんだよ、気分転換に。
ほるえ: ま、いいですけど。普通そういうのって現実逃避って言いませんか?
Masa: むー。そうともいうな。

「相手キャラクタの移動を追加しました」

サンプルが表示されない場合は、Java環境がインストールされていない可能性があります。
SUNホームページから、J2SE v 1.4.2_07 JRE以上のバージョンをダウンロードしてください。


←キャラクタグラフィックは、こちらからお借りしています。

デバックソフトの動作

 【相手キャラクタ】
 1)街、見方、敵を目指して移動します。
 2)全キャラクタが移動し終わると自分キャラクタの移動に移ります。

 【自分キャラクタ】
 1)中央のマップの右側に各キャラのステータス表示をつけました。この表示部分をクリックすることで各キャラをマップ画面の中央に持ってくることが出来ます。
 2)中央マップに表示された敵キャラについては、左側にステータス表示が出ます。
 3)選択したキャラの上で右クリックするとポップアップメニューが出ます。
 4)’MOVE’を選択しすると、キャラ周囲の移動可能部分に’□’マークが出ます。
 5)移動したいところをクリックすると、移動します。


Masa: なんか、バグでまくって、全然進んでない。本当は、移動する前に移動先の評価を入れるべきなんだけと、まだまた、出来てないっていうか、結構難しいな。
ほるえ: なんだ、いきなりギブアップ宣言ですか・・・ふっ(-_-)。
Masa: (むかっ)そんなわけあるかっ。今週は、ここまでってことで来週をみてろよっ
ほるえ: ふーん。(扱いやすくて助かる)で、今週はどこを説明するんですか?
Masa: あぁ、今回は、キャラ移動に使っているルーチンの説明をします。

「キャラ移動について」

移動領域の選択との違い
 連載のはじめに移動領域を決めるのに、深さ方向の探索を行って場所を探す方法を説明しました(図の白□)。今回は、その中の指定した移動先までの移動路を選択する(図の赤□)ルーチンです。

動作:
 移動領域を決定するルーチンで決定した配列tansaku[][]中の指定した一点へ移動するルーチンです。
前提条件:
 深さ方向を調査するルーチンで、tansaku[][]配列が作成されていること。

手順
 1.目標地点が配列内にあることを確認。
 2.上下左右のこまを調べて、
   調べたコマでの移動量残量=現時点の移動量残量+現時点の移動コスト
   ならば、移動する。
 3.移動コストが0のポイント(つまり元の位置)を探し出すまで、処理を続けます。


ソース解説(詳細)


public void pathserch( int OBV, int OBH,int VP, int HP,int ido) {
//VP,HP:目標地点,OBV,OBH:元のポイント,ido:移動量

 int hai,cost=100;//配列数
 int Lcost=100,Rcost=100,Ucost=100,Dcost=100;
 int ch_hai=pathNo(OBV,OBH);

 hai= pathNo(VP,HP);

 pathhai=0;

 path[pathhai][0] = tansaku[hai][0]; path[pathhai][1] = tansaku[hai][1];
 path[pathhai][2] = tansaku[hai][2]; path[pathhai][3] = tansaku[hai][3];
 path[pathhai][4] = tansaku[hai][4];
 pathhai++;

 while((VP!=OBV)||(HP!=OBH)){

  hai= pathNo(VP,HP);if(hai!=-1){cost=tansaku[hai][2];}
  int haiL= pathNo(VP-1,HP);
  if(haiL!=-1){Lcost=tansaku[haiL][2];}
  int haiR= pathNo(VP+1,HP);
  if(haiR!=-1){Rcost=tansaku[haiR][2];}
  int haiU= pathNo(VP,HP-1);
  if(haiU!=-1){Ucost=tansaku[haiU][2];}
  int haiD= pathNo(VP,HP+1);
  if(haiD!=-1){Dcost=tansaku[haiD][2];}

  int map_cost=map[VP][HP].GetCost();

  if ((haiL!=-1)&(Lcost == cost + map_cost)) {
   VP--;
  }else if ((haiR !=-1)&(Rcost ==cost + map_cost)) {
   VP++;
  }else if((haiU !=-1)&(Ucost == cost + map_cost)) {
   HP--;
  }else if((haiD !=-1)&(Dcost == cost + map_cost)) {
   HP++;
  }

 int debag=pathNo(VP,HP);

 path[pathhai][0] = tansaku[debag][0];
 path[pathhai][1] = tansaku[debag][1];
 path[pathhai][2] = tansaku[debag][2];
 path[pathhai][3] = tansaku[debag][3];
 path[pathhai][4] = tansaku[debag][4];
 pathhai++;
 }
 draw_path_flag = true;

}
VP,HP:目標地点
OBV,OBH:元の位置
ido:移動量


VP,HPの配列番号を読み込みます。



tansaku[][0],tansaku[][1]:座標
tansaku[][2]:移動量残量
tansaku[][3]:そこまでの移動コスト


移動コストが0のポイント(つまり今の位置)を探し出すまで処理を続けます。













上のマスが配列に入っているかを確認
移動先の残量
=現時点移動量残量+場所の移動コスト
ならば、そのポイントを次の移動点にする。
同様に、下のマス確認
同様に、左のマス確認
同様に、右のマス確認





移動路を配列path[][]に保存

public int pathNo(int VP, int HP) {


int hairetu=-1;

for (int i = 0; i < tanpc; i++) {
if ((tansaku[i][0]==VP)&(tansaku[i][1]==HP)){hairetu = i;}
}
return hairetu;
}
tansaku配列の中からVP,HPと等しい配列番号をピックアップし配列数を返す



更新記録
05.10.01 while()の条件の変更。path[][4]を追加。デバック性を高めるために変数をいろいろ追加


Masa: このルーチンのいいところは、tansaku[][]と、移動元、移動先のポイントがあればいいってこと。後は、移動先の選択ルーチンを強化していけばOKだ。
ほるえ: それが難しいんですよね。
Masa: そうなんだよなー。
今回は、ほんとにアップできるかどうかってところでした。やっぱ、コメント&フロー(UML?)は必須ですね。

Copyright (C) 錬金術師Masa
新規:2005年09月04日
更新:2005年10月01日