1

Hello Stackoverflow Community, could someone help me with my problem. When I move to the left I am quite fast but when I want to go to the right it takes way to lang. I deleted the dt from my move function and the went the same speed. I changed the buttons but the problem seems only to occure when I use the +=. Does one of you dealt with the problem before and could help me?

import pygame
import time
import random

#0 = Menu, 1 = Game, 2 = Quit
game_state = 1
WHITE = (255, 255, 255)

class Player(pygame.sprite.Sprite):
    speed = 100

    def __init__(self, WIDTH):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("player.png")
        self.rect = self.image.get_rect()
        self.rect.center = (WIDTH / 2, 480)

    def move(self, keys, dt):
        if(keys[0]):
            self.rect.x += self.speed * dt
            print(self.speed)
            print(dt)
            print(self.rect.x)
        if(keys[1]):
            print(self.speed)
            print(dt)
            self.rect.x -= self.speed * dt
            print(self.rect.x)
        

class Main():

    prev_time = time.time()
    dt = 0

    #initalizing menu or game depending on variables
    def __init__(self):
        global game_state

        while game_state !=2:
            WIDTH, HEIGHT = 800, 600
            screen = self.initialize_pygame("Alien Slaughter", WIDTH, HEIGHT)

            self.all_sprites = pygame.sprite.Group()
            self.player = Player(WIDTH)
            self.all_sprites.add(self.player)

            if(game_state == 1):
                self.prev_time = time.time()
                self.game(screen, WIDTH, HEIGHT)

    #calculating deltatime
    def calc_deltatime(self):
        self.now = time.time()
        self.dt = self.now - self.prev_time
        self.prev_time = self.now

    #initializing pygame and create window
    def initialize_pygame(self, title, width, height):
        screen = pygame.display.set_mode((width, height))
        pygame.display.set_caption(title)
        icon = pygame.image.load("icon.png")
        pygame.display.set_icon(icon)
        pygame.init()
        return screen

    def handle_inputs(self, keys, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_d:
                keys[0] = True
            if event.key == pygame.K_a:
                keys[1] = True
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_d:
                keys[0] = False
            if event.key == pygame.K_a:
                keys[1] = False

    def game(self, screen, width, height):
        global game_state

        BLACK = (100, 100, 100)

        keys = [False, False]

        #Game loop
        while game_state == 1:
            #Process input (events)
            for event in pygame.event.get():
                #Check for Closing windows
                if event.type == pygame.QUIT:
                    game_state = 2
                self.handle_inputs(keys, event)
            
            self.calc_deltatime()

            self.player.move(keys, self.dt)
            #Update
            self.all_sprites.update()

            #Draw / render
            screen.fill(BLACK)
            self.all_sprites.draw(screen)
            pygame.display.update()


game = Main()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Naomi
  • 37
  • 9

1 Answers1

1

Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.

The coordinates for Rect objects are all integers. [...]

The fraction part of the coordinates gets lost when the movement is added to the coordinates of the Rect object. If this is done every frame, the position error will accumulate over time.

If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables respectively attributes and to synchronize the pygame.Rect object. round the coordinate and assign it to the location of the rectangle:

class Player(pygame.sprite.Sprite):
    speed = 100

    def __init__(self, WIDTH):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("player.png")
        self.rect = self.image.get_rect()
        self.rect.center = (WIDTH / 2, 480)
        self.x = self.rect.x

    def move(self, keys, dt):
        if keys[0]:
            self.x += self.speed * dt
        if keys[1]:
            self.x -= self.speed * dt
        self.rect.x = round(self.x)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174