もぐら叩きを作ろう その4

いよいよ、大詰めです。最後に TBaseMog, THole クラスのインスタンス生成の役目を持たせるクラス TGameManager クラスの作成をします。この TGameManager クラスは、主に以下の役目を負います。

  1. TBaseMog クラスのインスタンスの生成と破棄
  2. THole クラスのインスタンスの生成と破棄
  3. 制限時間の表示と設定
  4. 獲得したスコアの表示と設定
  5. ゲームの進行(メインループ、もぐらの表示、制限時間、スコアの更新)
  6. マウスカーソルともぐらの当たり判定
  7. ゲームの初期化

Unit2 に以下のコードをタイプしてください。

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls;

const
  MAX_HOLES = 5; // モグラが出現する穴は全部で 5 つあります。

type

......................................................

  TGameManager = class(TObject)
  private
    fHoles: array[0..MAX_HOLES-1] of THole;
    fNormalMog: TBaseMog;
    fYellowMog: TBaseMog;
    fGameTime: Integer;     // 制限時間
    fGameScore: Integer;    // 獲得したスコア
  public
    constructor Create;
    destructor Destroy; override;

    // ハンマーがモグラに当たったかどうか
    procedure CheckMogState(X, Y: Integer);
    procedure GameLoop; // メインループ
    procedure GameOver;
    procedure GameInit; // ゲームの初期化
    procedure DecGameTime;
    function GetKindOfMog: TBaseMog;
    procedure UpdateGameScore;
    procedure UpdateGameTime;

    // 叩かれていないモグラを表示
    procedure ShowLiveMog(HoleNumber: Integer; Mog: TBaseMog);
    // 叩かれたモグラを表示
    procedure ShowDeadMog(HoleNumber: Integer; Mog: TBaseMog);
  end;
  
..................................................

{ TGameManager }

procedure TGameManager.CheckMogState(X, Y: Integer);
var
  i: Integer;
begin
  for i := 0 to MAX_HOLES-1 do
    if (fHoles[i].IsDead = false) and fHoles[i].HoleIsFull then
      // モグラが叩かれたかどうかの判定
      if (X > fHoles[i].HolePos.X) and
         (X < fHoles[i].HolePos.X+fHoles[i].Mogura.LiveBmp.Width) and
         (Y > fHoles[i].HolePos.Y) and
         (Y < fHoles[i].HolePos.Y+fHoles[i].Mogura.LiveBmp.Height) then
      begin
        fHoles[i].IsDead := true;         // モグラが叩かれました。
        ShowDeadMog(i, fHoles[i].Mogura); // 叩かれた絵を表示

        // 得点の追加
        Inc(fGameScore, fHoles[i].Mogura.Score);
      end;
end;

constructor TGameManager.Create;
begin
  // 穴の位置を設定
  fHoles[0] := THole.Create(Point(10, 10));
  fHoles[1] := THole.Create(Point(200, 10));
  fHoles[2] := THole.Create(Point(100, 100));
  fHoles[3] := THole.Create(Point(10, 200));
  fHoles[4] := THole.Create(Point(200, 200));

  // 普通のモグラの生成
  fNormalMog := TBaseMog.Create(1000, 800, 'Mog1', 'Mog2', 300);

  // 黄色いモグラの生成
  fYellowMog := TBaseMog.Create(500, 500, 'Mog3', 'Mog4', 700);

  GameInit; // ゲームの初期化
end;


procedure TGameManager.DecGameTime;
begin
  Dec(fGameTime, 100); // 制限時間を減らします。

  // 制限時間がゼロになるとゲームオーバー
  if fGameTime = 0 then GameOver;
  UpdateGameTime; // 制限時間の更新
end;

destructor TGameManager.Destroy;
var
  i: Integer;
begin
  for i := 0 to MAX_HOLES-1 do
    fHoles[i].Free;
  fNormalMog.Free;
  fYellowMog.Free;
  inherited;
end;

procedure TGameManager.GameInit;
begin
  fGameTime  := 30000; // 制限時間 (ms)
  fGameScore := 0;
  Form1.Canvas.FillRect(Form1.ClientRect);
  Form1.Timer1.Enabled := true;
end;

procedure TGameManager.GameLoop;
var
  HoleNum: Integer;
  i: Integer;
begin
  HoleNum := Random(17);
  if (HoleNum < 5) then
    if not fHoles[HoleNum].HoleIsFull then
      ShowLiveMog(HoleNum, GetKindOfMog); // モグラを表示します

  for i := 0 to MAX_HOLES-1 do 
    fHoles[i].DecLimitTime; // 表示時間を減らします

  DecGameTime;     // 制限時間を減らします。
  UpdateGameScore; // スコアの表示
end;

procedure TGameManager.GameOver;
begin
  Form1.Timer1.Enabled := false;
  Form1.Canvas.FillRect(Rect(0, 0, 300, 300));
  Form1.Canvas.TextOut(100, 100, 'Game Over');
end;

function TGameManager.GetKindOfMog: TBaseMog;
begin
  // 制限時間が 5〜10秒の時だけ黄色モグラを出現させる
  if (fGameTime < 10000) and (fGameTime > 5000) then
    Result := fYellowMog
  else
    Result := fNormalMog;
end;

procedure TGameManager.ShowDeadMog(HoleNumber: Integer; Mog: TBaseMog);
begin
  with fHoles[HoleNumber] do 
  begin
    LimitTime := Mog.DeadTime;
    Form1.Canvas.Draw(HolePos.X, HolePos.Y, Mog.DeadBmp);
  end;
end;

procedure TGameManager.ShowLiveMog(HoleNumber: Integer; Mog: TBaseMog);
begin
  with fHoles[HoleNumber] do 
  begin
    Existence := true;
    LimitTime := Mog.LiveTime;
    Mogura := Mog;
    Form1.Canvas.Draw(HolePos.X, HolePos.Y, Mog.LiveBmp);
  end;
end;

procedure TGameManager.UpdateGameScore;
begin
  Form1.Canvas.TextOut(300, 80, Format('Score: %d', [fGameScore]));
end;

procedure TGameManager.UpdateGameTime;
begin
  Form1.Canvas.TextOut(300, 30, Format('GameTime: %.3d', [fGameTime div 100]));
end;

up next
Last update: 2002/12/28