简单的拖动物理,向左或向右移动时表现不同

Simple drag physics, acting differently when moving left or right

我的代码对负速度的作用与对正速度的作用不同

我正在尝试实现平台物理,玩家在 X 方向上有速度,当用户分别按下“A”或“D”时速度增加或减少,或者当玩家碰撞时设置为 0有墙。

为了模拟与地面的摩擦,玩家的 X 速度乘以“self.drag”(小于 1 的浮点数)

我预计这段代码会降低玩家的 X 速度,随着时间的推移,它会微不足道地降低到接近 0,而不会实际反转速度(就像减去一个值一样),这会阻止玩家在用户不在时不受控制地滑动'输入移动命令。

这在向右移动时按预期工作,但是在向左移动时它的行为不同, 向左移动时,播放器似乎继续漂浮了一段时间才停止。

这是在玩家内部 class、运行 每帧接受玩家输入的代码:

dx = 0
if pygame.key.get_pressed()[pygame.K_a]:
        dx -= self.speed
if pygame.key.get_pressed()[pygame.K_d]:
        dx += self.speed

# to slow down horizontal movement
self.vx *= self.drag

# Add change in velocity to total velocity
self.vx += dx
self.vy += dy

也许这个概念可行,但我实施不正确? 有可能以我没有注意到的方式影响速度的碰撞代码? 该系统对于正速度和负速度的工作方式是否不同?

谢谢! 非常感谢任何帮助

问题是因为pygame.Rect存储了积分坐标:

The coordinates for Rect objects are all integers. [...]

当您这样做时,dxdy 的小数部分会丢失:

self.Rect.x += dx
self.Rect.y += dy

您必须以浮点精度进行计算。给class添加一个xy属性。增加 move 中的属性并同步 Rect 属性:

class Player:
    def __init__(self, color):
        self.Rect = pygame.Rect([50, 50], [30, 50])
        self.x = self.Rect.x
        self.y = slef.Rect.y
        # [...]

    def move(self, dx, dy, platforms):
        # Test for collisions with platforms

        # handle movement on the X axis
        self.x += dx
        self.Rect.x = round(self.x)
        for platform in platforms:
            if self.Rect.colliderect(platform.Rect):
                if dx > 0:
                    self.Rect.right = platform.Rect.left
                if dx < 0:
                    self.Rect.left = platform.Rect.right
                self.x = self.Rect.x
                # Reset velocity when collision with wall
                self.vx = 0

        # handle movement on the Y axis
        self.Rect.y += dy
        self.Rect.y = round(self.y)
        for platform in platforms:
            if self.Rect.colliderect(platform.Rect):
                if dy > 0:
                    self.Rect.bottom = platform.Rect.top
                if dy < 0:
                    self.Rect.top = platform.Rect.bottom
                self.y = self.Rect.y
                # Reset velocity when collision with floor or roof
                self.vy = 0

        # return correctly collided rect to draw()
        return self.Rect