Skip to content
第02回 プレイヤーの弾とオブジェクトプール

1 / 4 プレイヤー弾クラスの設計 ​

このステップの目的

提供済みのPlayerShotを読み、弾1発分の位置、有効フラグ、描画の役割を確認します。

提供済みの状態と責務を読む ​

このステップではPlayerShot.hとPlayerShot.cppの宣言・Spawn・Draw・GetDrawRectを読みます。これらは提供済みなので追加し直しません。未実装のUpdateはステップ4で編集します。

弾は発射位置から直進し、画面外へ出ると消滅します。この発射から消滅までの流れが、弾のライフサイクルです。
多数の弾を扱うための第一歩として、まずは「弾1発分」のデータと機能がひとつのクラスにどうまとまっているかを確認します。

PlayerShotクラスは、現在位置を表すpositionと、弾が画面上で動いているかを表す有効フラグisActiveを保持します。

PlayerShot.hcpp
#pragma once

#include "DxGame/Rect.h"
#include "DxGame/Vector2.h"

namespace dxgame::shooting
{
    class ImageManager;

    // プレイヤーが発射する1発の弾の位置と実行状態を管理する
    class PlayerShot
    {
    public:
        // 中心をstartPositionへ移動して弾を実行状態にする
        void Spawn(const Vector2& startPosition);

        // 弾を上方向へ移動し画面外へ出たら停止する
        // deltaTimeは1フレームの経過秒数
        void Update(float deltaTime);

        // 実行中の弾を画像で描く
        void Draw(const ImageManager& images) const;

        // 更新、描画の対象ならtrueを返す
        bool IsActive() const;

        // 弾を更新、描画の対象外にする
        void Deactivate();

        // 表示用Rectを現在位置へ移動して返す
        Rect GetDrawRect() const;

    private:
        // 弾の中心座標
        Vector2 position = {};
        bool isActive = false;
    };
}

弾の位置と有効状態はプライベート変数として保持します。外部からはSpawn()やDeactivate()を通して操作し、状態に矛盾が生じるのを防ぎます。

提供済みの発射と描画を追う ​

弾は、常に画面上に表示されているわけではありません。未発射の弾や、画面外へ飛び去った弾は停止状態(isActive == false)にしておく必要があります。

Spawn()が呼ばれると、指定された発射位置(銃口座標)をpositionに保存し、isActiveをtrueに設定して弾を有効化します。

PlayerShot.cppcpp
void PlayerShot::Spawn(const Vector2& startPosition)
{
    position = startPosition;
    isActive = true;
}

bool PlayerShot::IsActive() const
{
    return isActive;
}

void PlayerShot::Deactivate()
{
    isActive = false;
}

Draw()では、まずisActiveを確認します。停止中なら何も描かずに関数を終了し、有効な場合だけ画像を描きます。

PlayerShot.cppcpp
void PlayerShot::Draw(const ImageManager& images) const
{
    if (!isActive)
        return;

    Rect drawRect = GetDrawRect();
    images.Draw(ImageManager::Id::PlayerShot, drawRect);
}

弾の表示領域の計算 ​

弾の画像サイズはGameTuning.hに定義されています。
機体と同様に、弾の中心座標から表示用の矩形を求めるGetDrawRect()の計算を読みます。

GameTuning.hcpp
namespace playerShot
{
    // 弾の中心を基準とした画像の表示範囲(幅10、高さ28)
    inline constexpr Rect DrawRect = Rect::Centered(10.0f, 28.0f);
}
PlayerShot.cppcpp
Rect PlayerShot::GetDrawRect() const
{
    return tuning::playerShot::DrawRect.MovedBy(position);
}

これで「弾1発分」のデータ構造と描画機能を確認できました。
次のステップでは、このPlayerShotを複数束ねるPlayerShotManagerのうち、停止中の弾を探すSpawnを実装します。

チェックリスト
  • PlayerShotクラスが位置座標positionと有効状態isActiveを保持している
  • Spawn()によって初期位置が設定され、有効フラグがtrueになることを理解している
  • 停止中(isActive == false)の弾は描画されないようガードされている
  • 中心座標から描画用のRectを正しく生成できている