Search code examples
pythonmethodspygame

Is it possible (in pygame 1.9.6 / python 3.8.6) to move a character through a method?


So i am currently working on a simple game that until now only has the game loop and a class that is used to create the player. I want to keep my game loop clean so I decided that it would be a good idea to put the code used to move the character into a method 'move' which is called on the end of the game loop before the player is drawn. Currently when i run the code my character just sits on the spot and sometimes goes left/right if i spam the keys but it seems pretty random. This is the whole code, is the method not called correctly/every tick? I hope you guys can help me

import pygame

pygame.init()

screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
screenWidth, screenHeight = pygame.display.get_surface().get_size()
fpsclock = pygame.time.Clock()

def screen_refresh():
    screen.fill((0, 0, 0))
    player.move()
    player.draw()
    pygame.display.update()
    fpsclock.tick(60)

class player:

    def __init__(self, vel):
        self.img = pygame.image.load('player.png')
        #self.walk = [pygame.image.load('player_1.png'), pygame.image.load('player_2.png')]
        self.width, self.height = self.img.get_size()       
        self.x = (screenWidth - self.width) * 0.5
        self.y = screenHeight - self.height

        self.vel = vel

        self.xchange = 0

    def move(self):

        for event in pygame.event.get():

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_d:
                    self.xchange += self.vel
                if event.key == pygame.K_a:
                    self.xchange -= self.vel

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_d:
                    self.xchange -= self.vel
                if event.key == pygame.K_a:
                    self.xchange += self.vel

        self.x += self.xchange

        if self.x < 0:
            self.x = 0

        elif self.x > (screenWidth - self.width):
            self.x = screenWidth - self.width

    def draw(self):

        screen.blit(self.img, (self.x, self.y))

player = player(5)

running = True
while running:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:
            running = False

    screen_refresh()

Solution

  • Your code doesn't work, because you've multiple calls to pygame.event.get(). pygame.event.get() gets all event messages and remove them from the queue. Hence just one of the loops will receive the events, the other loop gets nothing. This causes that the events seems to be missed.

    Get the list of events once in the main application loop and pass the list to the functions and methods where they are handled:

    def screen_refresh(events):  # events: list of events 
        screen.fill((0, 0, 0))
        player.move(events)      # pass events to player.move
        player.draw()
        pygame.display.update()
        fpsclock.tick(60)
    
    class player:
        # [...]
    
        def move(self, events): # events: list of events 
    
            for event in events:
                # [...]
    
    running = True
    while running:
    
        events = pygame.event.get()  # get list of events
        for event in events:
    
            if event.type == pygame.QUIT:
                running = False
    
        screen_refresh(events)       # pass events to screen_refresh