Prosta fizyka przeciągania, inne działanie podczas ruchu w lewo lub w prawo [duplikat]
Mój kod działa inaczej dla prędkości ujemnych niż dodatnich
Próbuję zaimplementować fizykę platformówki, gracz ma prędkość w kierunku X, prędkość jest zwiększana lub zmniejszana, gdy użytkownik naciśnie odpowiednio „A” lub „D”, lub ustawiana na 0, gdy gracz zderzy się ze ścianą.
Aby zasymulować tarcie o podłoże, prędkość X gracza jest mnożona przez „self.drag” (pływak mniejszy niż 1)
Spodziewałem się, że ten kod zmniejszy prędkość X graczy, z czasem zmniejszając ją pomijalnie blisko 0, bez faktycznego odwracania prędkości (tak jak odejmowanie wartości), zatrzymałoby to niekontrolowane przesuwanie się gracza, gdy użytkownik nie narzuca poleceń ruchu .
Działa to zgodnie z przeznaczeniem podczas ruchu w prawo, jednak podczas ruchu w lewo zachowuje się inaczej, podczas ruchu w lewo gracz wydaje się przez chwilę unosić w powietrzu, zanim się zatrzyma.
Oto kod, który pobiera dane wejściowe gracza, wewnątrz klasy odtwarzacza, uruchamia każdą klatkę:
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
Może koncepcja działa i źle ją zaimplementowałem? Istnieje kod kolizji, który może wpływać na prędkości w sposób, którego nie zauważyłem? Czy ten system działa inaczej dla prędkości dodatnich i ujemnych?
Dzięki! Każda pomoc jest bardzo ceniona
Odpowiedzi
Problem jest spowodowany tym, że pygame.Rectprzechowuje integralne współrzędne:
Wszystkie współrzędne obiektów Rect to liczby całkowite. […]
Składnik ułamkowy dx
i dy
jest tracony, gdy:
self.Rect.x += dx
self.Rect.y += dy
Musisz wykonywać obliczenia z dokładnością zmiennoprzecinkową. Dodaj atrybut x
i y
do klasy. Zwiększ atrybuty move
i zsynchronizuj Rect
atrybut:
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