간단한 드래그 물리학, 왼쪽 또는 오른쪽으로 이동할 때 다르게 작동 [중복]

Nov 24 2020

내 코드는 음의 속도와 양의 속도에 대해 다르게 작동합니다.

저는 플랫 포머 물리를 구현하려고합니다. 플레이어는 X 방향으로 속도를 가지고 있으며, 사용자가 각각 "A"또는 "D"를 누르면 속도가 증가 또는 감소하거나 플레이어가 벽과 충돌 할 때 0으로 설정됩니다.

지면과의 마찰을 시뮬레이션하기 위해 플레이어의 X Velocity에 "self.drag"(1보다 작은 부동 소수점)를 곱합니다.

나는이 코드가 플레이어의 X Velocity를 감소시킬 것으로 예상했습니다. 시간이 지남에 따라 속도를 실제로 반전하지 않고 거의 0에 가깝게 줄였습니다 (값을 빼는 것과 같이). 이것은 사용자가 이동 명령을 대치하지 않을 때 플레이어가 제어 할 수 없게 미끄러지는 것을 막을 것입니다. .

이것은 오른쪽으로 이동할 때 의도 한대로 작동하지만 왼쪽으로 이동할 때 다르게 작동하며 왼쪽으로 이동할 때 플레이어는 정지하기 전에 잠시 동안 계속 떠있는 것처럼 보입니다.

다음은 플레이어 클래스 내에서 각 프레임을 실행하는 플레이어 입력을받는 코드입니다.

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

개념이 작동하고 잘못 구현했을 수 있습니까? 내가 알아 차리지 못한 방식으로 속도에 영향을 미칠 수있는 충돌 코드가 있습니까? 이 시스템은 포지티브 및 네거티브 속도에 대해 다르게 작동합니까?

감사! 어떤 도움이라도 대단히 감사합니다

답변

1 Rabbid76 Nov 24 2020 at 04:59

pygame.Rect적분 좌표를 저장 하기 때문에 문제가 발생 합니다.

Rect 객체의 좌표는 모두 정수입니다. [...]

다음 을 수행하면 dx및 의 분수 구성 요소 dy가 손실됩니다.

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

부동 소수점 정확도로 계산을 수행해야합니다. 클래스에 xand y속성을 추가하십시오 . 의 속성을 증가시키고 속성을 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