有什么方法可以将我的 pygame 游戏的所有音效都包含到我的 .exe 文件中吗?

Is there any way to include all of the sound effects for my pygame game into my .exe with pyinstaller?

我制作了一个相对简单的 pygame 程序,有 9 种不同的音效(.wav 格式,如果此信息很重要的话)。使用 pyinstaller 模块将我的 main.py 转换为可执行文件时,有什么方法可以让声音效果包含在可执行文件中,或者我是否需要找到解决方法(例如因为在 C:\Program Files 路径中有音效)?

这是我的 .spec 文件的内容:

# -*- mode: python ; coding: utf-8 -*-


block_cipher = None

added_files = [('C:\Users\joshu\CursorHunters\Assets\Sounds\*.wav', 'Sounds')]

a = Analysis(['main.py'],
             pathex=[],
             binaries=[],
             datas=added_files,
             hiddenimports=[],
             hookspath=[],
             hooksconfig={},
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,  
          [],
          name='Cursor Hunters',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=False,
          disable_windowed_traceback=False,
          target_arch=None,
          codesign_identity=None,
          entitlements_file=None )

如您所见,声音位于\C:\Users\joshu\CursorHunters\Assets\Sounds,而我的main.py位于\C:\Users\joshu\CursorHunters

不是将 .wav 文件与 .exe 文件打包在一起,而是 returns 当 运行 没有 Assets\Sounds 文件夹时出现此错误目录:

这就是我在 sound_effects.py 中访问我的 .wav 文件的方式,然后是 main.py :

import os.path, pygame, sys

pygame.mixer.init()


class SoundEffects(object):


    def __init__(self,
                 EXE_LOCATION: str):
        self.explosion1 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "explosion1.wav"))
        self.explosion2 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "explosion2.wav"))
        self.explosion3 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "explosion3.wav"))
        self.explosion4 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "explosion4.wav"))
        self.explosion5 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "explosion5.wav"))
        self.explosion_sounds = (self.explosion1,
                                 self.explosion2,
                                 self.explosion3,
                                 self.explosion4,
                                 self.explosion5)
        self.gameover1 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "gameover1.wav"))
        self.gameover2 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "gameover2.wav"))
        self.gameover3 = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "gameover3.wav"))
        self.gameover_sounds = (self.gameover1,
                                self.gameover2,
                                self.gameover3)
        self.restart_sound = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", "restart.wav"))

main.py:

if getattr(sys, "frozen", False):  # Gets the directory of this script
    EXE_LOCATION = os.path.dirname(sys.executable)

else:
    EXE_LOCATION = os.path.dirname(os.path.realpath(__file__))

pygame.init()  # Initialises all the pygame contents
sound_effects = SoundEffects(EXE_LOCATION)  # Sound effects library

pyinstaller 文档指出:

The list of data files is a list of tuples. Each tuple has two values, both of which must be strings:

  • The first string specifies the file or files as they are in this system now.

  • The second specifies the name of the folder to contain the files at run-time.

这意味着如果你这样做:

('C:\Users\joshu\CursorHunters\Assets\Sounds\*.wav', 'Sounds')

然后在运行时那些 .wav 文件将位于相对目录 Sounds 中。这意味着您可以使用

访问它们
os.path.join(EXE_LOCATION, "Sounds", "explosion1.wav")

并且在 main.py 中,您应该提供主文件目录的路径(首先 import os 或使用任何其他方法获取目录名称)

sound_effects = SoundEffects(os.path.dirname(__file__))

还有一点改进是使用循环加载文件:

self.explosion_sounds = []
for i in range(1, 5 + 1):
    sound = pygame.mixer.Sound(os.path.join(EXE_LOCATION, "Assets", "Sounds", f"explosion{i}.wav"))
    self.explosion_sounds.append(sound)
self.explosion_sounds = tuple(self.explosion_sounds)