克服一些普通状态模式限制的好方法是什么

问题描述 投票:0回答:1

我正在视频游戏开发的背景下实现State模式。例如,玩家有多种状态:

Idle
Run
Attack
。每个状态都在自己的类中实现。 重要的是,每个状态负责转换到另一个状态(例如,
Idle
状态可以转换到
Attack
,但是
Jump
状态无法转换到
Idle
,直到玩家接触地面)。请参阅下面我如何实现它的高级想法:

class Player
{
    private State _state = null;

    public Player()
    {
        this.TransitionTo(new IdleState(this));
    }

    public void TransitionTo(State state)
    {
        this._state = state;
        this._state.SetPlayer(this);
    }

    public void Jump()
    {
        this._state.jump();
    }
}

abstract class State
{
    protected Player _player;

    public void SetPlayer(Player player)
    {
        this._player = player;
    }

    public abstract void Jump();
}

class JumpState : State
{
    public override void Jump()
    {
        // double jump is not allowed
    }

}

class IdleState : State
{
    public override void Jump()
    {
        this._player.TransitionTo(new JumpState());
    }

}

这很有效,但我可以看到这种方法有两个很大的局限性:

  • 我无法交换状态的具体实现。例如,一个敌人在跳跃时可能会受到伤害,而另一个则不会。一个非常简单的
    override
    状态就可以做到,但是在我的实现中,一个状态负责转换到另一个状态,并且它通过引用另一个状态的具体实现来实现这一点。例如。在上面的代码片段中,请注意
    Jump
    如何转换为特定的
    IdleState
    。如果存在
    JumpState
    ,我还必须创建一个使用它的
    JumpNoDamageState
    状态与特定角色紧密耦合。例如,假设一个敌人的行为与另一个敌人完全相同,只不过该敌人也可以 
  • IdleNoDamageState
  • (如果生命值
    Escape
    、< 10% after taking damage. To do this, I need to recreate all
    Idle
    Attack
    状态来解释这一点),因为每个单独的状态都需要意识到这一点这种新状态以及过渡到它的可能性。
    
        
oop design-patterns game-development
1个回答
0
投票
有限状态机

(FSM)的面向对象配方。如果你想引入新的状态,你就需要改变 FSM 的定义。如果你想区分不同的 FSM,你可能必须实现不同的 State-based API。 另一个问题可能是

Jump

对象保持状态的结果。也许令人惊讶的是,


“状态对象通常是单例”

-

设计模式

您通常会通过将所谓的
Context

对象传递给每个 State 对象来设计 State 实现。在这种特殊情况下,您应该考虑更改 API,使其看起来像这样: State

您经常需要维护单独对象的状态,以便不同的对象在各自的路径中通过 FSM 进行转换。您将状态信息保存在 
Context

对象(此处为 class Player { private State _state; public Player() { _state = new IdleState(this)); } internal void TransitionTo(State state) { _state = state; } public void Jump() { _state.jump(this); } } abstract class State { public abstract void Jump(Player player); } class JumpState : State { // Singleton public static readonly State Instance = new JumpState(); private JumpState() {} public override void Jump(Player player) { // double jump is not allowed } } class IdleState : State { // Singleton public static readonly State Instance = new IdleState(); private IdleState() {} public override void Jump(Player player) { player.TransitionTo(JumpState.Instance); } } )上,以便不同的

Player
对象可以具有不同的状态,并以不同的方式通过相同的 FSM。
您也可以使 

Context

对象具有多态性。

例如,假设一个敌人的行为与另一个敌人完全相同

这听起来好像
Context

确实可能需要比 Player 更通用 - 也许

Player

除了这个敌人如果健康的话也可以逃跑

< 10% after taking damage

您可以重复使用相同的 FSM,但让它检查
Context

(Character?) 是否可能尝试逃脱。这可以像在

Context
对象上拥有布尔值一样简单。

© www.soinside.com 2019 - 2024. All rights reserved.