Skip to content
第21回 敵の配置とジャンプ操作の改善

2 / 4 配置数に合わせて敵を管理する

このステップの目的

CSVの配置情報から敵を生成し、EnemyManager がまとめて描画します。

単体と集合の役割を分ける

Enemy は単体の位置と表示矩形を持ちます。EnemyManager はCSVから読み込んだ SpawnPoint の数だけ Enemy を保持します。第21回では配置と描画を扱い、巡回や活動状態は第22回で追加します。

EnemyManager.hcpp
#pragma once

#include <vector>

#include "Platformer/Enemy.h"
#include "Platformer/Stage.h"

namespace dxgame::platformer
{
    class Camera;
    class ImageManager;

    // CSVから読み込んだ敵配置をEnemyの集合として所有する
    class EnemyManager
    {
    public:
        // ステージの配置情報から敵を作り直す
        void Reset(const std::vector<SpawnPoint>& spawnPoints);
        // カメラ内の敵を描画する
        void Draw(const Camera& camera, const ImageManager& images) const;

        std::size_t GetCount() const;

    private:
        std::vector<Enemy> enemies_;
    };
}

配置情報から初期化する

シューティングの弾では上限を事前に決めた std::array を使用しました。今回はCSVの配置数に合わせるため std::vector を使用します。std::vector は要素数を動的に変更できる配列です。Reset() で必要数を reserve() し、各配置へ初期化した Enemypush_back() で追加します。

EnemyManager.cppcpp
void EnemyManager::Reset(const std::vector<SpawnPoint>& spawnPoints)
{
    enemies_.clear();
    enemies_.reserve(spawnPoints.size());

    for (const SpawnPoint& spawnPoint : spawnPoints)
    {
        Enemy enemy;
        enemy.Reset(spawnPoint.position);
        enemies_.push_back(enemy);
    }
}

メモリの確保はステージ開始時の初期化でまとめて行います。毎フレームの描画時には要素を追加しません。

Gameへ接続する

Game.hEnemyManager.h をインクルードし、enemies_ をメンバとして追加します。Game::ResetStage()enemies_.Reset(stage_.GetEnemySpawns()) を追加し、Game::Draw() から enemies_.Draw(camera_, images_) を呼び出します。

EnemyManager.cppcpp
void EnemyManager::Draw(const Camera& camera,
    const ImageManager& images) const
{
    for (const Enemy& enemy : enemies_)
        enemy.Draw(camera, images);
}

std::size_t EnemyManager::GetCount() const
{
    return enemies_.size();
}

Enemy の宣言と定義をそろえてからビルドします。Enemy の画像IDと画像表は第13回から用意されているものを利用します。まずCSVに 90 を1つ追加し、敵が1体増えることを確認してください。

チェックリスト
  • CSVの 90 の配置数と、表示される敵の数が一致する
  • リセット時にCSVの位置へ敵が再配置される
  • std::arraystd::vector を、要素数の決定方法に応じて使い分けられる

ゲームプログラミング実践