《游戏编程模式》学习笔记(七)状态模式 State Pattern

这篇具有很好参考价值的文章主要介绍了《游戏编程模式》学习笔记(七)状态模式 State Pattern。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

状态模式的定义

允许对象在当内部状态改变时改变其行为,就好像此对象改变了自己的类一样。

举个例子

在书的示例里要求你写一个人物控制器,实现跳跃功能
直觉上来说,我们代码会这么写:

void Heroine::handleInput(Input input)
{
  if (input == PRESS_B)
  {
    yVelocity_ = JUMP_VELOCITY;
    setGraphics(IMAGE_JUMP);
  }
}

可是这么写不对,因为人物本身应该只能跳一次,这样写的话人物就可以无限按B实现跳跃了。我们加一个bool变量来限制跳跃的情况。

void Heroine::handleInput(Input input)
{
  if (input == PRESS_B)
  {
    if (!isJumping_)
    {
      isJumping_ = true;
      // 跳跃……
    }
  }
}

好的,现在还要加一个趴下的功能,松开按键还得能站起来。如果我们这么加代码:

void Heroine::handleInput(Input input)
{
  if (input == PRESS_B)
  {
    // 如果没在跳跃,就跳起来……
  }
  else if (input == PRESS_DOWN)
  {
    if (!isJumping_)
    {
      setGraphics(IMAGE_DUCK);
    }
  }
  else if (input == RELEASE_DOWN)
  {
    setGraphics(IMAGE_STAND);
  }
}

实际上就会出bug,如果玩家在趴下的状态下按了B跳起,此时再松开趴下键,人物就会在空中变成站立的姿势。那么为了防止这种情况的发生,我们又加了一个bool变量来标识趴下的情况:

void Heroine::handleInput(Input input)
{
  if (input == PRESS_B)
  {
    if (!isJumping_ && !isDucking_)
    {
      // 跳跃……
    }
  }
  else if (input == PRESS_DOWN)
  {
    if (!isJumping_)
    {
      isDucking_ = true;
      setGraphics(IMAGE_DUCK);
    }
  }
  else if (input == RELEASE_DOWN)
  {
    if (isDucking_)
    {
      isDucking_ = false;
      setGraphics(IMAGE_STAND);
    }
  }
}

这段代码已经很臃肿了,如果我们还想让人物实现移动,是不是又得加个标志位?再进一步,人物如果要实现攻击呢?代码就会越来越复杂……
这个时候我们就需要FSM来救场了。
(这里说的FSM和状态模式是同一个东西,下同)
FSM的要点:
《游戏编程模式》学习笔记(七)状态模式 State Pattern,游戏实用技术专栏,读书笔记,游戏,学习,笔记

顺着这个思路,这里列出一个最简单的FSM,我们先用枚举定义状态:

enum State
{
  STATE_STANDING,
  STATE_JUMPING,
  STATE_DUCKING,
  STATE_DIVING
};

在之前的代码中,我们先判断输入,再根据状态的不同做判断。但是在这里,我们让处理状态的代码聚在一起,所以先对状态做分支。这样的话:

void Heroine::handleInput(Input input)
{
  switch (state_)
  {
    case STATE_STANDING:
      if (input == PRESS_B)
      {
        state_ = STATE_JUMPING;
        yVelocity_ = JUMP_VELOCITY;
        setGraphics(IMAGE_JUMP);
      }
      else if (input == PRESS_DOWN)
      {
        state_ = STATE_DUCKING;
        setGraphics(IMAGE_DUCK);
      }
      break;

    case STATE_JUMPING:
      if (input == PRESS_DOWN)
      {
        state_ = STATE_DIVING;
        setGraphics(IMAGE_DIVE);
      }
      break;

    case STATE_DUCKING:
      if (input == RELEASE_DOWN)
      {
        state_ = STATE_STANDING;
        setGraphics(IMAGE_STAND);
      }
      break;
  }
}

我们扔掉了烦人的标志位,简化了状态的变化,将其变成了字段,然后将处理所有状态的代码都聚集在了一起。这就是最简单的一种FSM。
现在让我们更进一步,看看对于复杂情况,我们要如何构建一个状态模式控制下的人物逻辑。
对于一些复杂的状态,我们有时候既要处理输入,又要处理时间。因为有些状态会根据按下时间的长短进行改变。
比如,现在趴下一定时间后会进行充能,充能后发动的攻击威力更大。
我们以此为目标,按照面向对象的逻辑,我们先写一个状态基类:

class HeroineState
{
public:
  virtual ~HeroineState() {}
  virtual void handleInput(Heroine& heroine, Input input) {}
  virtual void update(Heroine& heroine) {}
};

这里的handleInput()就是处理输入的接口,update()就是处理状态随着时间变化的接口。
我们再以此为基础,写趴下状态,将其单独变为一个类,并且继承这个基类:

class DuckingState : public HeroineState
{
public:
  DuckingState()
  : chargeTime_(0)
  {}

  virtual void handleInput(Heroine& heroine, Input input) {
    if (input == RELEASE_DOWN)
    {
      // 改回站立状态……
      heroine.setGraphics(IMAGE_STAND);
    }
  }

  virtual void update(Heroine& heroine) {
    chargeTime_++;
    if (chargeTime_ > MAX_CHARGE)
    {
      heroine.superBomb();
    }
  }

private:
  int chargeTime_;
};

这样,我们在人物Heroine的类中添加当前状态的指针,就可以让人物拥有趴下的状态了:

class Heroine
{
public:
  virtual void handleInput(Input input)
  {
    state_->handleInput(*this, input);
  }

  virtual void update()
  {
    state_->update(*this);
  }

private:
  HeroineState* state_;
};

要改变状态,只要让指针指向别的地方就OK了。
这就是一个面向对象式的,相对复杂的状态模式的实现方式。是不是还算很简单?

一些细节

如果状态中不存储数据,或者只有全程只有一个人物拥有这些状态,你可以直接静态声明这些状态,将其放在全局存储区内。但如果这些状态包含着数据,就像上边的例子中的chargeTime,你就需要考虑把这些状态实例化,以便管理。
有时候你需要对状态加入入口行为和出口行为来控制状态的转换。例如在每个状态的入口行为方法中改变人物的贴图等等。

原文: https://gpp.tkchu.me/state.html文章来源地址https://www.toymoban.com/news/detail-666182.html

到了这里,关于《游戏编程模式》学习笔记(七)状态模式 State Pattern的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式之:状态模式(State Pattern)

    状态模式(State Pattern) 状态模式是一种行为设计模式,允许一个对象在其内部状态改变时改变它的行为。这种模式通过把状态的变化逻辑分布到State的子类之间,减少了相互间的依赖,使得状态的切换更加清晰。 状态模式的关键是将那些会随着状态改变而改变的行为抽离出

    2024年02月21日
    浏览(38)
  • 大话设计模式——17.状态模式(State Pattern)

    简介 对象的行为依赖于它的状态(属性),可以根据状态的改变而改变相关行为。 UML图: 应用场景: 对象的行为取决于其状态,并且必须要在运行时刻根据状态而改变行为 代码中包含大量与对象状态有关的条件语句 示例 上午、下午、晚上工作的状态 上下文对象: 状态

    2024年04月14日
    浏览(41)
  • 设计模式二十一:状态模式(State Pattern)

    一个对象的内部状态发生变化时,允许对象改变其行为。这种模式使得一个对象看起来好像在运行时改变了它的类,主要目的是将状态的行为从主要对象中分离出来,使得主要对象不必包含所有状态的逻辑,而是将每个状态的行为封装在独立的类中。这有助于减少代码的重复

    2024年02月11日
    浏览(47)
  • 命令模式 Command Pattern 《游戏设计模式》学习笔记

    对于一般的按键输入,我们通常这么做,直接if按了什么键,就执行相应的操作 在这里我们是将用户的输入和程序行为硬编码在一起,这是我们很自然就想到的最快的做法。 但是如果这是一个大型游戏,往往我们需要实现一个按键配置的功能(话说2077直到上线都没有实现这

    2024年02月14日
    浏览(44)
  • 状态设计模式(State Pattern)[论点:概念、相关角色、图示、示例代码、框架中的运用、适用场景]

            状态模式 (State Pattern)是一种行为型设计模式,用于解决对象在不同状态下的行为问题。它允许一个对象在其内部状态改变时改变它的行为。状态模式主要包含三个部分: 上下文 (Context)、 状态接口 (State)和 具体状态实现类 (ConcreteState)。 状态接口(St

    2023年04月14日
    浏览(45)
  • 【设计模式——学习笔记】23种设计模式——状态模式State(原理讲解+应用场景介绍+案例介绍+Java代码实现)

    请编写程序完成APP抽奖活动具体要求如下: 假如每参加一次这个活动要扣除用户50积分,中奖概率是10% 奖品数量固定,抽完就不能抽奖 活动有四个状态: 可以抽奖、不能抽奖、发放奖品和奖品领完,活动的四个状态转换关系图如下 一开始的状态为“不能抽奖”,当扣除50积分

    2024年02月12日
    浏览(49)
  • 设计模式学习笔记 - 设计模式与范式 -行为型:8.状态模式:游戏、工作流引擎中常用的状态机是如何实现的?

    本章学习状态模式。在实际的开发中,状态模式并不是很常用,但是在能够用到的场景里,它可以发挥很大的作用。从这一点上看,它有点像我们之前讲到的组合模式。 状态模式一般用来实现状态机,而状态机常用在游戏、工作流引擎等系统开发中。不过,状态机的实现方式

    2024年04月10日
    浏览(46)
  • 《游戏编程模式》学习笔记(十二)子类沙箱 Subclass Sandbox

    基类定义抽象的沙箱方法和几个提供的操作。 将操作标为protected,表明它们只为子类所使用。 每个推导出的沙箱子类用提供的操作实现了沙箱函数。 假设我们在做一个超级英雄的游戏,我们现在要实现一些超能力。我们计划创建一个Superpower基类。然后由它派生出各种超级能

    2024年02月09日
    浏览(38)
  • 状态模式(State)

    状态 是一种行为设计模式,让你能 在 一个对象的内部状态变化时改变其行为 ,使其 看上去就像改变了自身所属的类一样 。 1. 问题 状态模式与有限状态机的概念紧密相关 。 其主要思想是程序在任意时刻仅可处于几种有限的状态中 。在任何一个特定状态中, 程序的行为都

    2024年02月12日
    浏览(59)
  • 状态模式(State)

    状态模式是一种行为设计模式,允许一个对象在其内部状态改变时改变它的行为,使其看起来修改了自身所属的类。其别名为状态对象(Objects for States)。 在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(state

    2024年02月14日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包