Einfache Drag-Physik, die sich beim Bewegen nach links oder rechts anders verhält [Duplikat]
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
Das Problem wird verursacht, weil pygame.Rectintegrale Koordinaten gespeichert werden:
Die Koordinaten für Rect-Objekte sind alle Ganzzahlen. [...]
Die Bruchkomponente von dx
und dy
geht 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 x
und y
-Attribut hinzu. Erhöhen Sie die Attribute move
und synchronisieren Sie das Rect
Attribut:
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