レベル4

目次

レベル-1
入門以前の知識の紹介。
レベル0
コンポーネントの使用。
レベル1
とことんShowMessage。
レベル2
じゃんけん。
レベル3
キャラの表示と十字移動。
レベル4
敵をつくってみよう。
レベル5
DelphiXを利用してみよう。
発展
発展的入門知識(矛盾?)。
ショートカットキー
ショートカットキーの紹介。
テクニック
さまざまなテクニックの紹介。

今回は敵をつくり当たり判定を取ります。

敵を作る

このゲームは一応「避けゲー」にする予定なので敵を作らなければなりません。敵をつくりましょう。

まず、zikiを作った時と同じように「teki」という名のTImageを用意して画像を読み込んでください。とりあえずこれで敵が表示されました。

とりあえず此処までは楽勝ですが、ここからちょっと難しいお話になります。当たり判定のとり方は結構頭を使うのでがんばってください。

当たり判定をとる

zikiとtekiが当たったとき、「当たったよ」といって終了するプログラムを書いてみましょう。

今回使うのは四角形同士の当たり判定です。四角形同士の当り判定はたぶん一番使われる当り判定だと思います(2Dでは)。軽いし使いやすいし。マスターしましょう。

四角形同士の当たり判定をとる時には、中心間の距離を考えます。二つの四角形が四角A→■□←四角B

こんな状態になった時、Aの中心のX座標とBの中心のX座標間はAの横幅の半分+Bの横幅の半分以下になっています。これをX座標とY座標の両方で行えば当たり判定ができます。

Topは上端の座標なので、中心を出す際にはHeightの半分を足さなければならないことに注意です。実装してみましょう。ちなみに「Abs」は絶対値を返す関数です。

///andを使用しないのは軽量化の為です。
  with teki do
  begin
    if (Abs((Ziki.Left + Ziki.Width / 2) - (Left + Width / 2)  ) <=  (Ziki.Width + Width) / 2) then
      if (Abs((Ziki.Top + Ziki.Height / 2) - (Top + height / 2)  ) <=  (Ziki.Height + Height) / 2) then
      begin
        ShowMessage('あたったよ〜');
        Form1.Close;///Form1.Closeでプログラムが終了します。
      end;
  end;

これで、全く動かない敵にあたるとプログラムが終了するようになりました。

敵を動かす

正直敵が動かないとゲームとして成り立たないので敵を動かしましょう。

どのような動きをつけるかは貴方が自由に選んで結構ですが、とりあえずZikiのDxとDyにあたるものが必要なので、

{$R *.dfm}
var
  Dx,Dy:Extended;
  TDx,TDy:Extended;
  
procedure TForm1.Timer1Timer(Sender: TObject);
begin

  ///Ziki動かす
  with ziki do
  begin
  
    if GetKeyState(VK_Up) < 0    then Dy:=Dy - 5;
    if GetKeyState(VK_Down) < 0  then Dy:=Dy + 5;
    if GetKeyState(VK_Left) < 0  then Dx:=Dx - 5;
    if GetKeyState(VK_Right) < 0 then Dx:=Dx + 5;

    if (top + Dy < 0) and (Dy < 0) then Dy:=0;
    if (top + Dy > form1.height - height) and (Dy > 0) then Dy:=0;
    if (left + Dx < 0) and (Dx < 0) then Dx:=0;
    if (left + Dx > form1.Width - Width) and (Dx > 0) then Dx:=0;
    
  end;
  
  //Teki動かす
  with Teki do
  begin

    (*****ここに敵の動きを書く******)

    if (top + TDy < 0) and (TDy < 0) then TDy:=0;
    if (top + TDy > form1.height - height) and (TDy > 0) then TDy:=0;
    if (left + TDx < 0) and (TDx < 0) then TDx:=0;
    if (left + TDx > form1.Width - Width) and (TDx > 0) then TDx:=0;
    
  end;
  
  //Ziki予測代入
  with Ziki do
  begin
    Top :=Top + Trunc(Dy);
    Left:=Left+ Trunc(Dx);

    Dx:=Frac(Dx);
    Dy:=Frac(Dy);
  end;
  
  //Teki予測代入
  with Teki do
  begin
    Top :=Top + Trunc(TDy);
    Left:=Left+ Trunc(TDx);
    
    TDx:=Frac(TDx);
    TDy:=Frac(TDy);
  end;
  
end;

とだけ書きましょう。いやあ、with文を使ってるとほぼ丸コピーですんじゃうんで楽ですねえ。

Zikiの予測の代入の位置が結構変わってますが、これは最後にやった方がバグが少なくなるし便利です。

敵の動きは自由につけちゃっていいです。といってもいきなりそんなこと言われると困っちゃう人もいるみたいなので、ある程度の敵の動きの種類を此処に書いておきます。

ひたすら右に動くだけ

TDx:=TDx + 5とでも書いとけばOKです。

右端に当たってとまる、悲しい動き。

めちゃくちゃに動く

TDx:=TDx + Random(5)-2;
TDy:=TDy + Random(5)-2;

とんでもない動きをします。これはこれで楽しいかも?Random(5)-2というのに注意。

Zikiと正反対の動きをする

TDx:=-Ziki.Dx;
TDy:=-Ziki.Dy;

なんかゼ●ダの伝説夢をみる島でこんな敵キャラいたよね。

画面を左右に移動する

ウィンドウのの右端に当たるまで右移動、当たったら左移動、今度は左端に当たったら右移動…といった感じで。

これはほかのと違って「ウィンドウを飛び出さない判定」のところもちょっと変えます。ちょっと難しめ?

  with Teki do
  begin

    ///TagプロパティについてはLevel0を読めば良いと思うよ。
    ///此処ではTeki.Tagを「移動してる向き」として使ってます。0未満は左で0以上は右。
    if Tag < 0 then TDx:=Dx - 5
      else TDx:=Dx + 5;

    if (top + TDy < 0) and (TDy < 0) then TDy:=0;
    if (top + TDy > form1.height - height) and (TDy > 0) then TDy:=0;
    if (left + TDx < 0) and (TDx < 0) then
    begin
      TDx:=0;
      Tag:=1;///右向きにする
    end;
    if (left + TDx > form1.Width - Width) and (TDx > 0) then
    begin
      TDx:=0;
      Tag:=-1;///左向きにする
    end;
    
  end;

上下左右試してみるとおもしろいかも。

三角関数を使った動きをする

こっから先はちょっと難しいお話です。三角関数がわかってる人向けに話すので、特に説明もしません。わからなかったら飛ばしてOKです。

波のような動きをさせる

予めVar a:Extended;としておいてくださいな。

a:=a + 0.3;
TDy:=TDy + Sin(a) * 100; //100は波の幅、
TDx:=TDx + 3;///ヨコに動かす

Zikiを追跡させる or 逃げさせる

プログラム5行目くらいにuses Windows, Messages,--中略--Forms,Dialogs,Math;と追加しておいてください。

これも予めVar a:Extended;としておいてくださいな。

a:=ArcTan2(Top - Ziki.Top,Left - Ziki.Left);
  TDy:=TDy + Sin(a) * 5;
  TDx:=TDx + Cos(a) * 5

TDy + Sin(a) * 5の符号を変えれば向きがかわるよ。