【发布时间】:2022-01-12 01:46:35
【问题描述】:
我正在阅读 Robert Nystrom 的 Game Programming Patterns,并且对命令模式有疑问。
在Configuring Input 部分的第一个示例中,if/else 语句将游戏操作硬编码到控制台按钮:
void InputHandler::handleInput()
{
if (isPressed(BUTTON_X)) jump();
else if (isPressed(BUTTON_Y)) fireGun();
else if (isPressed(BUTTON_A)) swapWeapon();
else if (isPressed(BUTTON_B)) lurchIneffectively();
}
由于键映射在编译时是硬编码的,因此用户无法在运行时根据自己的喜好更改/配置它们。然后引入命令模式作为解决此问题的方法:
// ***Command interface***
class Command
{
public:
virtual ~Command() {}
virtual void execute() = 0;
};
// ***Concrete commands***
class JumpCommand : public Command
{
public:
virtual void execute() { jump(); }
};
class FireCommand : public Command
{
public:
virtual void execute() { fireGun(); }
};
[...]
// ***Input handler***
class InputHandler
{
public:
void handleInput();
// Methods to bind commands...
private:
Command* buttonX_;
Command* buttonY_;
Command* buttonA_;
Command* buttonB_;
};
void InputHandler::handleInput()
{
if (isPressed(BUTTON_X)) buttonX_->execute();
else if (isPressed(BUTTON_Y)) buttonY_->execute();
else if (isPressed(BUTTON_A)) buttonA_->execute();
else if (isPressed(BUTTON_B)) buttonB_->execute();
}
问题
我不清楚命令模式如何帮助使输入映射在运行时可配置。 GUI 中必须有一些表允许用户为每个操作类型指定一个键:
我认为我们需要使用 new 关键字来初始化指针,例如buttonX_ = new JumpCommand;,但我不确定如何创建绑定,我不明白为什么不能在运行时使用 if/else 来完成。
我对 JS 有一些经验,而对 C++ 没有经验,所以如果熟悉这两种语言的人能帮助我充实/理解这个示例中发生的事情,我将不胜感激。
【问题讨论】:
-
正如您所说,您需要通过初始化指针来设置绑定,因此您可能有一组默认绑定,您可以将按钮 x 分配给跳转等等。然后你可能有一种方法让用户配置绑定,例如他们可以选择左手设置,所以你只需将指针重新分配给新命令。如果您有不同的界面,使用命令也会有所帮助,例如使用键盘时您可能会跳到空格键等。
-
@Hovercraft Full Of Eels,我经常遇到这两种语言的命令模式示例,由于设计模式不是特定于语言的,我想也许有人在 Java 中使用过命令模式来解决这个问题将能够阐明一些问题。不过,我并没有违反社区准则的意思,我已经删除了这个标签。
-
很公平。感谢您的回复。
-
@Ian4264,是的,我想看看重新分配是如何完成的。目前,我想象我们在 GUI 中有某种键设置表,其中每行的第一列是命令名称,例如“跳转”,第二列是某种输入,允许用户指定他们想要用来调用该命令的键,例如空格键。但是为什么我们需要命令模式在运行时进行这些绑定呢?将这个表转换成
格式的地图/字典然后使用简单的 if/else 来执行 if(isPressed(keymap["jump"])) jump() 是否就足够了? ——
标签: c++ oop design-patterns game-development