When converting py to exe It wont run wav and png files

210 views Asked by At

My game runs fine from text editors as a py file but when I convert it to executable using cx_Freeze and pyinstaller I cant run the exe file it outputs it gives me this error :

Traceback (most recent call last):
File "egg_rampage.py", line 12, in <module>
File "img_sound.py", line 7, in __init__
pygame.error: Unable to open file 'music/scream.wav'
[9292] Failed to execute script egg_rampage

I have tried everything I found on the Internet: -using the complete path to the files -using init.py at the end of the files -installing the exe through a setup file -putting the audio and image files on a separate module

I dont know why this happens, because I tried doing it with another game and it worked, I dont know what is wrong with this one, below I put my game code so that you can see.

import pygame
import sys
import random
import time
from game_settings import Settings
from space_ship import SpaceShip
from img_sound import ImageSound


pygame.init()

imgs = ImageSound()

red = (255,0,0)
green = (0,255,0)
white = (255,255,255)
turquoise = (175,238,238)

crash_sound = imgs.scream
imgs.music

pygame.display.set_caption('Egg Rampage')
pygame.display.set_icon(imgs.caricon)
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.scr_width, 
ai_settings.scr_height))
ship = SpaceShip(screen, ai_settings)
screen_rect = screen.get_rect()

pause = False




def crash():
    pygame.mixer.music.stop()
    pygame.mixer.Sound.play(crash_sound)
    pygame.time.delay(600)
    exorcista_img = imgs.exorcista
    screen.blit(exorcista_img, [0,0])

    pygame.display.update()

    time.sleep(2)

    intro(ai_settings, screen)



def intro(ai_settings, screen):

    intro = True    
    while intro:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
        sys.exit()          

    intro_bg = imgs.intro_bg
    screen.blit(intro_bg, (0,0))                            


    button(screen, 170 , 200, 150, 50, ' PLAY', green, turquoise, "play")   
    button(screen, 170 , 270, 150, 50, ' QUIT', red, turquoise, "quit")

    highscore = load_highscores()
    button(screen, 170, 340, 150, 50, 'HIGHSCORE:' + str(highscore) , red, red) 
    pygame.display.update() 


def button(screen, x, y, w, h, text, a_color, i_color, action=None):

    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()

    if x+w > mouse[0] > x and y+h > mouse[1] > y:
    pygame.draw.rect(screen, i_color, (x, y, w, h))
    if click[0] == 1 and action != None:
        if action == "quit":
        sys.exit()
    elif action == "play":
        run_game()
    elif action == "continue":
        unpause()
    else:
    pygame.draw.rect(screen, a_color, (x, y, w, h))

    font = pygame.font.Font('freesansbold.ttf' , 20)
    small_text2 = font.render(text, True, (255,255,255))
    small_text2_rect = small_text2.get_rect()   
    small_text2_rect.center = (x + (w/2), y + (h/2))    
    screen.blit(small_text2, small_text2_rect)


def egg(egg_startx, egg_starty):

    egg_img = imgs.egg_img
    for egg_x in egg_startx:
    screen.blit(egg_img, [egg_x, egg_starty])


def display_score(dodged):

    font = pygame.font.SysFont(None, 25)
    text = font.render("Your score: " + str(len(dodged)), True, white)
    screen.blit(text, (0,0))

    current_highscore = font.render("Highscore: " + str(load_highscores()), True , white)
    screen.blit(current_highscore, (0, 25))

    filename = 'highscores.txt'
    highscore = load_highscores()

    if len(dodged) > highscore :
        highscore = len(dodged)
        with open(filename, '+r') as f:
        f.write(str(len(dodged)))


def load_highscores():
    filename = 'highscores.txt'
    with open(filename, '+r') as f:
        try:
        highscore = int(f.read())
    except:
    highscore = 0   
    return highscore

def paused(ai_settings, screen):

    pygame.mixer.music.pause()

    while pause:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
        sys.exit()                                  

        font = pygame.font.Font('freesansbold.ttf', 50)
    text = font.render('PAUSED', True, (255,255,255))
    text_rect = text.get_rect(center = (ai_settings.scr_width/2, 100))
    screen.blit(text , text_rect)           

    button(screen, 170 , 200, 150, 50, ' CONTINUE', green, turquoise, "continue")   
    button(screen, 170 , 270, 150, 50, ' QUIT', red, turquoise, "quit")     
    pygame.display.update() 


def unpause():
    global pause
    pygame.mixer.music.unpause()
    pause = False



def run_game():
    global pause

    pygame.mixer.music.play(-1)


    ship = SpaceShip(screen, ai_settings)
    egg_startx = [random.randrange(0, ai_settings.scr_width)]
    egg_starty = -600
    egg_count = 1
    ai_settings.egg_speed = 3
    dodged = []

    y = 0
    x = 0
    x1 = 0 
    y1 = -500

    screen.blit(ai_settings.bg, ai_settings.bg.get_rect())

    while True: 

   for event in pygame.event.get():
       if event.type == pygame.QUIT:
        sys.exit()

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT:
            ship.pressed_left = True
        elif event.key == pygame.K_RIGHT:
        ship.pressed_right = True
        elif event.key == pygame.K_p:
        pause = True
        paused(ai_settings, screen)

    elif event.type == pygame.KEYUP:
        if event.key == pygame.K_LEFT:
        ship.pressed_left = False
        elif event.key == pygame.K_RIGHT:
        ship.pressed_right = False

    y1 += 2
    y += 2

    screen.blit(ai_settings.bg, (x,y))
    screen.blit(ai_settings.bg, (x1,y1))
    if y > 500:
        y = -500
    if y1 > 500:
    y1 = -500



        display_score(dodged)

    #crash against egg  
     egg(egg_startx, egg_starty)
         egg_center = float(egg_starty)
     egg_center += ai_settings.egg_speed
     egg_starty = egg_center

     if egg_starty > ai_settings.scr_height:
    egg_starty = -600
    egg_startx = []

         for x in range(egg_count):
             new_egg = random.randrange(0, ai_settings.scr_width - 75)
         egg_startx.append(new_egg)

             ai_settings.egg_speed += 0.1
         dodged.append(egg)

         if len(dodged) % 10 == 0:
             if egg_count < 3:
             egg_count += 1

     if ship.rect.y < egg_starty + 75 and ship.rect.y + 50 > egg_starty:
             for egg_x in egg_startx:
         if ship.rect.x < egg_x + 75 and ship.rect.x + 50 > egg_x:
             crash()

     #crash against screen edges        
      if ship.rect.left <= screen_rect.left or ship.rect.right >= screen_rect.right:
          crash()

     ship.blitme()  
     ship.update()                  

     pygame.display.update()

intro(ai_settings, screen)      
run_game()

And here is the module containing the files:

import pygame

pygame.init()

class ImageSound():
    def __init__(self):
    self.scream = pygame.mixer.Sound("music/scream.wav")
    self.music = pygame.mixer.music.load("music/mario_kart_music.wav")
    self.caricon = pygame.image.load("images/caricon.png")
    self.exorcista = pygame.image.load("images/exorcista.bmp")
    self.intro_bg = pygame.image.load("images/intro_background.png")
    self.egg_img = pygame.image.load("images/egg.bmp")

And this is the setup file i used:

import cx_Freeze
import os
os.environ['TCL_LIBRARY'] = r"C:\Users\User\AppData\Local\Programs\Python\Python37\tcl\tcl8.6"
os.environ['TK_LIBRARY'] = r"C:\Users\User\AppData\Local\Programs\Python\Python37\tcl\tk8.6"

executables = [cx_Freeze.Executable("egg_rampage.py")]

cx_Freeze.setup(
name = "Egg Rampage",
options = {"build_exe": {"packages":["pygame"],
"include_files": 
[r"C:\Users\User\Desktop\egg_rampage\music\mario_kart_music.wav", 
r"C:\Users\User\Desktop\egg_rampage\music\scream.wav", 
r"C:\Users\User\Desktop\egg_rampage\images\background.png", 
r"C:\Users\User\Desktop\egg_rampage\images\caricon.png", 
r"C:\Users\User\Desktop\egg_rampage\images\egg.bmp", 
r"C:\Users\User\Desktop\egg_rampage\images\exorcista.bmp", 
r"C:\Users\User\Desktop\egg_rampage\images\intro_background.png", 
r"C:\Users\User\Desktop\egg_rampage\images\rocket.bmp", "highscores.txt"]} },
executables = executables
)

I hope you can find the problem please.

1

There are 1 answers

0
Jean-François Fabre On

from the documentation:

include_files: list containing files to be copied to the target directory;

it is expected that this list will contain strings or 2-tuples for the source and destination;** the source can be a file or a directory (in which case the tree is copied except for .svn and CVS directories); the target must not be an absolute path

I suppose that the files you're passing are copied flat in the destination directory, not in sub-directory.

to include music and images folders I would just do:

cx_Freeze.setup(
name = "Egg Rampage",
options = {"build_exe": {"packages":["pygame"],
"include_files": 
[r"C:\Users\User\Desktop\egg_rampage\music",
r"C:\Users\User\Desktop\egg_rampage\images","highscores.txt"]} },
executables = executables
)

for files only, specify target dir

cx_Freeze.setup(
name = "Egg Rampage",
options = {"build_exe": {"packages":["pygame"],
"include_files": 
[(r"C:\Users\User\Desktop\egg_rampage\music\mario_kart_music.wav","music"),

and so on with other files (tuple: original file, destination relative dir in the package)

BTW the program must still be run from the main script path else, since your code is using relative paths, this won't work. Something like:

MODULE_FILE = sys.executable if getattr(sys, 'frozen', False) else __file__  # to support both frozen and normal script
PROGRAM_DIR = os.path.abspath(os.path.dirname(MODULE_FILE))

then:

image_file = os.path.join(PROGRAM_DIR,"image","mario.png")