Einfache Drag-Physik, die sich beim Bewegen nach links oder rechts anders verhält [Duplikat]

Nov 24 2020

Mein Code verhält sich bei negativen Geschwindigkeiten anders als bei positiven

Ich versuche, die Plattformerphysik zu implementieren. Der Spieler hat eine Geschwindigkeit in X-Richtung. Die Geschwindigkeit wird erhöht oder verringert, wenn der Benutzer "A" oder "D" drückt, oder auf 0 gesetzt, wenn der Spieler mit einer Wand kollidiert.

Um die Reibung mit dem Boden zu simulieren, wird die X-Geschwindigkeit des Spielers mit "self.drag" (ein Float kleiner als 1) multipliziert.

Ich hatte erwartet, dass dieser Code die X-Geschwindigkeit des Spielers im Laufe der Zeit vernachlässigbar auf 0 reduziert, ohne die Geschwindigkeit tatsächlich umzukehren (wie das Subtrahieren eines Wertes). Dies würde den Spieler davon abhalten, unkontrolliert herumzurutschen, wenn der Benutzer keine Bewegungsbefehle unterstellt .

Dies funktioniert wie beabsichtigt, wenn Sie sich nach rechts bewegen. Wenn Sie sich jedoch nach links bewegen, verhält es sich anders. Wenn Sie sich nach links bewegen, scheint der Spieler eine Weile weiter zu schweben, bevor er zum Stillstand kommt.

Hier ist der Code, mit dem Spielereingaben innerhalb der Spielerklasse für jeden Frame ausgeführt werden:

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

Vielleicht funktioniert das Konzept und ich habe es falsch implementiert? Gibt es einen Kollisionscode, der die Geschwindigkeiten auf eine Weise beeinflusst, die ich nicht bemerkt habe? Funktioniert dieses System für positive und negative Geschwindigkeiten unterschiedlich?

Vielen Dank! Jede Hilfe wird sehr geschätzt

Antworten

1 Rabbid76 Nov 24 2020 at 04:59

Das Problem wird verursacht, weil pygame.Rectintegrale Koordinaten gespeichert werden:

Die Koordinaten für Rect-Objekte sind alle Ganzzahlen. [...]

Die Bruchkomponente von dxund dygeht verloren, wenn Sie Folgendes tun:

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

Sie müssen die Berechnungen mit Gleitkommagenauigkeit durchführen. Fügen Sie der Klasse ein xund y-Attribut hinzu. Erhöhen Sie die Attribute moveund synchronisieren Sie das RectAttribut:

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