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()