当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是控制一个对象状态转换条件表达式过于复杂时的情况。 把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化
传统MMO游戏中基于状态机实现的AI系统大部分使用的是状态模式。
状态模式的优点:
状态模式的缺点:
下面是简单的MMO游戏中基于状态机实现的AI系统:
enum class EState
{
E_Idle = 0,
E_Patrol,
E_Follow,
E_Attack,
E_Go_Home,
};
class StateABC
{
public:
virtual void run(Monster* pMonster) = 0;
};
class StateIdle : public StateABC
{
public:
void run(Monster* pMonster) override
{
if (nullptr == pMonster)
{
return;
}
cout << "my state:" << static_cast<int>(EState::E_Idle) << endl;
/*if (发现敌人)
{
if (在攻击范围)
{
pMonster->SetState(std::make_shared<StateAttack>());
}
else
{
pMonster->SetState(std::make_shared<StateFollow>());
}
return;
}*/
// 持续一段时间开始巡逻
pMonster->SetState(std::make_shared<StatePatrol>());
}
};
class StatePatrol : public StateABC
{
public:
void run(Monster* pMonster) override
{
if (nullptr == pMonster)
{
return;
}
cout << "my state:" << static_cast<int>(EState::E_Patrol) << endl;
/*if (发现敌人)
{
if (在攻击范围)
{
pMonster->SetState(std::make_shared<StateAttack>());
}
else
{
pMonster->SetState(std::make_shared<StateFollow>());
}
return;
}*/
/*if (在目标点)
{
pMonster->SetState(std::make_shared<StateGoHome>());
return;
}*/
}
};
class StateFollow : public StateABC
{
public:
void run(Monster* pMonster) override
{
if (nullptr == pMonster)
{
return;
}
cout << "my state:" << static_cast<int>(EState::E_Follow) << endl;
/*if (目标敌人存在)
{
if (在攻击范围)
{
pMonster->SetState(std::make_shared<StateAttack>());
return;
}
}
else
{
pMonster->SetState(std::make_shared<StateGoHome>());
}
*/
}
};
class StateAttack : public StateABC
{
public:
void run(Monster* pMonster) override
{
if (nullptr == pMonster)
{
return;
}
cout << "my state:" << static_cast<int>(EState::E_Attack) << endl;
/*if (目标敌人存在)
{
if (不在攻击范围)
{
pMonster->SetState(std::make_shared<StateFollow>());
return;
}
}
else
{
pMonster->SetState(std::make_shared<StateGoHome>());
}
*/
}
};
class StateGoHome : public StateABC
{
public:
void run(Monster* pMonster) override
{
if (nullptr == pMonster)
{
return;
}
cout << "my state:" << static_cast<int>(EState::E_Go_Home) << endl;
/*if (发现敌人)
{
if (在攻击范围)
{
pMonster->SetState(std::make_shared<StateAttack>());
}
else
{
pMonster->SetState(std::make_shared<StateFollow>());
}
return;
}*/
/*if (在home点)
{
pMonster->SetState(std::make_shared<StateIdle>());
return;
}*/
}
};
class Monster
{
public:
Monster()
{
m_ptrState = std::make_shared<StateIdle>();
}
void SetState(std::shared_ptr<StateABC> ptrState)
{
m_ptrState = ptrState;
}
void run()
{
m_ptrState->run(this);
}
private:
std::shared_ptr<StateABC> m_ptrState;
};
int main()
{
{
Monster objMonster;
//每个tick都要run
objMonster.run();
}
system("pause");
return 0;
}
对于简单的逻辑分支判断没必要使用状态模式,否则状态模式很自然的显现出来上面所提到的缺点,代码有种杀鸡用牛刀的味道