Skip to content

第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方向)へ直進自機を狙う任意の斜め方向
当たり判定の相手敵キャラクタープレイヤー(自機)
描画の順序敵より先に描く敵より後に描く

一つのクラスにまとめると、移動や判定の各所で自機の弾か敵弾かを判別する必要があり、コードが複雑になります。役割や動作が異なるものを専用クラスに分けることが、処理を追いやすくする設計の要点です。

敵弾の発射と移動の流れ
Enemy
銃口座標とプレイヤーの目標座標を渡して発射を依頼
EnemyShotManager
EnemyShotManager
空きスロットを探して速度ベクトルを算出し初期化
EnemyShot
EnemyShot
発射時に決めた速度で等速直進
自機方向

作業の準備 ​

開始用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には今回必要な定数を追記し、自身で調整した既存の値を維持します。

第05回の目次 ​