Home>戻る

〜第14章 イベント(キャラクター)を動かす〜


イベント(キャラクター)を動かしてみましょう。
キャラを動かすには、主人公と同じく座標、速度、方向等の情報が必要になるので、 イベントクラスの情報を増やしましょう。
class Event{
	int no;//イベントNO
	String filename;//スクリプト名
	int gra;//グラフィックス
	boolean move_flag;//通過可能か
	int type_of_move;//移動タイプ(0=移動しない、1=移動する)
	int type_of_event;//イベントタイプ(0=触れた時に起動、1=決定した時に起動)
	float speed;//速度
	int x,y;//座標
	float px,py;//P座標
	boolean moving_flag;//移動中か(yes=true)
	int moving_dir;//移動中の方向(上=0,下=1,左=2,右=3)
	float sum_move_length;//移動距離(32ドットずつ)(休憩用にも使う)

	Event(int no){
		this.no = no;
	}
}
キャラを描画する時は、今まではイベントマップの場所(event_data[x][y])に描画させてきましたが、 今回からは主人公と同様にキャラごとの座標(Event.px,Event.py)に描画させます。

そして、イベントを動かす時に大事なのが、イベントの衝突の回避です。
キャラが重なると、見栄えが不自然になり、 話すコマンドをした時にどのキャラが会話をしているのか分からなくなります。

そこでイベントのある場所には移動しないようにすればいいのですが、困るのが以下のような時です。
1.キャラA(16,14)が右に動こうとする。右には障害物が何もないので動き始める。
2.キャラB(18,14)が左に動こうとする。左には障害物が何もないので動き始める。
3.キャラAとBが(17,14)で重なる。

これを回避するには、キャラが移動し始める直前に移動先の場所に「今からそこに移動します。邪魔しないでね。」 というように情報を記録してやります。
そして他のキャラはその情報の場所には移動できなくなるようにします。主人公も。
そして移動先に移動した場合に、位置情報を更新してやります。

<具体的な手順>
1.キャラA(16,14)が右に動き出そうとする。右には障害物が何もないので(17,14)の場所に99という情報を記録する。
2.キャラB(18,14)が左に動き出そうとする。左には障害物は何もないが、99という情報があるので移動を諦める。
3.キャラAが(17,14)に到着する。前の(16,14)の場所のイベントNOを消し、今の(17,14)の99という値をイベントNOに更新させる。

以上です。主人公の移動のところも、同様な処理をしてやります。

ところで、移動部分の処理で、方向によってswitch〜caseで場合分けするのが面倒だと思いませんか?
そこでテーブルを用いて簡略化してみましょう。
   //方向テーブル(上下左右の順)
   int dir_x[] = {0,0,-1,+1};
   int dir_y[] = {-1,+1,0,0};
このようにテーブルを宣言します。
使い方は、
	next_x = My.x + dir_x[My.moving_dir];
	next_y = My.y + dir_y[My.moving_dir];
こういう感じです。
この二行で上下左右分の移動処理がまとめて行えます。
もし、主人公が左(My.moving_dir=2)を向いていれば、
	next_x = My.x + (-1);
	next_y = My.y + 0;
このようになってくれます。


<移動開始部分のプログラム>
    //現在、移動中でないなら移動開始
    if(!eventtbl[i].moving_flag){
       //ランダムに方向を決める
       ran=rand.nextInt();
       if(ran<0){ran=-ran;}
       dir = ran%4;//方向

       //目的の方向
       next_x = eventtbl[i].x + dir_x[dir];
       next_y = eventtbl[i].y + dir_y[dir];

       //System.out.println("["+i+"]next("+next_x+","+next_y+")");

       //-----その方向は通行可能か?-----

       //領域外
       if(next_x < 0 || next_y >= map_width || 
          next_y < 0 || next_y >= map_height){
           //通行不可
           ismove = false;
        }
       //障害物
       else if(!celltbl[ map_data[next_x][next_y] ].move_flag){
           //通行不可
           ismove = false;
       }
       //イベント
       else if(event_data[next_x][next_y] >= 1){
           //通行不可
           ismove = false;
       }
       //主人公の位置
       else if(next_x == My.x && next_y == My.y){
           //通行不可
           ismove = false;
       }
       //それ以外
       else{
           //通行可
           ismove = true;

           //移動開始
           eventtbl[i].sum_move_length = 0.0f;
           eventtbl[i].moving_dir = dir;

          //移動先イベントデータにKAKUHO_NOを入れる
          event_data[next_x][next_y] = KAKUHO_NO;
       }

       eventtbl[i].moving_flag = ismove;
    }
    //移動中の時
    else{
       //その方向に向かって移動
       CharaMoving( eventtbl[i] );
    }
<移動後のプログラム>
   //キャラ移動
   void CharaMoving(Event event){
      int ran;

      //その方向に移動
      event.px += FrameTime * event.speed * dir_x[event.moving_dir];
      event.py += FrameTime * event.speed * dir_y[event.moving_dir];

      //総合距離加算
      event.sum_move_length += FrameTime * event.speed;

      //一定距離動いたか
      if(event.sum_move_length >= (float)CHIP_SIZE){
         //前の位置のイベントを消す
         event_data[event.x][event.y] = 0;

         //ピッタリの位置にする
         event.x += dir_x[event.moving_dir];
         event.y += dir_y[event.moving_dir];
         event.px = event.x*CHIP_SIZE;
         event.py = event.y*CHIP_SIZE;
         event.moving_flag = false;
         event_data[event.x][event.y] = event.no;

         //小休止(ランダム1秒〜3秒)
         ran=rand.nextInt();
         if(ran<0){ran=-ran;}

         event.sum_move_length = -(ran%3+1);
      }
   }
<プログラム公開>
Rpg14.java

プロジェクト一式ダウンロード(データ含む)