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() し、各配置へ初期化した Enemy を push_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);
    }
}

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

敵をまとめて描画する ​

同じ EnemyManager.cpp に、敵を順に描く関数と、配置数を返す関数を定義します。

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();
}

Gameへ接続する ​

Game.h の既存のインクルードへ追加します。

Game.hcpp
#include "Platformer/Player.h"
#include "Platformer/EnemyManager.h"

Game クラスの player_ の下へ、敵の管理用メンバを追加します。

Game.hcpp
    Player player_;
    EnemyManager enemies_;

Game::ResetStage() でプレイヤーを初期化した直後に、配置情報から敵を初期化します。

Game.cpp(ResetStage内)cpp
    player_.Reset(stage_.GetPlayerSpawn());
    enemies_.Reset(stage_.GetEnemySpawns());
    camera_.Update(player_.GetPosition(), stage_.GetWorldWidth());

Game::Draw() のステージとプレイヤーの描画の間へ、敵の描画を加えます。

Game.cpp(Draw内)cpp
    stage_.Draw(camera_.GetX(), images_);
    enemies_.Draw(camera_, images_);
    player_.Draw(camera_, images_);

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

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

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