【问题标题】:How to stop player accelerating when it shouldn't be如何在不应该​​的情况下阻止玩家加速
【发布时间】:2013-08-06 02:14:13
【问题描述】:

在主游戏循环中,按下移动键会改变玩家状态:

for event in pygame.event.get():
    elif event.type == KEYDOWN:
        if event.key == K_w:
            player.state = "moving_up"
    elif event.type == KEYUP:
        if event.key == K_w:
            player.state = "stopping_up"

当调用播放器更新方法时,它会根据状态移动:

def update(self):
    if self.state == "idle":
        self.displacement = self.displacement
    else:            
        if self.state == "moving_up":
            self.displacement[1] = self.displacement[1] - self.speed
        if self.state == "stopping_up":
            s = self.rect.top % 32
            self.displacement[1] = self.displacement[1] - s
            self.state = "idle"
        new_position = self.rect.move(self.displacement)
        self.rect = new_position

当我移动播放器时,每次按键后速度似乎都在加快。例如第一次移动速度还可以,但下一次比以前更快,滚雪球……

这是右移时(速度),(位移)的打印输出:

idle
0.02 [0.7200000000000003, 0]
0.02 [0.7400000000000003, 0]
0.02 [0.7600000000000003, 0]

...

0.02 [1.2400000000000007, 0]
0.02 [1.2600000000000007, 0]
0.02 [19.26, 0]
idle

你可以看到,在最后一个动作中,位移大大增加了。

知道为什么会这样吗?


更新,这里是另一个打印出来的 s:

0.02 [1.1600000000000006, 0]
0.02 [1.1800000000000006, 0]
0.02 [1.2000000000000006, 0]
0.02 [1.2200000000000006, 0]
0.02 [1.2400000000000007, 0]
0.02 [1.2600000000000007, 0]
s: remainder to next tile 18
0.02 [19.2600000000000007, 0]

看起来 s 导致了位移的跳跃。

这是故意的,因为它应该找到到下一个图块的距离并让玩家移动到那里。 (瓷砖是 32x32),s 是直到下一个的余数。

似乎我需要修改运动代码,因为它没有达到我的预期。

【问题讨论】:

  • 这里显而易见的是,最终值使用的是s,而不是self.speed。也打印出s(即,它使用"stopping_up" 条件)。如果不是这样,我们没有足够的信息来解决这个问题。
  • 同意,需要查看s的值。另外,为什么在计算s 时使用%(模运算符)?值跳跃是有道理的,因为 s 将在 self.rect.top 传递 32 的倍数后跳跃
  • @tom10 我已经更新了帖子,看起来 s 是罪魁祸首。
  • 好的,我想我会写这个作为答案,只是为了解决这个问题。

标签: python pygame game-physics


【解决方案1】:

这里显而易见的是,最终值使用的是s,而不是self.speed

附带说明:
通常,在进行物理模拟时,最好使用物理单位。我的意思是,以秒为单位考虑时间,而不是循环传递等,并以此为单位工作。如果您想使用速度增加距离,请使用dist += dt*speed,而不是dist += speed。通常这涉及到额外的乘法,但这是非常值得的。否则,您将有效地使用时间单位,以便 dt=1.,这是可能的,但比起初看起来更棘手。

例如,在这里,您要添加self.displacement[1] - self.speed,然后在下一行添加self.displacement[1] = self.displacement[1] - s,其中s 似乎是一个距离。尽管从数量上看,这两件事看起来很相似,但在物理上它们却大不相同。这里有一个错误并不奇怪,因为整个事情很难理解。

【讨论】:

  • 我每 dt 都在更新物理特性,很难计算出每 dt 穿过瓷砖宽度的正确速度。假设我的时间步长是 0.01,我希望玩家在 0.20 秒内移动 32 像素(一个瓷砖)。那是 160 像素/秒。每次我调用更新函数时,玩家的位移 (s) = 800.0 * dt?
  • 在计算中使用时间的一个好处是您可以编写标准方程。 V=D/T或D=V T。你说你想要 V = 32p/(0.20sec)=160p/sec。那么 dD = VdT = (160p/sec)*(0.01sec) = 1.6p:如果你想移动得更远,你需要不同的速度或更多的时间。请注意,当您调用此 20x (0.2/.01) 时,您会移动所需的 32p。我猜你从 (160p/sec)/(0.2sec) 得到 800,但请注意这个单位是 800p/(sec^2),这不是一个距离(并且有真正的单位来做这种检查是使用实时的另一个优势)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多