1

My game in pygame works fine, but when I bundle it into an exe with pyinstaller, it breaks. I've discovered that it's because the quit() function is only usable with python, but my code breaks when I use pygame.quit() i.e. I get an error for trying to draw on the window after it has been closed.

Here is the current closing code:

if event.type == pygame.QUIT:
                done = True
                quit()

And here is the full game code:

import pygame , random

pygame.init()

WIDTH , HEIGHT = 900 , 500
WIN = pygame.display.set_mode((WIDTH , HEIGHT))
pygame.display.set_caption('game')

BLOCK_MOVEMENT_TIMER_EVENT = pygame.USEREVENT + 1
BLOCK_MOVEMENT_TIME_DELAY = 15
pygame.time.set_timer(BLOCK_MOVEMENT_TIMER_EVENT , BLOCK_MOVEMENT_TIME_DELAY)

BLOCK_CREATE_TIMER_EVENT = pygame.USEREVENT + 2
BLOCK_CREATE_TIME_DELAY = 1500
pygame.time.set_timer(BLOCK_CREATE_TIMER_EVENT, BLOCK_CREATE_TIME_DELAY)

FPS = 60

#colors
WHITE = (255 , 255 ,255)
BLACK = (0 , 0 , 0)
RED = (255 , 0 , 0)

BIGFONT = pygame.font.Font('Retro.ttf' , 65)
SMALLFONT = pygame.font.Font('Retro.ttf' , 20)

FLOOR = pygame.Rect(0 , 400 , 900 , 5)

class Player:
    def __init__(self):
        self.size = 20
        self.x = 75
        self.y = 380
        self.jumping = False
        self.fall = False
        self.update_rect()
        self.score = 0

    def update_rect(self):
        self.rect = pygame.Rect(self.x , self.y , self.size , self.size)

    def jump(self):
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_SPACE] and not self.fall:
            self.jumping = True
        
        if self.jumping:
            self.y -= 3
            if self.y < 300:
                self.y = 300
                self.fall = True
                self.jumping = False

        if self.fall:
            self.y += 3
            if self.y > 380:
                self.y = 380
                self.fall = False
        
        self.update_rect()

player = Player()

class Obstacles:
    def __init__(self , width , height):
        self.x = 900
        self.y = HEIGHT - height - 100
        self.width = width
        self.height = height
        self.update_rect()

    def update_rect(self):
        self.rect = pygame.Rect(self.x , self.y , self.width , self.height)

def move_obstacles(obstacle_list):
    for obstacle in obstacle_list:
        obstacle.x -= 3
        if obstacle.x < -100:
            obstacle_list.pop(0)
            player.score += 1
        
        obstacle.update_rect()

def add_obstacle(obstacle_list):
    obstacle1 = Obstacles(20 , 40)
    obstacle2 = Obstacles(75 , 20)
    obstacle3 = Obstacles(35 , 35)
    obstacle4 = Obstacles(50 , 25)
    obstacle5 = Obstacles(80 , 10)
    obstacle6 = Obstacles(40 , 20)
    obstacle7 = Obstacles(20 , 30)

    obstacle_options = [obstacle1 , obstacle2 , obstacle3 , obstacle4 , obstacle5 , obstacle6 , obstacle7]

    obstacle_list.append(obstacle_options[random.randint(0,6)])

def is_game_over(obstacle_list):
    for obstacle in obstacle_list:
        if player.rect.colliderect(obstacle):
            return True

def game_over():
    done = False
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    player.score = 0
                    main()
                    break
                if event.key == pygame.K_e:
                    done = True
                    quit()

        WIN.fill(BLACK)
        game_over = BIGFONT.render('GAME OVER', False, WHITE)
        WIN.blit(game_over , (200 , 175))

        instructions = SMALLFONT.render(f'You scored {player.score}. Press R to restart or E to exit' , False , WHITE)
        WIN.blit(instructions , (145 , 290))

        pygame.display.flip()

def draw_window(obstacle_list , is_game_over):
    WIN.fill(BLACK)
    pygame.draw.rect(WIN , WHITE , FLOOR)

    pygame.draw.rect(WIN , WHITE , player.rect)

    for obstacle in obstacle_list:
        pygame.draw.rect(WIN , RED , obstacle.rect)
    
    score_counter = BIGFONT.render(f'SCORE  {player.score}', False, (255, 255, 255))
    WIN.blit(score_counter , (240 , 100))

    pygame.display.flip()

def main():
    clock = pygame.time.Clock()
    
    obstacle_list = []

    done = False
    while not done:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_e:
                    done = True
                    quit()
            if event.type == BLOCK_MOVEMENT_TIMER_EVENT:
                move_obstacles(obstacle_list)
            if event.type == BLOCK_CREATE_TIMER_EVENT:
                add_obstacle(obstacle_list)

        draw_window(obstacle_list , is_game_over(obstacle_list))
        player.jump()
        is_game_over(obstacle_list)

        if is_game_over(obstacle_list):
            game_over()
            done = True
        pygame.display.flip()

if __name__ == '__main__':
    main()

EDIT: I figured out that I can fix it by adding import sys at the beginning and call sys.exit() after pygame.quit()

birdiechap
  • 55
  • 1
  • 5

0 Answers0