第05回 プレイヤーを狙う敵弾
第04回では、プレイヤーの弾を敵に当てて撃破し、スコアを獲得する仕組みを完成させました。
第05回では、敵がプレイヤーを狙って撃ち返す敵弾(てきだん)を実装します。
敵弾は発射時のプレイヤー位置へ向きを決め、その後は一定の速度で直進します。2点の座標の差から方向ベクトルを求め、正規化で長さをそろえるという、ゲーム数学の基本を学びます。
始める前に
弾の発行・更新と、座標の差を求める処理を確認してください。方向の計算は本文の数値例で確認します。確認したい場合は、プレイヤーの弾とオブジェクトプールを参照してください。
前の回の受講や完成物は必須ではありません。下の開始用プロジェクトを使い、配布済みの処理と今回追加する処理を確認してから進めます。
配布プロジェクト
第05回のプロジェクトを展開し、ShootingGame2D.slnをVisual Studio 2026で開いてください。
第04回で実装した弾と敵の命中判定、およびスコア加算機能が含まれたプロジェクトから開始します。
配布ファイル一覧
| ファイル | 役割 |
|---|---|
| Source/Shooting/Enemy.cpp | 敵の移動処理および弾の発射処理の実装 |
| Source/Shooting/EnemyManager.cpp | 敵全体の出現と更新・描画の統括 |
| Source/Shooting/Game.cpp | ゲームループと敵弾Managerの接続 |
| Source/Shooting/Tuning/GameTuning.h | 敵弾の速度や発射間隔などの調整値 |
| Assets/Images/EnemyShot.png | 敵弾用の画像素材 |
この回のゴール
画面上の敵が、プレイヤーの現在位置を狙って敵弾を発射し、弾が一定速度でまっすぐ飛んでくる状態を目指します。
- 敵弾1発分の位置と速度を管理する
EnemyShotクラスを実装できる - 2点間の座標の差から方向ベクトルを求め、正規化して一定の速度ベクトルを算出できる
- 発射時点の目標を狙う「直線弾」と、相手を追い続ける「追尾弾(ホーミング)」の違いを説明できる
EnemyShotManagerを用いて、敵弾をプール管理できる
今回のポイント
プレイヤー弾と敵弾を別のクラスに分ける理由
プレイヤー弾と敵弾は、どちらも画面上を移動する弾オブジェクトです。
同じクラスでフラグを使って区別する方法も考えられますが、この作品ではPlayerShotとEnemyShotを別々のクラスにします。
両者は以下のように、ゲーム上の性質が根本的に異なります。
| 項目 | プレイヤー弾(PlayerShot) | 敵弾(EnemyShot) |
|---|---|---|
| 発射する側 | プレイヤー(自機) | 敵キャラクター |
| 移動方向 | 常に上方向(-Y方向)へ直進 | 自機を狙う任意の斜め方向 |
| 当たり判定の相手 | 敵キャラクター | プレイヤー(自機) |
| 描画の順序 | 敵より先に描く | 敵より後に描く |
一つのクラスにまとめると、移動や判定の各所で自機の弾か敵弾かを判別する必要があり、コードが複雑になります。役割や動作が異なるものを専用クラスに分けることが、処理を追いやすくする設計の要点です。
作業の準備
開始用ZIPには前回までの到達状態が含まれています。今回の新規ファイルは、本文を進めながら追加します。ファイルの登録方法や変更の引き継ぎ手順は、配布ファイルの手順で確認できます。
| 作業 | 対象 |
|---|---|
| 新規作成 | Source/Shooting/EnemyShot.cpp、Source/Shooting/EnemyShot.h、Source/Shooting/EnemyShotManager.cpp、Source/Shooting/EnemyShotManager.h |
| 既存ファイルへ追記・編集 | Source/Shooting/Enemy.cpp、Source/Shooting/Enemy.h、Source/Shooting/Game.cpp、Source/Shooting/Game.h、Source/Shooting/ImageManager.cpp、Source/Shooting/ImageManager.h、Source/Shooting/Player.cpp、Source/Shooting/Player.h、Source/Shooting/Tuning/GameTuning.h |
| 重点的に実装・確認する処理 | EnemyShot::Spawn、Enemy::TryShoot、Game::Update |
ヘッダーの宣言、#include、登録テーブル、エラー処理などは、最終ステップの参考実装を参照できます。重点関数は各ステップで処理の流れを確認しながら記述します。関数を変更する際は、宣言・定義・呼び出し元の整合性を保ちます。
GameTuning.hには今回必要な定数を追記し、自身で調整した既存の値を維持します。