単純な抗力物理学、左または右に移動すると異なる動作をする[複製]

Nov 24 2020

私のコードは、負の速度に対して正の速度とは異なる動作をします

プラットフォーマーの物理を実装しようとしています。プレーヤーの速度はX方向です。ユーザーが「A」または「D」を押すと速度が増減するか、プレーヤーが壁に衝突すると速度が0に設定されます。

地面との摩擦をシミュレートするために、プレーヤーのX速度に「self.drag」(1未満のフロート)を掛けます。

このコードは、プレーヤーのX速度を低下させ、時間の経過とともに速度を実際に逆転させることなく(値を減算するように)、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

浮動小数点の精度で計算を行う必要があります。クラスにxandy属性を追加します。の属性をインクリメントし、属性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