Я, как и многие новички в создании игр, столкнулся с проблемой как поделиться готовым проектом с друзьями, у которых не установлен Python.
На недостаток обучалок по созданию игр на Pygame не пожалуешься, но мне не удалось найти подробной инструкции как собрать единый exe-файл, для запуска которого не требуется держать рядом папку с изображениями и игровыми звуками.
Из множества библиотек, собирающих проекты в exe, выбрал PyInstaller. Его оказалось достаточно, чтобы справиться с задачей. Опишу все пошагово (для Windows).
Установка PyInstaller
В командной строке пишем:
Создание spec-файла (файла спецификации)
Pyinstaller создает приложение, выполняя содержимое файла спецификации.
Чтобы создать spec-файл, через командную строку в папке с проектом набираем:
Флаг --onefile создает файл спецификации, который позволит упаковать всё необходимое в один exe-файл.
Получаем файл mygame.spec
Редактирование spec-файла
Теперь нужно правильно настроить spec-файл. Открываем spec-файл в текстовом редакторе.
В качестве первого атрибута для объекта класса Analysis передается имя py-файла, который нужно скомпилировать.
Атрибут pathex отвечает за путь к папке проекта.
В списке datas указываются файлы, которые нужно загрузить для работы приложения (изображения, музыка/звуки, шрифты). Datas — это список кортежей. Каждый кортеж имеет два элемента строкового типа:
В экземпляре класса EXE редактируем:
name — имя exe-файла.
console — отвечает за то, будет ли вызываться консоль при запуске приложения (True) или нет (False).
icon — содержит путь к иконке игры.
Редактирование путей к файлам в коде
В коде до загрузки файлов необходимо добавить функцию, которая позволит программе найти необходимые для работы файлы независимо от своего расположения (подсмотрено тут).
При запуске приложения PyInstaller распаковывает данные во временную папку и сохраняет путь к ней в переменной среды _MEIPASS.
Функция resource_path проверяет создана ли временная папка, и если да, то возвращает путь к ней для дальнейшей загрузки файлов. В противном случае (например, если запустить код через интерпретатор) функция вернет тот путь, который в неё передали (то есть путь к папке проекта с игрой).
Чтобы получить путь к файлу
При этом, если файл вынесен в отдельную папку проекта, то и во временной папке нужно создавать соответствующий подкаталог (см. редактирование параметра datas).
Далее загружаем файл:
С музыкой и шрифтами аналогично.
Создание exe
В командной строке вводим:
Готово! Exe-файл находится в папке dist.
На недостаток обучалок по созданию игр на Pygame не пожалуешься, но мне не удалось найти подробной инструкции как собрать единый exe-файл, для запуска которого не требуется держать рядом папку с изображениями и игровыми звуками.
Из множества библиотек, собирающих проекты в exe, выбрал PyInstaller. Его оказалось достаточно, чтобы справиться с задачей. Опишу все пошагово (для Windows).
Установка PyInstaller
В командной строке пишем:
pip install pyinstaller
Создание spec-файла (файла спецификации)
Pyinstaller создает приложение, выполняя содержимое файла спецификации.
Чтобы создать spec-файл, через командную строку в папке с проектом набираем:
pyi-makespec --onefile mygame.py
Флаг --onefile создает файл спецификации, который позволит упаковать всё необходимое в один exe-файл.
Получаем файл mygame.spec
Редактирование spec-файла
Теперь нужно правильно настроить spec-файл. Открываем spec-файл в текстовом редакторе.
block_cipher = None
a = Analysis(['mygame.py'],
pathex=['C:/Users/1/Desktop/Python/test'],
binaries=[],
datas=[('Images/image.png', 'Images'),
('Music/track.mp3', 'Music'),
('font.ttf', '.')],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='mygame',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False, icon='C:/Users/1/Desktop/Python/test/icon.ico')
В качестве первого атрибута для объекта класса Analysis передается имя py-файла, который нужно скомпилировать.
Атрибут pathex отвечает за путь к папке проекта.
В списке datas указываются файлы, которые нужно загрузить для работы приложения (изображения, музыка/звуки, шрифты). Datas — это список кортежей. Каждый кортеж имеет два элемента строкового типа:
- Первый — путь до файла, который нужно загрузить.
- Второй указывает имя папки для хранения файла во время выполнения программы
('.' — означает, что файл будет помещен во временную папку без подкаталога).
В экземпляре класса EXE редактируем:
name — имя exe-файла.
console — отвечает за то, будет ли вызываться консоль при запуске приложения (True) или нет (False).
icon — содержит путь к иконке игры.
Редактирование путей к файлам в коде
В коде до загрузки файлов необходимо добавить функцию, которая позволит программе найти необходимые для работы файлы независимо от своего расположения (подсмотрено тут).
def resource_path(relative):
if hasattr(sys, "_MEIPASS"):
return os.path.join(sys._MEIPASS, relative)
return os.path.join(relative)
При запуске приложения PyInstaller распаковывает данные во временную папку и сохраняет путь к ней в переменной среды _MEIPASS.
Функция resource_path проверяет создана ли временная папка, и если да, то возвращает путь к ней для дальнейшей загрузки файлов. В противном случае (например, если запустить код через интерпретатор) функция вернет тот путь, который в неё передали (то есть путь к папке проекта с игрой).
Чтобы получить путь к файлу
- если файл лежит в той же папке, что и py-файл, пишем:
path = resource_path('image.png')
- если файл вынесен в отдельную папку проекта, пишем:
path = resource_path(os.path.join('Folder', 'image.png'))
При этом, если файл вынесен в отдельную папку проекта, то и во временной папке нужно создавать соответствующий подкаталог (см. редактирование параметра datas).
Далее загружаем файл:
img = pygame.image.load(path)
С музыкой и шрифтами аналогично.
Создание exe
В командной строке вводим:
pyinstaller mygame.spec
Готово! Exe-файл находится в папке dist.
Замечание про функции quit() и exit()
Если в коде вашей игры в качестве функций выхода используются quit() или exit(), то скомпилированное приложение работать не будет.
Эти функции включены, чтобы новичкам было проще ориентироваться в коде, и предназначены только для использования в интерпретаторе. На самом деле для их корректной работы требуется загрузить модуль site.
Стандартным способом выйти из программы является использование sys.exit().
Более подробно здесь.
Эти функции включены, чтобы новичкам было проще ориентироваться в коде, и предназначены только для использования в интерпретаторе. На самом деле для их корректной работы требуется загрузить модуль site.
Стандартным способом выйти из программы является использование sys.exit().
Более подробно здесь.