0

I am faced with the following problem: in Pygame when controlling the direction of movement of the object manually an error appears due to the conversion of the values of the calculated coordinates into integers. How can I fix this error ? With small offsets, the error is significant, this can be seen when displaying the actual direction of movement and the calculated angle. My code:

import pygame as pg  
import math

py.init()  
clock = pg.time.Clock()  
SCREEN_WEIGHT = 1400  
SCREEN_HEIGHT = 1000  
screen = pg.display.set_mode((SCREEN_WEIGHT, SCREEN_HEIGHT))  
FPS = 50  
RED = (255, 0, 0)  
BLUE = (0, 0, 255)  
velocity = 20  

def get_angle(p1, p2):  
    dx = p1[0] - p2[0]  
    dy = p1[1] - p2[1]  
    if dx < 0:  
        angle = 2*math.pi - math.atan(-dy/dx) if dy >= 0 else math.atan(dy/dx)  
    elif dx > 0:  
        angle = math.atan(dy/dx) + math.pi if dy >= 0 else math.atan(-dx/dy) + math.pi/2  
    else:  
        angle = math.pi/2 if dy < 0 else 3*math.pi/2  
    if angle == 2*math.pi:  
        angle = 0  
    return angle  

class Car(pg.sprite.Sprite):  
    def __init__(self, im_name):  
        pg.sprite.Sprite.__init__(self)  
        self.image = pg.image.load(im_name).convert_alpha()  
        self.rect = self.image.get_rect(center=(SCREEN_WEIGHT/2, SCREEN_HEIGHT/2))  
        self.angle = 0  

    def move(self):
        sin_a = math.sin(self.angle)
        cos_a = math.cos(self.angle)
        keys = pg.key.get_pressed()
        prev_coords = [self.rect.centerx, self.rect.centery]
        self.rect.centerx = round(self.rect.centerx + velocity * cos_a)
        self.rect.centery = round(self.rect.centery + velocity * sin_a)
        if keys[pg.K_RIGHT]:
            self.angle += 0.1
        if keys[pg.K_LEFT]:
            self.angle -= 0.1
        mistake = get_angle(prev_coords, (self.rect.centerx, self.rect.centery))
        # индикация фактического направления движения
        pg.draw.line(screen, BLUE, (car.rect.centerx - 300*math.cos(mistake), car.rect.centery - 300*math.sin(mistake)),
                                   (car.rect.centerx + 300*math.cos(mistake), car.rect.centery + 300*math.sin(mistake)))

    def blitRotate(self):
        rotate_image = pg.transform.rotate(self.image, -math.degrees(self.angle))
        new_rect = rotate_image.get_rect(center=self.image.get_rect(topleft=self.rect.topleft).center)
        screen.blit(rotate_image, new_rect)


car = Car("car.png")
pg.display.update()
while True:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            exit()
    screen.fill((255, 255, 255))
    car.blitRotate()
    car.move()
    # actual direction of movement
    pg.draw.line(screen, RED, (car.rect.centerx, car.rect.centery), (car.rect.centerx + 80*math.cos(car.angle),
                                                                     (car.rect.centery + 80*math.sin(car.angle))))
    pg.display.update()
    clock.tick(FPS)
Dany
  • 1
  • A `pygame.Rect` object can only store integral data. See [Pygame doesn't let me use float for rect.move, but I need it](https://stackoverflow.com/questions/63468413/pygame-doesnt-let-me-use-float-for-rect-move-but-i-need-it/63468637#63468637). – Rabbid76 Oct 16 '22 at 14:49

0 Answers0