1

I've been making a game using pygame, and I wanted to turn it into an exe, using pyinstaller, to share it with a friend. When I tested it out on my computer it worked fine, no problems, but when I sent it to him he said that all it did was show a black screen (I had console disabled) and then quit. After some testing, I found out that the issue was with the imports the game needed, and, after some more testing, I found out that the import that was causing the problem was the one that imported the program that handles the game's dungeons (all the other imports worked fine). However, now I can't figure out what could be the problem that also can't be applied to one of the other imports that do work. So now I don't know if it's a problem with my coding, how Pyinstaller turns it into an exe, some combination of both, or something completely different all together. So if someone could please help me figure out what I'm doing wrong, it would be a big help, thank you!

The versions I'm using are Python v 3.6.8, Pygame v 1.9.6, and Pyinstaller v 3.6. There's over 1,000 lines total in the dungeon's code, but here's the main portion of it:

from random import randint
from DungeonPiecesXL import *
from PlayerClass import Player
from AudioClass import Audio
pygame.init()

WIN_WIDTH = 900
WIN_HEIGHT = 600

# Might need to have 'win' imported.
win = "" #pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) #Place holder data

colors = pygame.color.THECOLORS
font = pygame.font.SysFont("arjulianopentype", 40)

# Made it so changing colors are easier.
bgColor = colors['grey79'] #(201,201,201)
wallColor = colors['dimgray'] #[105, 105, 105]
floorColor = colors['burlywood'] #(222, 184, 135, 255)
exitColor = colors['cyan'] #(0, 255, 255, 255)

# changes the background.
#win.fill(bgColor)
#pygame.display.flip()

# X: East (right) is positive; West (left) is negative
# Y: North (up) is negative; South (down) is positive
# Starts at these coords, before getting set to the proper coords.
x = 414
y = 264

hallWidth = 81
mini = False # Tells if the mini version needs to be used or not.

room = "" #Rooms(win) #Place holder data
hall = "" #Halls(win) #Place holder data
audio = Audio()

# List that holds if a room has the stairs and, if so, where in the room they are.
# Defult is false, with the stairs in the center of the room.
exit = [False, 164, 164]
pause = False
clock = pygame.time.Clock()

openEnds = [] # List of open ended locations.
sequence = [] # Used to hold the order the rooms are generated.
wallList = [] # Used to keep track of walls.
pathList = [] # Used to keep track of paths the player can move on.
wallExep = [] # List of wall exeptions, contains 'seals' for now, but other things might get added later.

class Dungeon:
    
    def __init__(self, window, plChara):
        # Maybe have a module that sets the values for the number of floors and dungeon image set.
        global win
        global room
        global hall
        
        win = window
        pygame.display.set_caption("Dungeon Map")
        
        room = Rooms(win)
        hall = Halls(win)
        
        self._plChara = plChara # Carries over the player's data.
    
    def startDungeon(self):
        global win
        global x
        global y
        global mini
        global pause
        
        audio.setMusic('dung.mid')
        
        reset() #Sets all the values to what they need to be when starting out.
        
        plFace = "s" # Direction the player is facing. Defaults to south.
        standing = True # Allows for checks to see if the player is standing or moving.
        floor = 1 # Player starts on floor 1.
        holdX = x # Holds the x value when the mini map is being checked.
        holdY = y # Holds the y value when the mini map is being checked.
        
        placement()
        
        self._plChara.dunCoordSet(True)
        pygame.display.flip()
        #print(openEnds)
        #print(sequence)
        
        # Window loop
        run = True
        while run:
            clock.tick(30)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
            
            # Redraws the map.
            reDraw()
            
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            # Figure out why the player shows when the map is mini and multiple directions are held.
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        
            keys = pygame.key.get_pressed()
            
            # If, and when, enemies get added, their movement will be tied to the player's movement.
            # Add checks for diagnal bounderies.
            # Just disabled diagnal movement for now.
            if keys[pygame.K_w] and not keys[pygame.K_d] and not keys[pygame.K_a] and not keys[pygame.K_s] and not mini:
                # North
                # Allows the player to face walls.
                if self._plChara._hitBoxN.collidelist(wallList) == -1 or (self._plChara._hitBoxN.collidelist(wallList) != -1 and\
                self._plChara._hitBoxN.collidelist(pathList) != -1) and pathList[self._plChara._hitBoxN.collidelist(pathList)].contains(self._plChara._hitBoxN) and\
                self._plChara._hitBoxN.collidelist(wallExep) == -1 and not self._plChara._hitBox.colliderect(room._stairs):
                    for i in range(0,4):
                        y += 20 #Offsets y to the correct cordinates.
                        plFace = "n"
                        standing = False
                        reDraw() # Removes the smudging of the character.
                        self._plChara.movePlayer(0,0,plFace,standing)
                else:
                    plFace = "n"
                    self._plChara.movePlayer(0,0,plFace,standing)
                    
            if keys[pygame.K_d] and not keys[pygame.K_w] and not keys[pygame.K_s] and not keys[pygame.K_a] and not mini:
                # East
                if self._plChara._hitBoxE.collidelist(wallList) == -1 or (self._plChara._hitBoxE.collidelist(wallList) != -1 and\
                self._plChara._hitBoxE.collidelist(pathList) != -1) and pathList[self._plChara._hitBoxE.collidelist(pathList)].contains(self._plChara._hitBoxE) and\
                self._plChara._hitBoxE.collidelist(wallExep) == -1 and not self._plChara._hitBox.colliderect(room._stairs):
                    for i in range(0,4):
                        x -= 20 #Offsets x to the correct cordinates.
                        plFace = "e"
                        standing = False
                        reDraw()
                        self._plChara.movePlayer(0,0,plFace,standing)
                else:
                    plFace = "e"
                    self._plChara.movePlayer(0,0,plFace,standing)
                    
            if keys[pygame.K_s] and not keys[pygame.K_d] and not keys[pygame.K_a] and not keys[pygame.K_w] and not mini:
                #South
                if self._plChara._hitBoxS.collidelist(wallList) == -1 or (self._plChara._hitBoxS.collidelist(wallList) != -1 and\
                self._plChara._hitBoxS.collidelist(pathList) != -1) and pathList[self._plChara._hitBoxS.collidelist(pathList)].contains(self._plChara._hitBoxS) and\
                self._plChara._hitBoxS.collidelist(wallExep) == -1 and not self._plChara._hitBox.colliderect(room._stairs):
                    for i in range(0,4):
                        y -= 20
                        plFace = "s"
                        standing = False
                        reDraw()
                        self._plChara.movePlayer(0,0,plFace,standing)
                else:
                    plFace = "s"
                    self._plChara.movePlayer(0,0,plFace,standing)
                    
            if keys[pygame.K_a] and not keys[pygame.K_w] and not keys[pygame.K_s] and not keys[pygame.K_d] and not mini:
                #West
                if self._plChara._hitBoxW.collidelist(wallList) == -1 or (self._plChara._hitBoxW.collidelist(wallList) != -1 and\
                self._plChara._hitBoxW.collidelist(pathList) != -1) and pathList[self._plChara._hitBoxW.collidelist(pathList)].contains(self._plChara._hitBoxW) and\
                self._plChara._hitBoxW.collidelist(wallExep) == -1 and not self._plChara._hitBox.colliderect(room._stairs):
                    for i in range(0,4):
                        x += 20
                        plFace = "w"
                        standing = False
                        reDraw()
                        self._plChara.movePlayer(0,0,plFace,standing)
                else:
                    plFace = "w"
                    self._plChara.movePlayer(0,0,plFace,standing)
                    
            if not (keys[pygame.K_w] or keys[pygame.K_d] or keys[pygame.K_a] or keys[pygame.K_s]) and not mini:
                # Used to display the player when not moving.
                self._plChara.movePlayer(0,0,plFace,standing)
                
            elif (keys[pygame.K_w] and keys[pygame.K_d]) or (keys[pygame.K_s] and keys[pygame.K_d]) or (keys[pygame.K_s] and keys[pygame.K_a]) or\
               (keys[pygame.K_w] and keys[pygame.K_a]) or (keys[pygame.K_w] and keys[pygame.K_s]) or (keys[pygame.K_a] and keys[pygame.K_d]) and not mini:
                # Used to keep the player displayed even if several directions are held.
                self._plChara.movePlayer(0,0,plFace,standing)
            
            standing = True
            text = font.render("F" + str(floor), True, colors['black'])
            win.blit(text, (10,5)) # Tells the player what floor they're on.
            
            pygame.display.flip()
            pygame.time.delay(100) #150 is used for now, might change it later.
            # Good delay numbers: 100; 125; 150
            
            '''
            # Used to quickly get a new layout to test different rooms/ hallways.
            if keys[pygame.K_r]:
                floorTrans()
                reset()
                plFace = "s"
                standing = True
                placement()
                #print(sequence)
                pygame.event.clear() #Prevents 'r' from auto firing multiple times.
            
            # Allows 'sequence' to be checked.
            if keys[pygame.K_f]:
                print(sequence)
                #print(keys)
            #'''
            
            if keys[pygame.K_TAB]:
                # Opens the mini map.
                # Will need to make the mini map bigger at some point.
                if mini:
                    x = holdX
                    y = holdY
                    mini = False
                    pause = False
                elif not mini:
                    # Sets the hold values to what 'x' and 'y' are so they can be changed back when done.
                    holdX = x
                    holdY = y
                    x = 414
                    y = 264
                    mini = True
                    pause = True
                    
                pygame.event.clear() #Prevents 'tab' from auto firing multiple times. Doesn't actually work.
            
            # Resets everything if the player reaches the exit.
            if self._plChara._hitBox.colliderect(room._stairs):
                if floor == 3: # Number of floors in dungeon.
                    return
                else:
                    floorTrans()
                    reset()
                    plFace = "s"
                    standing = True
                    floor += 1
                    placement()
                    #print(sequence)
        
        pygame.quit() 

All the code past this are functions that help it generate a map layout. As I stated before, I tested the all the imports, and they all work fine. Also, one last thing, if the code looks a bit off, it would be because I had to change it from a stand alone program into a class in order to make it work for the game (which I feel like might be where the problem might be coming from, but I'm not sure). If I need to post more of the code, I can. Once again, thank you!

  • Welcome to Stackoverflow ElectroTerra! Please have a look into this question and the different answers. Pyinstaller doesn't automatically include all module imports you import in your python files. For some it might be enough to add the script (if it's your own) to the folder of the exe, for other modules (installed via pip e.g.) you might have to edit the spec file pyinstaller generates and re-compile your exe based on the spec file. https://stackoverflow.com/questions/7436132/pyinstaller-spec-file-importerror-no-module-named-blah/47337389#47337389 – Cribber Aug 14 '20 at 08:29
  • 1
    Does this answer your question? [PyInstaller, spec file, ImportError: No module named 'blah'](https://stackoverflow.com/questions/7436132/pyinstaller-spec-file-importerror-no-module-named-blah) – Cribber Aug 14 '20 at 08:41

0 Answers0