Simple drag physics, acting differently when moving left or right [duplicate]

守給你的承諾、 提交于 2020-12-07 06:40:27

问题


My code is acting differently for negative velocities than it is positive ones

I'm trying to implement platformer physics, the player has velocity in the X direction, the velocity is increased or decreased when the user presses "A" or "D" respectively, or set to 0 when the player collides with a wall.

To simulate friction with the ground, the X Velocity of the player is multiplied with "self.drag" (a float less than 1)

I expected this code to reduce the players X Velocity, over time reducing it neglibly near to 0, without actually reversing the velocity (like subtracting a value would), this would stop the player sliding about uncontrollably when the user isn't imputing movement commands.

This works as intended when moving right, however when moving left it acts differently, when moving to the left the player seems to continue floating for a while before coming to a stop.

Here's the code that takes player input, inside the player class, run each frame:

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

Maybe the concept works and I've implemented it incorrectly? There's collision code that may be affecting the velocities in ways I haven't noticed? Does this system work differently for positive and negative velocities?

Thanks! Any help is much appreciated


回答1:


The issue is caused, because pygame.Rect stores integral coordinates:

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

The fraction component of dx and dy is lost when you do:

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

You have to do the calculations with floating point accuracy. Add an x ​​and y attribute to the class. Increment the attributes in move and synchronize the Rect attribute:

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 


来源:https://stackoverflow.com/questions/64977010/simple-drag-physics-acting-differently-when-moving-left-or-right

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!