地形判定させてみる


●操作分岐をしっかりさせる

地形判定の前に、歩行やジャンプの部分で操作分岐が
かなり複雑になってしまったので、ここで一度見直し
状態変更の管理をきちんをするようにしてみた。
//行動モード別に行動
procedure Tman.actMove(JX,JY,B1,B2:int);
begin
 //行動変更チェック
 case act of
  actStop:begin
   if JX <> 0 then actChange(actwalk);
   if B1 = 1 then actChange(actjump);
   end;
  actWalk:begin
   if JX = 0 then actChange(actstop);
   if B1 = 1 then actChange(actjump);
   end;
  end;

 //移動判定
 case act of
  actStop:stopMove(JX,JY,B1,B2); //今は必要ない入力も
  actWalk:WalkMove(JX,JY,B1,B2); //一応取り込んでおく。
  actJump:JumpMove(JX,JY,B1,B2); //追加などの拡張に対応するため。
  end;
 //マップとの当たり判定
 MapChk;
 //当たり判定後にアクション更新
 actAnimation;
end;

//アクション変化
procedure Tman.actChange(chg:Tact);
begin
 //アニメーションリセット
 anmCnt := 0;
 anmNum := 0;
 case chg of
  actstop:begin
   DY := 0;
   act := actstop;
   end;
  actwalk:begin
   act := actwalk;
   end;
  actjump:begin
   act := actJump;
   DY := -7;
   end;
  end;
end;
最初の//行動変更チェックの部分で、ボタン入力があった場合の
状態変更をしている。これをactChange関数によって場合分けし
操作入力後の状態で次の//移動判定を行うようにしている。


●マップユニットの読み込みと表示

簡単な説明だけ。
まずはパラメーターユニットでマップ形式の宣言。
TBord = array[0..BORDMAX_X+1,0..BORDMAX_Y+1] of int;
これによりusesにパラメーターユニットを宣言したユニット同士で
データー交換できるようになる。

そしてマップ読み出し専用の新たなユニットを作成する。
内容は、以前の「設定データーの読み書きをしてみる」のものを利用。
データー受け渡しは、上記TBord形式の変数を使用する。

表示は、もう一つ以前の「BITBLTを活用してみる」のものを利用。
番号指定でブロックを表示できるようにしておく。

●地形判定

地形との当たり判定は、横方向と縦方向で分けておく。
そして必ず縦と横は同じ位置で判定させないようにしておく。
これは斜め方向からのぶつかりで変な方向に修正しないために必要。

が、四箇所だけでは判定としてイマイチ。

ゲーム内容にもよるが、最低でも六ヶ所での判定は必要になる。

そしてブロック端までキャラを落ちないようにするには
下の落下判定を二ヶ所に広げればいい。
//マップとの当たり判定
procedure Tman.MapChk;
begin
//右上壁判定
 if PBord[((X+16+8)div BORDSIZE),((Y+6) div BORDSIZE)] <> 0 then
 begin
 RX := RX - 1.5;
 X := Trunc(RX);
 DX := 0;
 end;
//右下壁判定
 if PBord[((X+16+8)div BORDSIZE),((Y+28) div BORDSIZE)] <> 0 then
 begin
 RX := RX - 1.5;
 X := Trunc(RX);
 DX := 0;
 end;
//左上壁判定
 if PBord[((X+16-8) div BORDSIZE),((Y+6) div BORDSIZE)] <> 0 then
 begin
 RX := RX + 1.5;
 X := Trunc(RX);
 DX := 0;
 end;
//左下壁判定
 if PBord[((X+16-8) div BORDSIZE),((Y+28) div BORDSIZE)] <> 0 then
 begin
 RX := RX + 1.5;
 X := Trunc(RX);
 DX := 0;
 end;
//ジャンプ中に
 if act = actjump then
 begin
 //頭上にブロックで上昇停止
  if PBord[((X+16)div BORDSIZE),((Y+4) div BORDSIZE)] <> 0 then
  begin
  RY := ((Y+32) div BORDSIZE)*BORDSIZE-4;
  Y := Trunc(RY);
  DY := 0;
  end;
 //足元にブロックがあれば着地(二ヶ所チェック)
  if (PBord[((X+16+4)div BORDSIZE),((Y+32) div BORDSIZE)] <> 0) or
   (PBord[((X+16-4)div BORDSIZE),((Y+32) div BORDSIZE)] <> 0) then
  begin
  RY := (Y div BORDSIZE)*BORDSIZE;
  Y := Trunc(RY);
  actChange(actstop);
  end;
 end;
//歩行中か停止中に
//足元にブロックがなければ落下(二ヶ所チェック)
 if (act = actwalk) or (act = actstop) then //消える床があった場合に備え、停止中でも判定
 begin
  if (PBord[((X+16+4)div BORDSIZE),((Y+32) div BORDSIZE)] = 0) and
   (PBord[((X+16-4)div BORDSIZE),((Y+32) div BORDSIZE)] = 0) then
  begin
  RY := (Y div BORDSIZE)*BORDSIZE;
  Y := Trunc(RY);
  actChange(actJump);
  DY := 0;
  DX := DX /4; //落下時に横移動を落とす
  end;
 end;
end;
実際には上判定はジャンプ中のみで、落下判定は歩行か停止中のみでしている。

●サンプル

以上の経過&実行形式をまとめたものがこちら。

GameBone2006D.lzh

ご利用はご勝手に。ただし責任は各自で。
GameBone2006D.exeを実行すれば表示。
DelphiがあればGameBone2006D.dprをダブルクリックすれば
プログラムの内容がそのまま表示されるはず。

 戻る