在游戏中模拟 gravity/jump - 问题

Simulating gravity/jump in game - issue

我正在使用游戏引擎在 python 中制作我自己的 3D 游戏。我需要模拟跳跃 and/or 重力,但我 运行 遇到了一个问题:计算是即时的,我的角色没有移动,比如没有动画、瞬间闪烁,或者(例如,如果我的 for 循环中有一个更大的数字)它需要 wayyyy 更多的时间,真的很慢,它滞后和一切,努力计算跳跃。我有两个极端,并且 none 有效,所以我想找到一种方法来实现我的跳跃。我所能做的就是:

player.y +=
#can be -=, =, +=, etc.

那么,您有什么方法可以做到这一点吗?我并不是真的在问一个具体的问题,我只是想收集一些想法!甚至不需要给出预先完成的示例,只需提出您的想法,例如:使用这个、尝试使用这个公式、这个函数等。

添加一些细节:我已经尝试过的。

这是我尝试过的主要解决方案,非常基础:

velocity = 3
def input(key):
    global velocity
    if key == "space":
        for i in range(7):
            print(velocity)
            player.y += velocity
            velocity -= 1
        velocity = 3

这很酷,因为你的身高必须是 3,然后是 2,然后是 1(随着你的能量降低而减速),然后你加上 -1、-2、-3(重力加速度),然后回到你的起点。完美的 !但是,正如所说,立即完成。所以如果我试试这个:

velocity = 3
def input(key):
    global velocity
    if key == "space":
        for i in range(61):
            print(velocity)
            player.y += velocity
            velocity -= 0.1
        velocity = 3

同样,立即完成。如果我尝试越来越高的间隔,在某些时候我只会让它滞后,没有中间正确完成的地方

您首先需要知道当前时间步长是多少,因为如果您的帧之间有 2 毫秒和 20 毫秒,您需要调整每一步进入玩家 y 位置的量。

那么除了位置之外,还有一个玩家速度变量会很棒。然后,您必须决定一个速度,以便在发生跳跃时立即增加玩家的速度,并且每个时间步长都会因重力而增加一点加速度。

稍微偏离主题:您不想将函数命名为 input(),因为它会掩盖内置的 input() 函数。


问题是你改变了速度,然后在一个循环中迭代地递减它 因为 python 的方式(或大多数编程语言,就此而言) 有效,程序执行仅在 完成执行您的 input() 函数后才转到“在屏幕上绘制”步骤 。因此,当您按下某个键时,您的程序将执行以下操作:

  • 绘制框架并监听按键
  • 按下键!调用 input() 来处理按键(假设 player.y = 0
  • 密钥是space吗?进入循环
    • velocity = 3。将玩家向上移动 3。减速度。 player.y = 3
    • velocity = 2。将玩家向上移动 2。减速度。 player.y = 5
    • ...等等,直到退出循环
    • player.y又是0
  • 再画一帧。玩家在他们开始的同一个地方,所以看起来什么都没发生。

当您向循环添加迭代时,此过程需要更长的时间(因此您会看到滞后),但本质上会发生相同的事情。

要解决此问题,您需要在绘制框架的函数中添加重力效果。例如,您可以在按下跳跃键时设置一个标志,如果您有一个函数 step() 在模拟的每个时间步调用,您可以检查是否设置了标志,然后处理这种情况

def user_input(key):
    global jump_velocity, is_player_jumping
    if key == "space":
        is_player_jumping = True
        jump_velocity = 3

def step():
    global jump_velocity, is_player_jumping
    if is_player_jumping:
        player.y += jump_velocity
        jump_velocity -= 0.1

        if player.y == 0: # Player is back on the ground
            is_player_jumping = False 

这样,你只需要在绘制下一帧之前稍微改变玩家的位置,就可以真正看到动画。