WinFormsを使ったシンプルな落ち物キャッチゲームのチュートリアル

2025年2月27日

1. ゲームの概要

このゲームでは、画面下部に配置したプレイヤー(バスケットなどのイメージ)を左右の矢印キーで操作し、上部から落ちてくるオブジェクト(フルーツやボールなど)をキャッチします。
衝突判定は PictureBox の Bounds プロパティと IntersectsWith メソッドを利用して実装します。

2. 開発環境とプロジェクト作成

必要な環境

  • Visual Studio(C#のWinFormsアプリケーション開発環境)
    ※Visual Studio Community Editionで十分です。

プロジェクトの作成手順

  1. Visual Studio を起動し、「新しいプロジェクト」を選択。
  2. 「Windows Forms アプリケーション(.NET Framework または .NET)」を選び、プロジェクトに名前(例:CatchFallingObjectGame)を付けて作成します。

3. フォームデザインとコントロール配置

主なコントロール

ツールボックスからデザインウィンドウにドラッグ&ドロップする前提にしています

  • PictureBox (Player)
    画面下部に配置。バスケットやキャラクターの画像を設定します。
    例:pictureBoxPlayer
  • PictureBox (Falling Object)
    画面上部から落ちてくるオブジェクトの画像を設定します。
    例:pictureBoxFalling
  • Timer
    落ちてくるオブジェクトの移動や、衝突判定の更新に使用します。
    プロパティで Interval を 50~100 ミリ秒程度に設定します。
    例:gameTimer

レイアウト例

  • Player PictureBox:フォーム下部中央に配置
  • Falling Object PictureBox:フォーム上部のランダムな位置に配置

4. コードの実装

4.1 プレイヤーの移動

フォームの KeyDown イベントを使って、左右の矢印キー入力に応じてプレイヤー(PictureBox)の位置を変更します。

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    int moveSpeed = 20; // 移動量の調整

    if (e.KeyCode == Keys.Left)
    {
        // 画面左端を越えないように移動
        if (pictureBoxPlayer.Left - moveSpeed >= 0)
            pictureBoxPlayer.Left -= moveSpeed;
    }
    else if (e.KeyCode == Keys.Right)
    {
        // 画面右端を越えないように移動
        if (pictureBoxPlayer.Right + moveSpeed <= this.ClientSize.Width)
            pictureBoxPlayer.Left += moveSpeed;
    }
}

このメソッドは、キーボードのキーが押されたときにプレイヤーの PictureBox を左右に移動させる処理 を実装しています。
以下、コードを詳しく解説していきます。


1. メソッドの宣言

private void Form1_KeyDown(object sender, KeyEventArgs e)

このメソッドは キーイベント(KeyDown) に対応するイベントハンドラで、Form1KeyDown イベントに設定されるべき関数です。

  • privateこのクラス内でのみ使用可能
  • void戻り値なし(何も返さない)
  • senderイベントを発生させたオブジェクト(通常 Form1
  • KeyEventArgs e押されたキーの情報 を持つ引数

KeyEventArgs には以下のようなプロパティがあります:

  • e.KeyCode押されたキーの種類 (Keys.LeftKeys.Right など)
  • e.Shift / e.Control / e.Alt修飾キー(Shift, Ctrl, Alt)の状態

2. 移動量の設定

int moveSpeed = 20; // 移動量の調整
  • プレイヤー(pictureBoxPlayer)を 1回のキー入力で 20 ピクセル 移動 させる。
  • moveSpeed の値を調整すると 移動速度を変更可能

3. 左キーが押された場合の処理

if (e.KeyCode == Keys.Left)
{
    // 画面左端を越えないように移動
    if (pictureBoxPlayer.Left - moveSpeed >= 0)
        pictureBoxPlayer.Left -= moveSpeed;
}

解説

  1. if (e.KeyCode == Keys.Left)
    • 左キー () が押されたかどうかを判定
  2. if (pictureBoxPlayer.Left - moveSpeed >= 0)
    • 左端を超えないかチェック
      • pictureBoxPlayer.Left左端の座標PictureBox左上の X 座標)。
      • - moveSpeed で左に移動したとき、 0 以上(ウィンドウの左端より内側)なら移動を許可
  3. pictureBoxPlayer.Left -= moveSpeed;
    • 左へ moveSpeed ピクセル移動

処理の流れ

pictureBoxPlayer.Left(現在の位置)pictureBoxPlayer.Left - moveSpeed (移動後の位置)画面外に出る?移動の可否
3010いいえ移動OK
10-10はい移動NG
5-15はい移動NG
0-20はい移動NG

4. 右キーが押された場合の処理

else if (e.KeyCode == Keys.Right)
{
    // 画面右端を越えないように移動
    if (pictureBoxPlayer.Right + moveSpeed <= this.ClientSize.Width)
        pictureBoxPlayer.Left += moveSpeed;
}

解説

  1. else if (e.KeyCode == Keys.Right)
    • 右キー () が押されたかどうかを判定
  2. if (pictureBoxPlayer.Right + moveSpeed <= this.ClientSize.Width)
    • 右端を超えないかチェック
      • pictureBoxPlayer.Right右端の座標PictureBox右上の X 座標)。
      • + moveSpeed で右に移動したとき、 ウィンドウの右端(this.ClientSize.Width)以内なら移動を許可
  3. pictureBoxPlayer.Left += moveSpeed;
    • 右へ moveSpeed ピクセル移動

処理の流れ

フォームの右端 (this.ClientSize.Width = 500) とした例

pictureBoxPlayer.Right(現在の位置)pictureBoxPlayer.Right + moveSpeed (移動後の位置)画面外に出る?移動の可否
300320いいえ移動OK
480500いいえ移動OK
490510はい移動NG
500520はい移動NG

5. FormKeyDown イベントを設定する

上記のメソッドを Form1 に設定するには、以下のように KeyDown イベントを紐づける必要があります。

方法 1: デザイナーで設定

  1. Form1 を開く
  2. プロパティウィンドウ(F4) を開く
  3. 「イベント(雷マーク)」タブ をクリック
  4. KeyDown の欄で Form1_KeyDown を選択

方法 2: コードで設定

this.KeyDown += new KeyEventHandler(Form1_KeyDown);
this.KeyPreview = true; // フォームがキー入力を先に受け取る
  • this.KeyPreview = true; を設定すると、フォームがキー入力を コントロールより先に処理 できる。
  • これを設定しないと、PictureBox などの他のコントロールがフォーカスを持っているときに キー入力が反応しない

※フォームのプロパティで KeyPreview を true に設定しておくと、フォーム全体でキー入力を受け取れます。

1. KeyPreview プロパティとは?

KeyPreview プロパティは、Windows Forms アプリケーションでフォーム全体のキー入力を制御するためのプロパティです。これを true に設定すると、フォームがフォーカスを持っているすべてのコントロールよりも先にキーボードイベント (KeyDownKeyPressKeyUp) を受け取ることができます。


2. なぜ KeyPreview = true が必要なのか?

通常、Windows Forms ではフォーカスのあるコントロール(TextBox や Button など)がキー入力を最初に受け取ります。そのため、たとえば Form に KeyDown イベントを追加しても、フォーカスが TextBox にある場合は TextBox が先にキーを処理してしまい、フォームの KeyDown イベントが発生しないことがあります。

しかし、KeyPreview を true に設定すると、フォームが最初にキー入力を受け取るため、フォーム側で一括して処理したり、特定のキーの動作をカスタマイズできます。

4.2 落ち物の移動と再出現

Timerの Tick イベントで、落ち物を下方向に移動させ、画面下まで到達したら上部に戻す処理を実装します。

private void gameTimer_Tick(object sender, EventArgs e)
{
    int fallSpeed = 5; // 落下速度

    // 落ち物を下に移動
    pictureBoxFalling.Top += fallSpeed;

    // 画面下に到達した場合、再度上部ランダム位置に配置
    if (pictureBoxFalling.Top > this.ClientSize.Height)
    {
        ResetFallingObject();
    }

    // 衝突判定を実施
    CheckCollision();
}

4.3 落ち物のリセット

private void ResetFallingObject()
{
    // 落ち物のY座標をリセット
    pictureBoxFalling.Top = -pictureBoxFalling.Height;
    // X座標は画面幅内のランダムな位置に配置
    Random rnd = new Random();
    pictureBoxFalling.Left = rnd.Next(0, this.ClientSize.Width - pictureBoxFalling.Width);
}

4.4 衝突判定の実装

PictureBox の Bounds プロパティと IntersectsWith メソッドを利用して、プレイヤーと落ち物が重なった場合の衝突判定を行います。

private void CheckCollision()
{
    if (pictureBoxPlayer.Bounds.IntersectsWith(pictureBoxFalling.Bounds))
    {
        // 衝突時の処理(例:得点加算、メッセージ表示、落ち物の再配置など)
        ResetFallingObject();
        MessageBox.Show("キャッチ成功!");
    }
}

このコードは、ゲームなどで「キャッチ」する動作を実現するための基本的な衝突判定(コリジョンチェック)の一例です。以下、各部分を初学者向けに分解して説明します。

1. メソッド名「CheckCollision」

  • 意味: 「CheckCollision」は「衝突を確認する」という意味です。つまり、このメソッドはプレイヤーと落ち物がぶつかっているかどうかをチェックします。

2. if文の中身

if (pictureBoxPlayer.Bounds.IntersectsWith(pictureBoxFalling.Bounds))
  • pictureBoxPlayer と pictureBoxFalling:
    • これらは画面に表示される画像(PictureBoxオブジェクト)です。例えば、pictureBoxPlayerはプレイヤーのキャラクター、pictureBoxFallingは落ちてくる物を表していると考えられます。
  • Bounds プロパティ:
    • PictureBox の「Bounds」は、その位置とサイズ(矩形の範囲)を示します。つまり、画像が画面上のどこにあり、どのくらいの大きさかを表現しています。
  • IntersectsWith メソッド:
    • このメソッドは、二つの矩形(ここではプレイヤーと落ち物の領域)が重なっているかどうかを判断します。重なっていれば「衝突している」と判断されます。

3. 衝突時の処理

{
    // 衝突時の処理(例:得点加算、メッセージ表示、落ち物の再配置など)
    ResetFallingObject();
    MessageBox.Show("キャッチ成功!");
}
  • ResetFallingObject():
    • これは、落ち物の位置を初期状態に戻すためのメソッドです。衝突が検出されたら、落ち物を再配置することで、次の動作に備えます。
  • MessageBox.Show(“キャッチ成功!"):
    • 画面に「キャッチ成功!」というメッセージを表示します。これは、プレイヤーが落ち物をキャッチできたことをユーザーに知らせるためのフィードバックです。

4. 全体の流れ

  • チェック: 毎回この CheckCollision メソッドが呼ばれるたびに、プレイヤーの画像と落ち物の画像が重なっているかを確認します。
  • 衝突があった場合:
    • 落ち物の位置をリセットし(ResetFallingObject())、
    • ユーザーに成功のメッセージを表示します(MessageBox.Show("キャッチ成功!"))。

このように、プログラムはプレイヤーが落ち物をキャッチした瞬間を検出し、適切な反応(得点の追加、再配置、メッセージ表示など)を行っています。これが基本的な「衝突判定」の仕組みです。

5. イベントハンドラの設定と実行

5.1 gameTimer の開始

フォームの Load イベントで gameTimer.Start(); を呼び出して、タイマーが動作するように設定します。

private void Form1_Load(object sender, EventArgs e)
{
    gameTimer.Interval = 50; // 50msごとにTickイベントを発生
    gameTimer.Start(); // タイマーを開始
    ResetFallingObject();
}

5.2 イベントの紐付け

  • フォームの KeyDown イベントに上記の Form1_KeyDown メソッドを設定。
  • Timer の Tick イベントに gameTimer_Tick を設定。

※Visual Studio のデザイナーからイベントプロパティを使って、各イベントハンドラを紐付けるか、以下のようにコードで設定することも可能です。

public Form1()
{
    InitializeComponent();
    this.KeyDown += Form1_KeyDown;
    gameTimer.Tick += gameTimer_Tick;
}

6. 実行方法

  1. プロジェクトをビルドして実行します。
  2. キーボードの左右矢印キーでプレイヤー(PictureBox)を動かします。
  3. 落ちてくるオブジェクトと衝突するか確認します。

7. まとめ

このチュートリアルでは、WinFormsのPictureBoxを利用したシンプルな落ち物キャッチゲームを作成しました。

  • プレイヤーの移動:KeyDownイベントで左右の移動を実装
  • 落ち物の移動:Timerを用いて定期的に落下させ、再出現させる処理を実装
  • 衝突判定:PictureBoxのBoundsとIntersectsWithメソッドで実装

この基本構造を理解したら、スコアカウンターや難易度調整、複数の落ち物など、さらに機能を拡張してみましょう。