Search code examples
pythonloopspygameexit

Why doesn't this loop run properly?


while g.running:
    for event in pygame.event.get():
        if event == pygame.QUIT:
            g.running = False
    g.run(Player_1)

quit()

when I run this loop it completely skips the for loop or just does it once and is too fast for me to be able to run and it just goes on to run. How do I make the loop work fine? https://github.com/maartenww/100daysOfCode_projectOne << for the full code.

Also, what g.run basically does is just update the game. So it draws and or moves all the sprites, draws the text unto the screen and does some calculations

class Game:
    def __init__(self):
        self.running = True

    def run(self, player_1):
        self.border_col(player_1)
        self.load_text(player_1)
        self.update_game(player_1)

    def update_game(self, player_1):
        clock.tick(FPS)
        gameDisplay.fill(black)
        gameDisplay.blit(self.xcolon, (0, 0))
        gameDisplay.blit(self.actual_x, (25, 0))
        gameDisplay.blit(self.ycolon, (0, 30))
        gameDisplay.blit(self.actual_y, (25, 30))
        gameDisplay.blit(self.acolon, (0, 60))
        gameDisplay.blit(self.actual_a, (25, 60))
        gameDisplay.blit(self.vcolon, (0, 90))
        gameDisplay.blit(self.actual_v, (25, 90))
        all_sprites.draw(gameDisplay)
        Player.move_player(player_1)
        Player.update_player(player_1)
        pygame.display.update()

Solution

  • I looked into your repo, and the revelant code is this, in player.py:

    def move_player(self):
        for event in pygame.event.get():
            # Player movement
            if (event.type == pygame.KEYDOWN):
                if (event.key == pygame.K_d):
                    self.player_acc = PLAYER_ACC
    
                if (event.key == pygame.K_a):
                    self.player_acc = -PLAYER_ACC
    
            if (event.type == pygame.KEYUP):
                if (event.key == pygame.K_d):
                    self.player_acc = 0
    
                if (event.key == pygame.K_a):
                    self.player_acc = 0
    

    Think about what happens in your main loop:

    while g.running:
        for event in pygame.event.get():
            if (event.type == pygame.QUIT):
                g.running = False
        g.run(Player_1)
    

    You get all events from the event queue, clearing it, and check for QUIT.

    Then you call g.run, which will call self.update_game, which will call Player.move_player, which will again get all events from the event queue and clear it.

    So when the QUIT event is in the event queue at the moment pygame.event.get() is called inside Player.move_player, it is practically lost, since you don't handle it in this for loop. When pygame.event.get() is then called again in main, the QUIT event is no longer in the queue (because calling event.get clears the queue).

    Basically, you should call 'event.get' only once per main loop iteration (the same is true for pygame.display.flip/pygame.display.update).

    Maybe change the loop in main to something like this:

    while g.running:
        for event in pygame.event.get():
            g.handle(event, Player_1)
        g.run(Player_1)
    

    add this to Game:

    def handle(self, event, player_1):
        if event.type == pygame.QUIT:
            self.running = False
        else:
            player_1.handle(event)
    

    and this to Player:

    def handle(self, event):
        # Player movement
        if (event.type == pygame.KEYDOWN):
            if (event.key == pygame.K_d):
                self.player_acc = PLAYER_ACC
    
            if (event.key == pygame.K_a):
                self.player_acc = -PLAYER_ACC
    
        if (event.type == pygame.KEYUP):
            if (event.key == pygame.K_d):
                self.player_acc = 0
    
            if (event.key == pygame.K_a):
                self.player_acc = 0
    

    and remove Player.move_player