9-1 インベーダーゲームを作ってみよう

ゲーム黎明期、インベーダーゲームというゲームが非常に広く流行しました。

昔のインベーダーゲームの画面

9章では、このインベーダーゲームを作ってみましょう。といっても、本格的なものは少々難しいので、ここでは次のように簡略化したものを作ります。

実際に私たちが作るインベーダーゲームの画面 (インベーダは1機のみ) は次のようになります。

これから作るインベーダーゲームの画面

※ 上方の"△"がインベーダー、画面中央の"|"が、弾 (ミサイル) です。

まずは、次のように4つのフォームを用意してください。

4つのフォーム

そして、それぞれのコンポーネントに次の通り名前を付けます。

フォーム コンポーネント Name プロパティ
「操作盤」
(FormControl)
「開始」ボタン ButtonStart
「弾発射」ボタン ButtonFire
タイマー TimerMain
「表示盤」
(FormDisplay)
イメージ ImageField
「インベーダー」
(FormInvader)
「動いている」チェックボックス CheckBoxAlive
y 座標のスピンエディット SpinEditY
x 座標のスピンエディット SpinEditX
速度のスピンエディット SpinEditSpeed
「描く」ボタン ButtonDraw
「消す」ボタン ButtonErase
「左右移動」ボタン ButtonGoHorizontal
「下移動」ボタン ButtonGoDown
「命中判定」ボタン ButtonHitCheck
「移動」ボタン ButtonMove
「初期処理」ボタン (インベーダーを作り出す) ButtonConst
「終了処理」ボタン (インベーダーを消滅させる) ButtonDest
「弾」
(FormBullet)
「動いている」チェックボックス CheckBoxAlive
y 座標のスピンエディット SpinEditY
「描く」ボタン ButtonDraw
「消す」ボタン ButtonErase
「移動」ボタン ButtonMove
「初期処理」ボタン (弾を作り出す) ButtonConst
「終了処理」ボタン (弾を消滅させる) ButtonDest

全てのフォームの Visible プロパティを True に、Position プロパティを poDefaultPosOnly にして、表示盤上のイメージコンポーネントの Height プロパティと Width プロパティはそれぞれ 200 に設定してください。また、操作盤の中の TimerMainEnabled プロパティは False にし、Interval プロパティの値を200にしてください。

忘れないうちに、保存をしておきましょう。「FormControl」があるユニットは「control」という名前で保存します。他のユニットも同様です (Display, Invader等々です)。最後に、プロジェクトを「invader_game」という名前で保存します。

では、早速プログラムを書いて行きましょう。最初は「インベーダー」フォームの「描く」ボタンの動作を記述します。このボタンが押されると、スピンエディットで指定されている座標 (x, y) を中心にインベーダーを描きます。複雑なインベーダーを描くと大変なので、とりあえず次のような三角形でインベーダーを表すことにしましょう。

インベーダーの形

プログラムは次のようになります。

// 「描く」ボタン
procedure TFormInvader.ButtonDrawClick(Sender: TObject);
var
  CenterX : Integer; // とりあえず X 座標を入れておく変数
  CenterY : Integer; // とりあえず Y 座標を入れておく変数
begin
  CenterX := SpinEditX.Value; // とりあえず X 座標を代入
  CenterY := SpinEditY.Value; // とりあえず Y 座標を代入
  FormDisplay.ImageField.Canvas.Pen.Color := clBlack; // 黒でインベーダーを描く
  FormDisplay.ImageField.Canvas.MoveTo(CenterX, CenterY - 3);
  FormDisplay.ImageField.Canvas.LineTo(CenterX - 5, CenterY + 3);
  FormDisplay.ImageField.Canvas.LineTo(CenterX + 5, CenterY + 3);
  FormDisplay.ImageField.Canvas.LineTo(CenterX, CenterY - 3);
end;

※ 上のプログラムで、CenterX, CenterY という変数なしでプログラムを書くこともできます。しかし、中心座標を CenterX, CenterY と設定することでプログラムが見やすくなります。

同様に、「消す」ボタンを押すとスピンエディットで指定された座標 (x, y) のインベーダーが消えるようにします。プログラムは次のようになります。ここでは、背景色 (白色) でインベーダーを描くことで消しています。

// 「消す」ボタン
procedure TFormInvader.ButtonEraseClick(Sender: TObject);
var
  CenterX : Integer; // とりあえず X 座標を入れておく変数
  CenterY : Integer; // とりあえず Y 座標を入れておく変数
begin
  CenterX := SpinEditX.Value; // とりあえず X 座標を代入
  CenterY := SpinEditY.Value; // とりあえず Y 座標を代入
  FormDisplay.ImageField.Canvas.Pen.Color := clWhite; // 白でインベーダを描く
  FormDisplay.ImageField.Canvas.MoveTo(CenterX, CenterY - 3);
  FormDisplay.ImageField.Canvas.LineTo(CenterX - 5, CenterY + 3);
  FormDisplay.ImageField.Canvas.LineTo(CenterX + 5, CenterY + 3);
  FormDisplay.ImageField.Canvas.LineTo(CenterX, CenterY - 3);
end;

ここまでのプログラムをダウンロード(D)

【基礎課題 9-1】

(1) 上の2つのボタンがあれば、次のようにしてインベーダーを動かすことができます。フォーム上のスピンエディットやボタンを使って、次の操作をしてください。(実行しようとしたときに「…このユニットを追加してよいですか?」という質問が表示されたら、「はい」を押してもう1度実行してください。)

(2) 今の位置から今度は下に動かします。次の空欄を埋めてください。

この操作を繰り返せば、インベーダーを動かすことができます。しかし、手動では大変ですし、これではゲームになりません。次節で自動的に動かすようにしましょう。