GitHub - kowara-gan/ProjectCpp: c++勉強用
c++勉強用. Contribute to kowara-gan/ProjectCpp development by creating an account on GitHub.
参考書の4章で作るゲームを作ります。
準備を前回と同じように行います。
ステートマシン
ステートマシンを設計します。状態の遷移を管理するのですが、クラスとしてオブジェクト指向を利用したステートマシンを使うことで拡張性があります。
class AIState
{
public:
AIState(class AIComponent* owner)
:mOwner(owner)
,mTower(nullptr)
,mEnemy(nullptr)
{ }
// 状態ごとの振る舞い
virtual void Update(float deltaTime) = 0;
virtual void OnEnter() = 0;
virtual void OnExit() = 0;
// 状態名の取得
virtual const char* GetName() const = 0;
protected:
class Enemy* mEnemy;
class Tower* mTower;
class AIComponent* mOwner;
};
AIStateは基底クラスであり、その派生クラスの実装ではオーバーライドして拡張します。
class AIPatrol : public AIState
{
public:
AIPatrol(class AIComponent* owner)
:EnemyState(owner, enemy)
{
}
// 振る舞いをオーバーライドする
void Update(float deltaTime) override;
void OnEnter() override;
void OnExit() override;
const char* GetName() const override
{
return "Patrol";
}
};
ステートマシンを利用するコンポーネントはステートマシンのポインタを配列で持ち、アップデート関数では現在のステートに動作を委譲するような設計となります。先ほどのステートクラスを使うには登録が必要です。
class AIComponent : public Component
{
public:
AIComponent(class Actor* owner);
void Update(float deltaTime) override;
void ChangeState(const std::string& name);
// 新しい状態を登録
void RegisterState(class AIState* state);
private:
// 状態の名前とインスタンスを対応づけるマップ
std::unordered_map<std::string, class AIState*> mStateMap;
// 現在の状態
class AIState* mCurrentState;
};
経路探索
ここに関しては迷路のゲーム情報学で解説したいので、その記事を参照してください。(まだない)
参考書ではグラフ、幅優先探索、ヒューリスティック(マンハッタン・ユークリッド距離)、欲張り法、A*探索、ダイクストラ法が紹介されます。
ゲーム木
この内容は以下の記事を参照してください。
練習問題
ステートマシンを実装します。判定のためにキャストしており、適切なステート名をつけるかもっと良い方法があるかもしれません。下記のプログラムも参考ですが、A*探索のgifがわかりやすいです。
重力付き4目並べを実装します。ほとんど用意されているので、αβ法を実装するだけです。
float AlphaBetaMax(const BoardState* node, int depth, float alpha, float beta)
{
if (node->IsTerminal() || depth == 0)
{
return node->GetScore();
}
float maxValue = -std::numeric_limits<float>::infinity();
for (const BoardState* child : node->GetPossibleMoves(BoardState::Red))
{
maxValue = std::max(maxValue, AlphaBetaMin(child, depth - 1, alpha, beta));
if (maxValue >= beta)
{
return maxValue;
}
alpha = std::max(maxValue, alpha);
}
return maxValue;
}
float AlphaBetaMin(const BoardState* node, int depth, float alpha, float beta)
{
if (node->IsTerminal()||depth==0)
{
return node->GetScore();
}
float minValue = std::numeric_limits<float>::infinity();
for (const BoardState* child : node->GetPossibleMoves(BoardState::Yellow))
{
minValue = std::min(minValue, AlphaBetaMax(child, depth-1, alpha, beta));
if (minValue <= alpha)
{
return minValue;
}
beta = std::min(minValue, beta);
}
return minValue;
}
const BoardState* AlphaBetaDecide(const BoardState* root ,int maxDepth)
{
const BoardState* choice = nullptr;
float maxValue = -std::numeric_limits<float>::infinity();
float beta = std::numeric_limits<float>::infinity();
for (const BoardState* child : root->GetPossibleMoves(BoardState::Red))
{
float v = AlphaBetaMin(child,maxDepth-1,maxValue, beta);
if (v > maxValue)
{
maxValue = v;
choice = child;
}
}
return choice;
}
ライセンス元
GitHub - gameprogcpp/code: Game Programming in C++ Code
Game Programming in C++ Code. Contribute to gameprogcpp/code development by creating an account on GitHub.
コメント