第10回 エフェクトと演出
1 / 4 エフェクトのプール管理
このステップの目的
命中時に発生するヒットエフェクトを、固定容量の配列を用いたプール構造で管理します。
エフェクト用の軽量なデータ構造
今回のヒットエフェクトは、中心から円が広がり、薄くなって消える演出です。専用の画像は使いません。
大きなクラスは必要ありません。中心座標center、経過秒数age、有効フラグisActiveだけを持つ構造体にします。外部から直接参照しないため、EffectManagerのprivate内に定義します。
EffectManager.hcpp
#pragma once
#include <array>
#include <cstddef>
#include "DxGame/Vector2.h"
namespace dxgame::shooting
{
// 命中時に広がって消える円形エフェクトを固定数管理する
class EffectManager
{
public:
// 停止中のエフェクトをcenterで開始する
// 空きがない場合は何もしない
void Spawn(const Vector2& center);
// すべてのエフェクトの経過時間を進め表示時間を終えたものを停止する
// deltaTimeは1フレームの経過秒数
void Update(float deltaTime);
// 実行中のエフェクトを経過時間に応じた半径と透明度で描く
void Draw() const;
// すべてのエフェクトを停止して空の状態に戻す
void Reset();
private:
// 1つのエフェクトの中心座標、経過時間、実行状態を保持する
struct Effect
{
Vector2 center = {};
float age = 0.0f;
bool isActive = false;
};
// エフェクトの最大数
static constexpr std::size_t Capacity = 32;
std::array<Effect, Capacity> effects = {};
};
}最大数を32個(Capacity = 32)に限定し、std::arrayでプールを保持します。
空きスロットの探索と初期化
エフェクトを発生させるEffectManager::Spawn()では、配列effectsの中から現在停止しているスロット(!effect.isActive)を探します。
EffectManager.cppcpp
void EffectManager::Spawn(const Vector2& center)
{
// 先頭から停止中のエフェクトを探して再利用する
for (Effect& effect : effects)
{
if (effect.isActive)
continue;
effect.center = center;
effect.age = 0.0f;
effect.isActive = true;
return;
}
}第02回の弾、第03回の敵と同じく、固定配列から停止中のスロットを探して再利用します。
32個すべてが使用中なら、新しいエフェクトの発生を見送ります。ゲーム全体の動作やメモリには悪影響を与えません。
チェックリスト
- エフェクトのデータ構造が
EffectManager内部にプライベート構造体としてカプセル化されている - 固定長配列(
Capacity = 32)を用いてプール管理されている - 停止中のスロットを見つけて初期化し、再利用する処理を説明できる
- プールが上限に達した場合でも、ゲームが安全に動作を継続する設計になっていることを理解している