在游戏开发中使用命令模式的一个例子html
在每一个游戏中都有一块代码读取用户的输入——按钮按下,键盘敲击,鼠标点击,诸如此类。 这块代码会获取用户的输入,而后将其变为游戏中有意义的行为。编辑器
一种简单死了的实现会是这样:函数
void InputHandler::handleInput(){工具 if (isPressed(BUTTON_X)) jump();编码 else if (isPressed(BUTTON_Y)) fireGun();设计 else if (isPressed(BUTTON_A)) swapWeapon();3d else if (isPressed(BUTTON_B)) lurchIneffectively();htm }对象 |
这个函数一般在游戏循环中每帧调用一次,我确信你能够理解它作了什么。这代码在咱们想将用户的输入和程序行为硬编码在一块儿时能够正常工做,可是许多游戏容许玩家设定按键的功能。为了支持这点,须要将这些对jump()和fireGun()的直接调用转化为能够更换的东西。 “更换”听起来有点像声明变量,所以咱们须要表示游戏行为的对象。进入:命令模式。blog
先实现命令:
class JumpCommand: ICommand { public void execute() { //这此方法可能来自另外的类,这里只是表达一下调用的意思。 jump(); } }
class FireCommand : ICommand { public void execute() { fireGun(); } } ///下面省略几千行 |
构造一个控制器,在输入控制器,为每一个键存储一个指向命令的引用,至关于前面说的Invoker:
class InputHandler { private ICommand commandX; private ICommand commandY; private ICommand commandA; private ICommand commandB;
//处理输入的操做 public void handleInput() { if (isPressed(BUTTON_X)) commandX.execute(); else if (isPressed(BUTTON_Y)) commandY.execute(); else if (isPressed(BUTTON_A)) commandA.execute(); else if (isPressed(BUTTON_B)) commandB.execute(); }
//这是另一个使用方式,与上面的是同样的,这里把command传出去 ICommand InputHandler::handleInput() { if (isPressed(BUTTON_X)) return commandX; if (isPressed(BUTTON_Y)) return commandY; if (isPressed(BUTTON_A)) return commandA; if (isPressed(BUTTON_B)) return commandB;
// Nothing pressed, so do nothing. return NULL; } }
|
这是命令模式的简短使用。若是你可以看出它的好处,能够接着往下看了。
在实践中,这并非经常使用的功能,可是这常常会有相似的用例跳出来。到目前为止,咱们只考虑了玩家控制的角色,可是游戏中的其余角色呢?它们被游戏AI控制。咱们能够在AI和角色之间使用相同的命令模式;AI代码只是简单的放出Command对象。在选择命令的AI和展示命令的游戏角色间解耦给了咱们很大的灵活度。 咱们能够对不一样的角色使用不一样的AI,或者为了避免同的行为而混合AI。 想要一个更加有攻击性的同伴?插入一个更加有攻击性的AI为其生成命令。 事实上,咱们甚至能够为玩家角色加上AI, 这在原型阶段,游戏须要自动驾驶员是颇有用的。把控制角色的命令变为第一公民对象,去除直接方法调用中严厉的束缚。 取而代之的是,将其视为命令队列,或者是命令流:
一些代码(输入控制器或者AI)产生一系列指令而后将其放入流中。 另外一些指令(调度器或者角色自身)消耗指令并调用他们。 经过在中间加入了一个队列,咱们解耦了消费者和生产者。
撤销和重作
这个例子是这种模式最广为人知的使用状况。若是一个命令对象能够作一件事,那么它亦能够撤销这件事。在一些策略游戏中使用撤销,这样你就能够回滚那些你不喜欢的操做。在人们创造游戏时,这是必不可少的工具。不能撤销肥手指致使的错误的编辑器,确定会让游戏设计者恨你。
没有了命令模式,实现撤销很是困难,有了它,就是小菜一碟。假设咱们在制做单人回合制游戏,想让玩家能撤销移动,这样他们就能够集中注意力在策略上而不是猜想上。咱们已经使用了命令来抽象输入控制,因此每一个玩家的举动都已经被封装其中。举个例子,移动一个单位的代码可能以下: