Language agnostic 推还是拉?将按键转换为游戏中车辆的速度

Language agnostic 推还是拉?将按键转换为游戏中车辆的速度,language-agnostic,Language Agnostic,我应该在按下按键时将按键按到车辆上,还是车辆应该从发动机上拔下按键 我有一个车辆对象,它有位置、速度和加速度成员(除其他外)和一个更新方法,在此过程中,它根据其速度更新其位置,并根据其加速度更新其车辆速度 我有一个包含游戏循环的游戏对象,它调用车辆上的更新方法 如果玩家使用箭头键控制车辆,是否应按一个键设置加速(推)并释放一个键清除速度,或者如果按下加速键(拉),车辆是否应询问游戏引擎?我认为,按下意味着键盘控制模块需要了解车辆,而拉动意味着车辆需要了解特定的键盘控制 我认为一个相关的问题应该是

我应该在按下按键时将按键按到车辆上,还是车辆应该从发动机上拔下按键

我有一个车辆对象,它有位置、速度和加速度成员(除其他外)和一个更新方法,在此过程中,它根据其速度更新其位置,并根据其加速度更新其车辆速度

我有一个包含游戏循环的游戏对象,它调用车辆上的更新方法

如果玩家使用箭头键控制车辆,是否应按一个键设置加速(推)并释放一个键清除速度,或者如果按下加速键(拉),车辆是否应询问游戏引擎?我认为,按下意味着键盘控制模块需要了解车辆,而拉动意味着车辆需要了解特定的键盘控制


我认为一个相关的问题应该是这样的:是所有对象都知道所有其他对象,还是应该有一个严格的层次结构,这样对象可以向树上的其他对象询问/告诉事情,而不是向下(反之亦然)?

您应该尝试遵循一种模式。 您将所有密钥捕获代码放入一个InputManager,然后将需要对管理器中的输入寄存器作出反应的每个对象放入其中

管理器保存已订阅对象的列表,并在按键/按下时向其发送事件。 当对象被删除或“失去焦点”时,不要忘记取消订阅

这避免了轮询问题。
很少有例外情况需要轮询解决方案。

如果不更深入地了解游戏引擎的工作原理,就很难回答这个问题。话虽如此,我还是要试试看。在我看来,“按下键盘”的方法就像“事件”或“回调”策略。您在某个地方定义了一个类似于
def handle\u key\u event(key的名称):
的函数,每当发生key事件时都会调用该函数。这样做的好处是,从可读性的角度来看,您确切地知道在哪里处理关键事件。另一方面,每次按键都需要被视为原子操作。如果您需要在其他按键的状态上保留大量状态变量,以确定每次按下时要执行的操作,则可能会有点混乱

另一方面,如果拉动按键,则会在捕捉按键时引入固有的延迟。你捕捉关键事件的速度不会超过你的滴答/帧速。如果你的游戏运行得又快又好,这是很好的,但是你不希望当你的帧速率变慢时,用户界面变得神经质/迟钝


我想这是值得思考的。最重要的是,选择一个策略并坚持下去。例如,如果键盘事件是回调,不要对鼠标事件使用“拉”方法。在这里,一致性比正确性更重要。

在我看来,你的车辆不应该知道任何关于键盘、鼠标或游戏机的信息。而且您的输入处理代码也不应该知道您的车辆的任何信息。输入处理代码应该读取每个播放器的输入,并将其转换为特定于其上下文的某种指令。例如,如果玩家一驾驶汽车,他的指令可能包括方向盘旋转、加速度和制动值。而驾驶飞机的玩家可能需要俯仰、偏航等


通过将gamepad输入(或其他)转换为适当的指令类型,您可以将输入机制与游戏逻辑分离。通过这种级别的解耦,可以从网络输入创建一个“CarInstruction”。

@Joel:我同意-车辆不应该知道特定的硬件控制,输入处理代码不应该知道车辆的任何信息。应该有一些从钥匙映射到车辆的中间类。谢谢你的贡献

您要投票:

void UpdateVehicleFromInput()
{
   if (InputSystem()->IsKeyDown(key))
      DoSomething();
}
当然,这是“在你的更新循环中适合你设计的某个地方”,如果你想把这个地方称为“你的输入系统的一部分”或“你的游戏逻辑的一部分”或其他任何东西,那就把你自己搞垮

通过这种方式,您可以知道为什么要做某件事(因为钥匙已关闭),您可以简单地调整条件,您知道您正在做某件事一次又一次(并且您可以在没有分支的情况下更改它,特别是在车辆不存在的情况下),并且您知道您正在做某件事的时间(在你说之前或之后,对伤害做出反应,或者定位你的粒子效果,或者谁知道还有什么)

如果你真的在做跨平台的开发,抽象输入系统是有效的。对于随意的开发来说,这是非常不必要的(但是当你没有游戏设计思想来实现时,这是一种有趣的技术干扰)


与非理性的流行观点相反,轮询没有任何负面影响。处理器每秒执行>1B的操作,如果帧不相关(几乎唯一相关的cpu操作是N^2,其中N>100,并清空二级缓存,当然忙着等待磁盘访问)。轮询输入是O(1)。

假设我有两个键执行相同的操作(比如,WASD键和Arrows键都可以加速车辆)。为了避免2次加速,您必须在车辆中设置一点“由于按键按下此帧而导致我加速”(lame),或者您需要将键->游戏命令逻辑置于两者之间(这两者本身也有例外)。不是真正的jeff…如果(键==键a)加速=10;如果(键==向上箭头)加速度=10;或者我没有领会你的意思吗?是的,你把钥匙的操作从:V=V+10;变成了A=10;而延迟的V+=A;这正是“车辆中表示我已加速此帧的位”。现在如果你有另一个“刹车”钥匙,你现在卡在A=10或A=-10(除非你去添加更多的状态A_刹车)。(更糟糕的是,+或-10取决于观察员的注册顺序!)