ホームへ戻る

15章. 敵を実装する

 今回は敵を作ってみましょう。
本章ではまず敵の基本的な骨格のみを作ります。
敵が持つ最小限の要素として、「座標」「移動速さ」「移動角度」があります。
これらの情報を保持させれば自動的にその方向に動くようにしてみます。


Enemy.h


#pragma once

#include "Task.h"

class Enemy : public Task
{
public:
    Enemy(float x, float y);
    virtual ~Enemy() = default;
    bool update() override;
    void draw() const override;

protected:
    float _x, _y;//座標
    float _speed;//速さ
    float _angle;//角度
};

Enemy.cpp


#include "Enemy.h"
#include <DxLib.h>
#include "Image.h"
#include "Define.h"

Enemy::Enemy(float x, float y) : _x(x), _y(y), _speed(2.f), _angle(Define::PI/2)
{
}

bool Enemy::update()
{
    _x += cos(_angle)*_speed;
    _y += sin(_angle)*_speed;
    return true;
}

void Enemy::draw() const
{
    DrawRotaGraphF(_x, _y, 1.0, 0.0, Image::getIns()->getEnemyNormal()[4], TRUE);
}

仮に現在は速さを2[pixel/frame]、角度をπ/2としました。
角度は0が右向き、これを原点に時計回りします。(数学で習った時は反時計回りだったと思いますが、ウィンドウはyの正が下方向なので逆回りなのです)
π/2が下、πが左、π*1.5が上、2*πがまた右を指します。
ですので、下向きにスーッと移動することを期待します。
移動計算はsin,cosで計算します。三角比の計算方法が分からない方はこちらをご覧ください。
Imageクラスには下の画像を読み込むように追加してあります。

LoadDivGraphで配列要素9の配列に格納するので中央の画像は[4]となります。
次に、このEnemyを管理するマネージャークラスです。


EnemyManager.h


#pragma once

#include "Task.h"
#include <memory>
#include <list>
#include "Enemy.h"

class EnemyManager : public Task
{
public:
    EnemyManager();
    virtual ~EnemyManager() = default;
    bool update() override;
    void draw() const override;

private:
    std::list<std::shared_ptr<Enemy>> _list;
};

EnemyManager.cpp


#include "EnemyManager.h"
#include "Define.h"

using namespace std;

EnemyManager::EnemyManager()
{
    _list.emplace_back(make_shared<Enemy>(Define::CENTER_X, 100));
}

bool EnemyManager::update()
{
    for (auto enemy : _list) {
        enemy->update();
    }
    return true;
}

void EnemyManager::draw() const
{
    for (const auto enemy : _list) {
        enemy->draw();
    }
}

敵管理クラスであるEnemyManagerクラスは敵のインスタンスをリストで保持します。
updateの指示もdrawの指示もforでまわしているだけです。
敵が増えた時はコンストラクタの代入を増やすだけでよく、updateやdraw部は変更する必要がありません。
このクラスはGameSceneクラスから呼ばれるわけですが、GameSceneクラスは例によって同じ要領で処理を追加するだけです。


GameScene.h


#pragma once

#include "AbstractScene.h"
#include "Player.h"
#include <memory>
#include "Board.h"
#include "AbstractBackground.h"
#include "EnemyManager.h"

class GameScene : public AbstractScene
{
public:
    const static char* ParameterTagStage;//パラメータのタグ「ステージ」
    const static char* ParameterTagLevel;//パラメータのタグ「レベル」

    GameScene(IOnSceneChangedListener* impl, const Parameter& parameter);
    virtual ~GameScene() = default;

    void update() override;
    void draw() const override;

private:
    std::shared_ptr<Player> _player;
    std::shared_ptr<Board>  _board;
    std::shared_ptr<AbstractBackground> _background;
    std::shared_ptr<AbstractBackground> _backgroundSpell;
    std::shared_ptr<EnemyManager> _enemyManager;
};

GameScene.cpp


#include "GameScene.h"
#include <DxLib.h>
#include "Macro.h"
#include "Background01.h"
#include "Background01spell.h"

using namespace std;

const char* GameScene::ParameterTagStage = "ParameterTagStage";//パラメータのタグ「ステージ」
const char* GameScene::ParameterTagLevel = "ParameterTagLevel";//パラメータのタグ「レベル」

GameScene::GameScene(IOnSceneChangedListener* impl, const Parameter& parameter) : AbstractScene(impl, parameter)
{
    _background = make_shared<Background01>();
    _backgroundSpell = make_shared<Background01spell>();
    _player = make_shared<Player>();
    _board = make_shared<Board>();
    _enemyManager = make_shared<EnemyManager>();
}

void GameScene::update()
{
    _background->update();
    _player->update();
    _board->update();
    _enemyManager->update();
}

void GameScene::draw() const
{
    _background->draw();
    _player->draw();
    _board->draw();
    _enemyManager->draw();
}

実行結果

→分からないことがあれば掲示板で質問して下さい


HPトップへ 質問掲示板へ

- Remical Soft -