python - 如何让物体永远在同一高度弹跳

标签 python pygame game-physics pyglet

我试图让球永远弹跳,始终在同一高度,就像弹跳中没有能量损失一样。

我不知道为什么,根据我所做的,随着时间的推移它会弹得更高,或者每次跳跃都会弹得更低。我的期望是,每次弹跳时它都应该始终达到相同的高度,而不是更高或更低。

这是我的代码(代码位于 pyglet 中,但即使您不了解该库,它也很容易阅读)。在这里,一个正方形从屏幕中间掉落,用箭头标记,我希望立方体在地板上弹起,并在返回时精确地达到原始高度:

import pyglet


class Polygon(object):
    def __init__(self, vertices, color, velocity=0, acceleration=-600):
        self.vertices = vertices
        self.y_idx = 1
        self.num_vertices = int(len(self.vertices) // 2)
        self.colors = color * self.num_vertices
        self.velocity = velocity
        self.acceleration = acceleration
        self.bottom_edge = 0

    def draw(self):
        self.vertex_list = pyglet.graphics.vertex_list(self.num_vertices,
                                                       ("v2f", self.vertices),
                                                       ("c3B", self.colors))
        self.vertex_list.draw(pyglet.gl.GL_POLYGON)

    def move_by_offset(self, offset):
        for i in range(1, len(self.vertices), 2):
            self.vertices[i] += offset  # only modify y values

    def bounce(self, dt):
        if self.vertices[self.y_idx] < self.bottom_edge:
            self.velocity = abs(self.velocity)
            return True
        return False

    def update(self, dt):
        # move
        self.move_by_offset(self.velocity * dt)
        # check if bounce
        self.bounce(dt)
        # accelerate
        self.velocity += self.acceleration * dt


class GameWindow(pyglet.window.Window):
    def __init__(self, objects=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.objects = objects

    def update(self, dt):
        for obj in self.objects:
            obj.update(dt)

    def on_draw(self):
        self.clear()
        for obj in self.objects:
            obj.draw()


class Game(object):
    def __init__(self, w=400, h=400, title="My game", resizable=False):
        self.w = w
        self.h = h
        objects = [
            # square
            Polygon(vertices=[w/2-20, h/2, w/2-20, h/2+40, w/2+20, h/2+40, w/2+20, h/2],
                    color=[0, 128, 32],  # green
                    velocity=0,
                    acceleration=-6000),
            # arrow, marks exactly how high the square should bounce
            Polygon(vertices=[w/2, h/2, w/2+40, h/2+20, w/2+30, h/2, w/2+40, h/2-20],
                    color=[255, 255, 0], # yellow
                    velocity=0,
                    acceleration=0)
        ]
        self.window = GameWindow(objects, self.w, self.h, title, resizable)

    def update(self, dt):
        self.window.update(dt)


if __name__ == "__main__":
    game = Game(resizable=False)
    pyglet.clock.schedule_interval(game.update, 1/120)
    pyglet.app.run()

我尝试了不同的更新顺序,例如在弹跳后改变速度之前根据加速度修改速度,或者甚至在弹跳后根本不加速(这似乎效果最好),但弹跳仍然不准确并且不断改变高度:

    def update2(self, dt):
        # move
        self.move_by_offset(self.velocity * dt)
        # accelerate
        self.velocity += self.acceleration * dt
        # check if bounce
        self.bounce(dt)

    def update3(self, dt):
        # move
        self.move_by_offset(self.velocity * dt)
        # check if bounce
        bounced = self.bounce(dt)
        if not bounced:
            # accelerate (only if no bounce happened)
            self.velocity += self.acceleration * dt

我什至尝试了更复杂的方法:创建 2 个 dt,一个在反弹之前,一个在反弹之后,并进行 2 个加速更新,但这也不起作用。

你们能帮帮我吗?对于如此简单的场景,如何对游戏物理进行编程?

最佳答案

数值积分很难!由于您可以轻松地精确求解一维弹道方程,因此请执行以下操作:计算

y1=y0+v0*dt+g*dt*dt/2
v1=v0+g*dt

这是velocity Verlet method在恒定加速度的简单情况下。如果y1<0 ,您可以求解二次方程来找出何时它反弹并从该点重新开始积分(速度取负)。

如果您想结合更复杂的物理原理,同时保持数值精确,请考虑速度变量的居中。通过错开它可以获得更好的精度 - 在定义位置的点之间的中间时间点定义它,给出类似的 leapfrog method .

对于保守力,一种非常不同的方法是定义球的总能量,并根据球的高度必须有多少动能来移动它。即使如此,您也必须将上述更正包含在 dt*dt 中。以避免最大高度附近的数值问题。

关于python - 如何让物体永远在同一高度弹跳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56301279/

相关文章:

python - 如何通过正则表达式检查url格式?

python - Django - 计算created_at和done_at之间的平均时间

python - PyGame:文本未出现

java - 敌方物体不会移动 LibGDX

java - Android文字游戏的保存技巧

python - 为什么我无法获得预期输出 'BBB' ?

python - 用python数据框中的列表替换python中的缺失值

python - 缩放 Sprite 大小

python - wxPython 或 pygame 用于简单的纸牌游戏?

java - 有人可以解释如何实验重力值吗?