《游戏编程模式》一7.5 状态对象应该放在哪里呢

7.5 状态对象应该放在哪里呢

我这里忽略了一些细节。为了修改一个状态,我们需要给state_指针赋值为一个新的状态,但是这个新的状态对象要从哪里来呢?我们之前的枚举方法是定义一些数字。但是,现在我们的状态是类,我们需要获取这些类的实例。通常来说,有两种实现方法。

7.5.1 静态状态

如果一个状态对象没有任何数据成员,那么它的唯一数据成员便是虚表指针了。那样的话,我们就没有必要创建此状态的多个实例了,因为它们的每一个实例都是相同的。

在那种情况下,我们可以定义一个静态实例。即使你有一系列的FSM在同时运转,所有的状态机也能同时指向这一个唯一的实例。

如果你的状态类没有任何数据成员,并且只有一个虚函数方法。那么我们还可以进一步简化此模式。我们可以使用一个普通的状态函数来替换状态类。这样的话,我们的state_变量就变成一个状态函数指针。

这个就是享元模式。(第3章)
你把静态方法放置在哪里,这个由你自己来决定。如果没有任何特殊原因的话,我们可以把它放置到基类状态类中:

class HeroineState
{
public:
 static StandingState standing;
 static DuckingState ducking;
 static JumpingState jumping;
 static DivingState diving;

 // Other code...
};

每一个静态成员变量都是对应状态类的一个实例。如果我们想让主角跳跃,那么站立状态应该是这样子:

if (input == PRESS_B)
{
 heroine.state_ = &HeroineState::jumping;
 heroine.setGraphics(IMAGE_JUMP);
}

7.5.2 实例化状态

有时候上面的方法可能不行。一个静态状态对于躲避状态而言是行不通的。因为它有一个chargeTime_成员变量,所以这个具体取决于每一个躲避状态下的主角类。如果我们的游戏里面只有一个主角的话,那么定义一个静态类也是没有什么问题的。但是,如果我们想加入多个玩家,那么此方法就行不通了。

当你为状态实例动态分配空间时,你不得不考虑碎片化问题了。对象池模式(第19章)可以帮助到你。
在那种情况下,我们不得不在状态切换的时候动态地创建一个躲避状态实例。这样,我们的有限状态机就拥有了它自己的实例。当然,如果我们又动态分配了一个新的状态实例,则要负责清理老的状态实例。这里必须相当小心,因为修改状态的函数是在当前状态里面,所以我们需要小心地处理删除的顺序。

另外,我们也可以选择在HeroineState类中的handleInput()方法里面可选地返回一个新的状态。当这个状态返回的时候,主角将会删除老的状态并切换到这个新的状态,如下所示:

void Heroine::handleInput(Input input)
{
 HeroineState* state = state_−>handleInput(
      *this, input);
 if (state != NULL)
 {
  delete state_;
  state_ = state;
 }
}

那样的话,我们只有在从handleInput方法返回的时候才有可能去删除前面的状态对象。现在,站立状态可以通过创建一个躲避状态的实例来切换状态了。

HeroineState* StandingState::handleInput(
      Heroine& heroine, Input input)
{
 if (input == PRESS_DOWN)
 {
  // Other code...
  return new DuckingState();
 }

 // Stay in this state.
 return NULL;
}

通常情况下,我倾向于使用静态状态。因为它们不会占用太多的CPU和内存资源。

时间: 2024-12-26 21:26:11

《游戏编程模式》一7.5 状态对象应该放在哪里呢的相关文章

《游戏编程模式》一导读

前 言 游戏编程模式在五年级的时候,我和我的小伙伴们获准使用一个放置着几台非常破旧的TRS-80s[1]的闲置教室.为了激励我们,一位老师找到了一份印有一些简单BASIC程序的打印文档给我们. 当时,计算机上的音频磁带驱动器是坏掉的,所以每次我们想要运行一些代码的时候,都不得不仔细地从头开始键入代码.这使得我们更喜欢那些只有几行代码的程序: 如果计算机打印足够多的次数,或许它会神奇的变成现实哦[2]. 10 PRINT "BOBBY IS RADICAL!!!" 20 GOTO 10

《游戏编程模式》一第1章 架构,性能和游戏

第1章 架构,性能和游戏 游戏编程模式在我们一头扎进一堆模式之前,我想为你介绍一些关于我如何看待软件架构以及它是如何应用到游戏的一些背景,这可能会帮助你更好地理解这本书的其余部分.至少,当你陷入关于设计模式和软件架构是多么糟糕(或者很棒)的一场争论中时,它会给你一些论据来使用. 请注意,我没有假设你站在争论中的哪一方.就像任何军火商一样,我为所有战斗方提供武器.

《游戏编程模式》一7.4 状态模式

7.4 状态模式 对于熟知面向对象方法的人来说,每一个条件分支都可以用动态分发来解决(换句话说,都可以用C++里面的虚函数来解决).但是,如果这样做,你可能会把简单问题复杂化.有时候,一个简单的if语句就足够了. 状态模式的由来也有一些历史原因.许多面向对象设计的拥护者-- GoF和重构的作者Martin Fowler都是Smalltalk出身.在那里,如果有一个ifThen语句,我们便可以用一个表示true和false的对象来操作.但是,在我们这个例子当中,我们发现面对对象设计也就是状态模式更

《游戏编程模式》一第7章 状态模式

第7章 状态模式 "允许一个对象在其内部状态改变时改变自身的行为.对象看起来好像是在修改自身类." 交代一下:我写的有些过头了,我在本章里面添加了太多东西.表面上这一章是介绍状态模式[1]的,但是我不能抛开游戏里面的有限状态机(finite state machines,FSM)而单独只谈"状态模式".不过,当我讲到FSM的时候,我发觉我还有必要再介绍一下层次状态机(hierarchical state machine)和下推自动机(pushdown automat

《游戏编程模式》一7.6 进入状态和退出状态的行为

7.6 进入状态和退出状态的行为 状态模式的目标就是将每个状态相关的所有的数据和行为封装到相关类里面.万里长征,我们仅仅迈出去了一步,我们还有更多路要走. 当主角更改状态的时候,我们也会切换它的贴图.现在,这段代码包含在它要切换的状态的上一个状态里面.当她从躲避状态切换到站立状态时,躲避状态将会修改它的图像: HeroineState* DuckingState::handleInput( Heroine& heroine, Input input) { if (input == RELEASE

《游戏编程模式》一7.2 救星:有限状态机

7.2 救星:有限状态机 为了消除你心中的疑惑,你可以准备一张纸和一支笔,让我们一起来画一张流程图.对于女主角能够进行的动作画一个"矩形":站立.跳跃.躲避和俯冲.当你可以按下一个键让主角从一个状态切换到另一个状态的时候,我们画一个箭头,让它从一个矩形指向另一个矩形.同时在箭头上面添加文本,表示我们按下的按钮. 恭喜,你刚刚已经成功创建了一个有限状态机.有限状态机借鉴了计算机科学里的自动机理论(automata theory)中的一种数据结构(图灵机)思想.有限状态机(FSMs)可以看

《游戏编程模式》一1.1 什么是软件架构

1.1 什么是软件架构 如果你从头到尾阅读了这本书,那么你并不会了解到3D图形背后的线性代数或者游戏物理背后的演算.这本书也不会告诉你如何一步步改进你的AI搜索树或者模拟音频播放中的房间混响. 哇,此段简直为这本书打了一个糟糕的广告. 相反,这本书是关于上面这一切要使用的代码的组织方式.这里少谈代码,多谈代码组织.每个程序都具有一定的组织性,即使它只是"把所有东西扔到main()函数里然后看看会发生什么",所以我认为讨论如何形成好的组织性会更有趣些.我们如何分辨一个架构的好坏呢? 我大

《游戏编程模式》一1.3 性能和速度

1.3 性能和速度 你有时候会听到关于软件架构和相关概念的批评声,尤其在游戏开发中:它会影响到游戏的性能.许多模式让你的代码更加灵活,但是它依赖于虚函数派发.接口.指针.消息以及其他至少有一些运行成本的机制. 一个有趣的范例是C++模板.模板元编程有时可以让你获得抽象接口而没有任何运行时开销. 对灵活的定义,不同人有不同的看法,当你在某些类中调用一个具体方法时,你相当于将这个类固定(很难做出改变).当你使用一个虚方法或者接口时,被调用的类将直到真正运行起来才能被追踪到,这样的程序更具灵活性但是会

《游戏编程模式》一7.1 我们曾经相遇过

7.1 我们曾经相遇过 假设我们现在正在开发一款横版游戏.我们的任务是实现女主角--游戏世界中玩家的图像.我们需要根据玩家的输入来控制主角的行为.当按下B键的时候,她应该跳跃.我们可以这样实现: void Heroine::handleInput(Input input) { if (input == PRESS_B) { yVelocity_ = JUMP_VELOCITY; setGraphics(IMAGE_JUMP); } } 找找看,bug在哪里? 这里应该还有如果主角着地将isJum