为使用 pygame 模块制作的 python 游戏文件创建可执行安装程序时出错
Error while creating an executable installer for a python game file made using pygame module
我使用 Python 的 pygame 模块制作了一个游戏。我想制作该文件的可执行安装程序,这样任何人都可以玩该游戏,而无需安装 python 或 pygame。我使用模块 cx-freeze 为我的游戏文件创建可执行文件。我将用于制作可执行安装程序的代码存储在名为 setup.py 的文件中,并将其保存在与游戏文件和游戏所需的所有其他文件相同的目录中,例如图像、声音等
当我执行命令 python setup.py build
来创建可执行文件时,我开始收到 警告 并在最后发生此错误:
Traceback (most recent call last):
File "setup.py", line 5, in <module>
cx_Freeze.setup(
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\dist.py", line 342, in setup
distutils.core.setup(**attrs)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\core.py", line 148, in setup
dist.run_commands()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\dist.py", line 966, in run_commands
self.run_command(cmd)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\dist.py", line 985, in run_command
cmd_obj.run()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\command\build.py", line 135, in run
self.run_command(cmd_name)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\cmd.py", line 313, in run_command
self.distribution.run_command(command)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\dist.py", line 985, in run_command
cmd_obj.run()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\dist.py", line 217, in run
freezer.Freeze()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\freezer.py", line 645, in Freeze
self._WriteModules(fileName, self.finder)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\freezer.py", line 536, in _WriteModules
sourcePackageDir = os.path.dirname(module.file)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\ntpath.py", line 223, in dirname
return split(p)[0]
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\ntpath.py", line 185, in split
p = os.fspath(p)
TypeError: expected str, bytes or os.PathLike object, not NoneType
显示的警告是:
running build
running build_exe
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\setuptools\distutils_patch.py:25: UserWarning: Distutils was imported before Setuptools. This usage is discouraged and may exhibit undesirable behaviors or errors. Please use Setuptools' objects directly or at least import Setuptools first.
warnings.warn(
C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\pygame\examples\chimp.py:32: SyntaxWarning: "is" with a literal. Did you mean "=="?
if colorkey is -1:
C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\pygame\tests\test_utils\__init__.py:162: SyntaxWarning: "is not" with a literal. Did you mean "!="?
(rect.left is not 0 and [(rect.left-1, rect.top)] or []) +
copying c:\users\armaan barak\appdata\local\programs\python\python38\python38.dll -> build\exe.win-amd64-3.8\python38.dll
copying c:\users\armaan barak\appdata\local\programs\python\python38\vcruntime140.dll -> build\exe.win-amd64-3.8\vcruntime140.dll
copying c:\users\armaan barak\appdata\local\programs\python\python38\python3.dll -> build\exe.win-amd64-3.8\python3.dll
copying C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\bases\Console.exe -> build\exe.win-amd64-3.8\SpaceInvader2.exe
*** WARNING *** unable to create version resource
version must be specified
安装文件中的代码:
import cx_Freeze
executable = [cx_Freeze.Executable('SpaceInvader2.py')]
cx_Freeze.setup(
name="Space Invaders 2",
options={
"build_exe": {
"packages": [
"pygame",
"random",
"math",
"pygame.mixer",
"time"
],
"include_files": [
"spaceship.png",
"space.png",
"home_screen.png",
"ammunition.png",
"alien.png",
"alien2.png",
"alien3.png",
"alien4.png",
"player.png",
"settings.png",
"controls.png",
"game_over.png",
"background.wav",
"laser.wav",
"explosion.wav"
]
}
},
executables=executable
)
游戏文件中的代码:
import pygame
import random
import math
from pygame import mixer
import time
# Game Screen Initialization
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Loading Images
icon = pygame.image.load('spaceship.png')
game_background = pygame.image.load('space.png')
home_screen_img = pygame.image.load('home_screen.png')
bullet = pygame.image.load('ammunition.png')
alien_img = pygame.image.load('alien.png')
alien_img2 = pygame.image.load('alien2.png')
alien_img3 = pygame.image.load('alien3.png')
alien_img4 = pygame.image.load('alien4.png')
player_img = pygame.image.load('player.png')
settings_img = pygame.image.load('settings.png')
controls_img = pygame.image.load('controls.png')
game_over_img = pygame.image.load('game_over.png')
# Loading sounds
mixer.music.load('background.wav')
mixer.music.play(-1)
bullet_sound = mixer.Sound('laser.wav')
explosion_sound = mixer.Sound('explosion.wav')
# Title and Icon
pygame.display.set_caption('Space Invader')
pygame.display.set_icon(icon)
# Bullet variables
bullet_x = 0
bullet_y = 480
bullet_x_change = 0
bullet_y_change = 4
bullet_state = 'ready'
# Player variables
player_x = 370
player_y = 480
player_x_change = 0
# Enemy variables
enemy_img = []
enemy_x = []
enemy_y = []
enemy_x_change = []
enemy_y_change = []
num_of_enemies = 13
# Creating 10 enemy objects
for i in range(num_of_enemies):
enemy_img.append(random.choice([alien_img, alien_img2, alien_img3, alien_img4]))
enemy_x.append(random.randint(0, 735))
enemy_y.append(random.randint(50, 200))
enemy_x_change.append(2)
enemy_y_change.append(40)
# Score variables
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 24)
over_font = pygame.font.Font('freesansbold.ttf', 80)
text_X = 10
text_y = 10
# Game Functions
def show_score(x, y):
score = font.render('Score: ' + str(score_value), True, (165,240,67))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render('GAME OVER!', True, (255, 0, 0))
screen.blit(over_text, (160, 250))
def player(x, y):
screen.blit(player_img, (x, y))
def enemy(x, y, i):
screen.blit(enemy_img[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = 'fire'
screen.blit(bullet, (x + 16, y + 10))
def is_collision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY-bulletY, 2)))
return distance < 27
# Button colors and fonts
color = (0, 0, 0)
color_light = (100,149,237)
color_dark = (138,43,226)
# Fonts
game_name_font = pygame.font.SysFont("Chiller", 140)
btn_font = pygame.font.SysFont('Corbel Bold', 34)
random_font = pygame.font.SysFont('Arial', 60)
info_btn = pygame.font.SysFont('Century Gothic', 24)
controls_font = pygame.font.SysFont('Consolas', 15)
credits_btn = pygame.font.SysFont('Consolas', 18)
# Texts
game_text = game_name_font.render('Space Invaders!', True, (255,255,0))
play_text = btn_font.render('Play Game', True, color)
controls_text = btn_font.render('Controls', True, color)
credits_text = btn_font.render('Credits', True, color)
settings_text = btn_font.render('Settings', True, color)
quit_text = btn_font.render('Quit Game', True, color)
version_text = btn_font.render('Version 2.8', True, (255, 255, 255))
back_text = btn_font.render('Go Back', True, color)
under_development_text = random_font.render('This area is under development', True, (0, 0, 0))
# Controls text
controls_1 = controls_font.render('Left Arrow : Spaceship moves Left', True, (124, 252, 0))
controls_2 = controls_font.render('Right Arrow : Spaceship moves Right', True, (124, 252, 0))
controls_3 = controls_font.render('Spacebar : Shoots bullets', True, (124, 252, 0))
# Credits text
credits_line_1 = credits_btn.render("The games first version was made while learning from the pygame video", True, (255, 255, 255))
credits_line_2 = credits_btn.render("of FreeCodeCamp.org. The successive updates in version 1 and 2 are", True, (255, 255, 255))
credits_line_3 = credits_btn.render("made by Armaan Barak. No external code was copied. But help was taken", True, (255, 255, 255))
credits_line_4 = credits_btn.render("from google. Images and icons shown this game are taken from freepik.com", True, (255, 255, 255))
credits_line_5 = credits_btn.render("and flaticon.com respectively. The images were resized from", True, (255, 255, 255))
credits_line_6 = credits_btn.render("reduceimages.com and the sounds are imported from github account of", True, (255, 255, 255))
credits_line_7 = credits_btn.render("Mr. Attreya Bhatt. Direct Link to repository:", True, (255, 255, 255))
credits_line_8 = credits_btn.render("https://github.com/attreyabhatt/Space-Invaders-Pygame.", True, (255, 255, 255))
credits_line_9 = credits_btn.render("This game is free and open-source. User is independent for", True, (255, 255, 255))
credits_line_10 = credits_btn.render("manipulating code but it's encouraged that you avoid cheating.", True, (255, 255, 255))
credits_line_11 = credits_btn.render("Creator and Developer: Armaan Barak", True, (255, 255, 255))
# Game loop variables
running = True
home_screen = True
settings = False
controls = False
game_screen = False
credits_screen = False
game_over_screen = False
while running:
# To loop through events untill event is QUIT
for event in pygame.event.get():
# QUIT Button
if event.type == pygame.QUIT:
running = False
# Mouse key controls
if event.type == pygame.MOUSEBUTTONDOWN:
# Game is Over
if game_over_screen:
if 250 <= mouse[0] <= 385 and 520 <= mouse[1] <= 560:
home_screen = True
settings = False
controls = False
game_screen = False
credits_screen = False
game_over_screen = False
for i in range(num_of_enemies):
enemy_y[i] = random.randint(50, 200)
player_y = 480
bullet_y = 480
if 420 <= mouse[0] <= 560 and 520 <= mouse[1] <= 560:
quit()
# Play button clicked
if 230 <= mouse[0] <= 370 and 270 <= mouse[1] <= 310:
home_screen = False
settings = False
controls = False
game_screen = True
credits_screen = False
# Instructions button clicked
if 400 <= mouse[0] <= 540 and 270 <= mouse[1] <= 310:
home_screen = False
settings = False
controls = True
game_screen = False
credits_screen = False
# Settings button clicked
if 230 <= mouse[0] <= 370 and 350 <= mouse[1] <= 390:
home_screen = False
settings = True
controls = False
game_screen = False
credits_screen = False
# Credits button clicked
if 400 <= mouse[0] <= 540 and 350 <= mouse[1] <= 390:
home_screen = False
settings = False
controls = False
game_screen = False
credits_screen = True
# Quit button clicked
if 315 <= mouse[0] <= 455 and 430 <= mouse[1] <= 470:
quit()
if settings or controls or credits_screen:
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
home_screen = True
settings = False
controls = False
game_screen = False
credits_screen = False
# KeyBoard Controls
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_x_change = -3
if event.key == pygame.K_RIGHT:
player_x_change = 3
if event.key == pygame.K_SPACE:
if bullet_state == 'ready':
bullet_sound.play()
bullet_x = player_x
fire_bullet(bullet_x, bullet_y)
# Reseting player's x axis speed when left or right key is lifted
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
player_x_change = 0
# Home Screen
if home_screen:
# Displaying main screen
screen.blit(home_screen_img, (0,0))
# Getting Mouse Position
mouse = pygame.mouse.get_pos()
# Changing color of text boxes on the basis of cursor position
# play game text
if 230 <= mouse[0] <= 370 and 270 <= mouse[1] <= 310:
pygame.draw.rect(screen, color_light, [230, 270, 140, 40])
else:
pygame.draw.rect(screen, color_dark,[230,270,140,40])
# instructions text
if 400 <= mouse[0] <= 540 and 270 <= mouse[1] <= 310:
pygame.draw.rect(screen, color_light, [400, 270, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [400, 270, 140, 40])
# settings text
if 230 <= mouse[0] <= 370 and 350 <= mouse[1] <= 390:
pygame.draw.rect(screen, color_light, [230, 350, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [230, 350, 140, 40])
# credits text
if 400 <= mouse[0] <= 540 and 350 <= mouse[1] <= 390:
pygame.draw.rect(screen, color_light, [400, 350, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [400, 350, 140, 40])
# quit game text
if 315 <= mouse[0] <= 455 and 430 <= mouse[1] <= 470:
pygame.draw.rect(screen, color_light, [315, 430, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [315, 430, 140, 40])
# Displaying text
screen.blit(game_text, (90, 100))
# Displaying buttons
screen.blit(play_text, (240, 280))
screen.blit(controls_text, (421, 280))
screen.blit(settings_text, (253, 360))
screen.blit(credits_text, (427, 360))
screen.blit(quit_text, (325, 440))
# Version Display
screen.blit(version_text, (325, 580))
# Updating Screen
pygame.display.update()
# Settings Screen
elif settings:
screen.blit(settings_img, (0, 0))
mouse = pygame.mouse.get_pos()
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
pygame.draw.rect(screen, color_light, [50, 30, 115, 40])
else:
pygame.draw.rect(screen, color_dark, [50, 30, 115, 40])
screen.blit(back_text, (60, 40))
screen.blit(under_development_text, (60, 250))
pygame.display.update()
# Controls Screen
elif controls:
screen.blit(controls_img, (0, 0))
mouse = pygame.mouse.get_pos()
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
pygame.draw.rect(screen, color_light, [50, 30, 115, 40])
else:
pygame.draw.rect(screen, color_dark, [50, 30, 115, 40])
screen.blit(back_text, (60, 40))
screen.blit(controls_1, (255, 240))
screen.blit(controls_2, (255, 290))
screen.blit(controls_3, (255, 340))
pygame.display.update()
# Credits Screen
elif credits_screen:
screen.fill((85, 107, 47))
mouse = pygame.mouse.get_pos()
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
pygame.draw.rect(screen, color_light, [50, 30, 115, 40])
else:
pygame.draw.rect(screen, color_dark, [50, 30, 115, 40])
screen.blit(back_text, (60, 40))
screen.blit(credits_line_1, (40, 150))
screen.blit(credits_line_2, (40, 180))
screen.blit(credits_line_3, (40, 210))
screen.blit(credits_line_4, (40, 240))
screen.blit(credits_line_5, (40, 270))
screen.blit(credits_line_6, (40, 300))
screen.blit(credits_line_7, (40, 330))
screen.blit(credits_line_8, (40, 360))
screen.blit(credits_line_9, (40, 390))
screen.blit(credits_line_10, (40, 420))
screen.blit(credits_line_11, (40, 450))
pygame.display.update()
# Game Screen
else:
# Adding background image
screen.blit(game_background, (0,0))
# Player Movement
player_x += player_x_change
if player_x <= 0:
player_x = 0
elif player_x >= 736:
player_x = 736
# Handling movement of enemies
for i in range(num_of_enemies):
# Game Over
if enemy_y[i] > 450:
game_over_screen = True
# Hiding Characters
for j in range(num_of_enemies):
enemy_y[j] = 2000
player_y = -2000
bullet_y = -4000
screen.blit(game_over_img, (0, 0))
# Back button
if 250 <= mouse[0] <= 385 and 520 <= mouse[1] <= 560:
pygame.draw.rect(screen, color_light, [250, 520, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [250, 520, 140, 40])
# Quit Button
if 420 <= mouse[0] <= 560 and 520 <= mouse[1] <= 560:
pygame.draw.rect(screen, color_light, [420, 520, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [420, 520, 140, 40])
mouse = pygame.mouse.get_pos()
screen.blit(back_text, (270, 530))
screen.blit(quit_text, (430, 530))
# Enemy Movement
enemy_x[i] += enemy_x_change[i]
if enemy_x[i] <= 0:
enemy_x_change[i] = 2
enemy_y[i] += enemy_y_change[i]
elif enemy_x[i] >= 736:
enemy_x_change[i] = -2
enemy_y[i] += enemy_y_change[i]
# Collision control
collision = is_collision(enemy_x[i], enemy_y[i], bullet_x, bullet_y)
if collision:
explosion_sound.play()
bullet_y = 480
bullet_state = 'ready'
score_value += 1
enemy_x[i] = random.randint(0, 735)
enemy_y[i] = random.randint(50, 200)
# drawing enemy
enemy(enemy_x[i], enemy_y[i], i)
# Bullet Movement
if bullet_y <= 0:
bullet_y = 480
bullet_state = 'ready'
if bullet_state == "fire":
fire_bullet(bullet_x, bullet_y)
bullet_y -= bullet_y_change
# drawing player
player(player_x, player_y)
# Version Display
screen.blit(version_text, (325, 580))
# drawing score card
show_score(text_X, text_y)
# Updates screen
pygame.display.update()
我尝试使用命令 python setup.py bdist_msi
但同样的事情发生了。
我正在使用 python 版本 3.8.6rc1 我也尝试过使用 pyinstaller 但是每当我尝试 运行 pyinstaller 制作的可执行文件时它说执行失败游戏文件.
我知道这需要阅读很多内容并且很难理解。但我真的需要一些帮助。
如果有人可以建议该怎么做或如何解决这个问题,那将非常有帮助。如果您需要更多信息来为我提供解决方案,请告诉我。
P.S。所有游戏文件都保存在同一个目录中,并且游戏 运行s 没有任何错误。我遇到的唯一麻烦是为这个问题创建这个可执行安装程序。
Thanks in Advance
我以前没有用过cxFreeze,所以我不能直接帮助你解决问题,但我真的很推荐使用pyinstaller
来打包python程序。我之前在 pygame 中使用过它,它运行良好,甚至不需要安装文件。
Pyinstaller可以使用pip安装,打包一个文件你调用:
pyinstaller file.py
,以及您可能需要的任何标志。通常,我使用 pyinstaller file.py --onefile --noconsole
,它创建一个可执行文件。
Pyinstaller 不打包资产文件,所以你必须在项目中提供它们,但是项目使用的所有 python 文件(包括库)都被打包,所以项目不需要提供任何代码.
Pyinstaller 有时会不稳定,所以我建议首先创建一个简单的 hello world 文件,并使用 pyinstaller helloworld.py --onefile
打包它,然后 运行 将文件 dist/
文件夹。
docs对pyinstaller的帮助并不总是很大,但我发现学习打包项目的最好方法是慢慢增加你尝试打包的项目的复杂性,并在打包后检查每个项目的工作情况.
如果您使用相关脚本和资产导入(例如 pygame.image.load('image.png')
),您需要将生成的 .exe
移动到原始脚本的位置(通常创建 .exe
在 dist/
文件夹中,如果您使用相对导入和 运行 那里的 .exe
将不起作用。
如果要添加图标,可以像这样使用 --icon
标志:pyinstaller file.py --icon=image.ico
(图标文件必须是 .ico
文件 - 您可以随时在线转换器(如果需要)
我使用 Python 的 pygame 模块制作了一个游戏。我想制作该文件的可执行安装程序,这样任何人都可以玩该游戏,而无需安装 python 或 pygame。我使用模块 cx-freeze 为我的游戏文件创建可执行文件。我将用于制作可执行安装程序的代码存储在名为 setup.py 的文件中,并将其保存在与游戏文件和游戏所需的所有其他文件相同的目录中,例如图像、声音等
当我执行命令 python setup.py build
来创建可执行文件时,我开始收到 警告 并在最后发生此错误:
Traceback (most recent call last):
File "setup.py", line 5, in <module>
cx_Freeze.setup(
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\dist.py", line 342, in setup
distutils.core.setup(**attrs)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\core.py", line 148, in setup
dist.run_commands()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\dist.py", line 966, in run_commands
self.run_command(cmd)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\dist.py", line 985, in run_command
cmd_obj.run()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\command\build.py", line 135, in run
self.run_command(cmd_name)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\cmd.py", line 313, in run_command
self.distribution.run_command(command)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\distutils\dist.py", line 985, in run_command
cmd_obj.run()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\dist.py", line 217, in run
freezer.Freeze()
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\freezer.py", line 645, in Freeze
self._WriteModules(fileName, self.finder)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\freezer.py", line 536, in _WriteModules
sourcePackageDir = os.path.dirname(module.file)
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\ntpath.py", line 223, in dirname
return split(p)[0]
File "C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\ntpath.py", line 185, in split
p = os.fspath(p)
TypeError: expected str, bytes or os.PathLike object, not NoneType
显示的警告是:
running build
running build_exe
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\setuptools\distutils_patch.py:25: UserWarning: Distutils was imported before Setuptools. This usage is discouraged and may exhibit undesirable behaviors or errors. Please use Setuptools' objects directly or at least import Setuptools first.
warnings.warn(
C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\pygame\examples\chimp.py:32: SyntaxWarning: "is" with a literal. Did you mean "=="?
if colorkey is -1:
C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\pygame\tests\test_utils\__init__.py:162: SyntaxWarning: "is not" with a literal. Did you mean "!="?
(rect.left is not 0 and [(rect.left-1, rect.top)] or []) +
copying c:\users\armaan barak\appdata\local\programs\python\python38\python38.dll -> build\exe.win-amd64-3.8\python38.dll
copying c:\users\armaan barak\appdata\local\programs\python\python38\vcruntime140.dll -> build\exe.win-amd64-3.8\vcruntime140.dll
copying c:\users\armaan barak\appdata\local\programs\python\python38\python3.dll -> build\exe.win-amd64-3.8\python3.dll
copying C:\Users\Armaan Barak\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\bases\Console.exe -> build\exe.win-amd64-3.8\SpaceInvader2.exe
*** WARNING *** unable to create version resource
version must be specified
安装文件中的代码:
import cx_Freeze
executable = [cx_Freeze.Executable('SpaceInvader2.py')]
cx_Freeze.setup(
name="Space Invaders 2",
options={
"build_exe": {
"packages": [
"pygame",
"random",
"math",
"pygame.mixer",
"time"
],
"include_files": [
"spaceship.png",
"space.png",
"home_screen.png",
"ammunition.png",
"alien.png",
"alien2.png",
"alien3.png",
"alien4.png",
"player.png",
"settings.png",
"controls.png",
"game_over.png",
"background.wav",
"laser.wav",
"explosion.wav"
]
}
},
executables=executable
)
游戏文件中的代码:
import pygame
import random
import math
from pygame import mixer
import time
# Game Screen Initialization
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Loading Images
icon = pygame.image.load('spaceship.png')
game_background = pygame.image.load('space.png')
home_screen_img = pygame.image.load('home_screen.png')
bullet = pygame.image.load('ammunition.png')
alien_img = pygame.image.load('alien.png')
alien_img2 = pygame.image.load('alien2.png')
alien_img3 = pygame.image.load('alien3.png')
alien_img4 = pygame.image.load('alien4.png')
player_img = pygame.image.load('player.png')
settings_img = pygame.image.load('settings.png')
controls_img = pygame.image.load('controls.png')
game_over_img = pygame.image.load('game_over.png')
# Loading sounds
mixer.music.load('background.wav')
mixer.music.play(-1)
bullet_sound = mixer.Sound('laser.wav')
explosion_sound = mixer.Sound('explosion.wav')
# Title and Icon
pygame.display.set_caption('Space Invader')
pygame.display.set_icon(icon)
# Bullet variables
bullet_x = 0
bullet_y = 480
bullet_x_change = 0
bullet_y_change = 4
bullet_state = 'ready'
# Player variables
player_x = 370
player_y = 480
player_x_change = 0
# Enemy variables
enemy_img = []
enemy_x = []
enemy_y = []
enemy_x_change = []
enemy_y_change = []
num_of_enemies = 13
# Creating 10 enemy objects
for i in range(num_of_enemies):
enemy_img.append(random.choice([alien_img, alien_img2, alien_img3, alien_img4]))
enemy_x.append(random.randint(0, 735))
enemy_y.append(random.randint(50, 200))
enemy_x_change.append(2)
enemy_y_change.append(40)
# Score variables
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 24)
over_font = pygame.font.Font('freesansbold.ttf', 80)
text_X = 10
text_y = 10
# Game Functions
def show_score(x, y):
score = font.render('Score: ' + str(score_value), True, (165,240,67))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render('GAME OVER!', True, (255, 0, 0))
screen.blit(over_text, (160, 250))
def player(x, y):
screen.blit(player_img, (x, y))
def enemy(x, y, i):
screen.blit(enemy_img[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = 'fire'
screen.blit(bullet, (x + 16, y + 10))
def is_collision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY-bulletY, 2)))
return distance < 27
# Button colors and fonts
color = (0, 0, 0)
color_light = (100,149,237)
color_dark = (138,43,226)
# Fonts
game_name_font = pygame.font.SysFont("Chiller", 140)
btn_font = pygame.font.SysFont('Corbel Bold', 34)
random_font = pygame.font.SysFont('Arial', 60)
info_btn = pygame.font.SysFont('Century Gothic', 24)
controls_font = pygame.font.SysFont('Consolas', 15)
credits_btn = pygame.font.SysFont('Consolas', 18)
# Texts
game_text = game_name_font.render('Space Invaders!', True, (255,255,0))
play_text = btn_font.render('Play Game', True, color)
controls_text = btn_font.render('Controls', True, color)
credits_text = btn_font.render('Credits', True, color)
settings_text = btn_font.render('Settings', True, color)
quit_text = btn_font.render('Quit Game', True, color)
version_text = btn_font.render('Version 2.8', True, (255, 255, 255))
back_text = btn_font.render('Go Back', True, color)
under_development_text = random_font.render('This area is under development', True, (0, 0, 0))
# Controls text
controls_1 = controls_font.render('Left Arrow : Spaceship moves Left', True, (124, 252, 0))
controls_2 = controls_font.render('Right Arrow : Spaceship moves Right', True, (124, 252, 0))
controls_3 = controls_font.render('Spacebar : Shoots bullets', True, (124, 252, 0))
# Credits text
credits_line_1 = credits_btn.render("The games first version was made while learning from the pygame video", True, (255, 255, 255))
credits_line_2 = credits_btn.render("of FreeCodeCamp.org. The successive updates in version 1 and 2 are", True, (255, 255, 255))
credits_line_3 = credits_btn.render("made by Armaan Barak. No external code was copied. But help was taken", True, (255, 255, 255))
credits_line_4 = credits_btn.render("from google. Images and icons shown this game are taken from freepik.com", True, (255, 255, 255))
credits_line_5 = credits_btn.render("and flaticon.com respectively. The images were resized from", True, (255, 255, 255))
credits_line_6 = credits_btn.render("reduceimages.com and the sounds are imported from github account of", True, (255, 255, 255))
credits_line_7 = credits_btn.render("Mr. Attreya Bhatt. Direct Link to repository:", True, (255, 255, 255))
credits_line_8 = credits_btn.render("https://github.com/attreyabhatt/Space-Invaders-Pygame.", True, (255, 255, 255))
credits_line_9 = credits_btn.render("This game is free and open-source. User is independent for", True, (255, 255, 255))
credits_line_10 = credits_btn.render("manipulating code but it's encouraged that you avoid cheating.", True, (255, 255, 255))
credits_line_11 = credits_btn.render("Creator and Developer: Armaan Barak", True, (255, 255, 255))
# Game loop variables
running = True
home_screen = True
settings = False
controls = False
game_screen = False
credits_screen = False
game_over_screen = False
while running:
# To loop through events untill event is QUIT
for event in pygame.event.get():
# QUIT Button
if event.type == pygame.QUIT:
running = False
# Mouse key controls
if event.type == pygame.MOUSEBUTTONDOWN:
# Game is Over
if game_over_screen:
if 250 <= mouse[0] <= 385 and 520 <= mouse[1] <= 560:
home_screen = True
settings = False
controls = False
game_screen = False
credits_screen = False
game_over_screen = False
for i in range(num_of_enemies):
enemy_y[i] = random.randint(50, 200)
player_y = 480
bullet_y = 480
if 420 <= mouse[0] <= 560 and 520 <= mouse[1] <= 560:
quit()
# Play button clicked
if 230 <= mouse[0] <= 370 and 270 <= mouse[1] <= 310:
home_screen = False
settings = False
controls = False
game_screen = True
credits_screen = False
# Instructions button clicked
if 400 <= mouse[0] <= 540 and 270 <= mouse[1] <= 310:
home_screen = False
settings = False
controls = True
game_screen = False
credits_screen = False
# Settings button clicked
if 230 <= mouse[0] <= 370 and 350 <= mouse[1] <= 390:
home_screen = False
settings = True
controls = False
game_screen = False
credits_screen = False
# Credits button clicked
if 400 <= mouse[0] <= 540 and 350 <= mouse[1] <= 390:
home_screen = False
settings = False
controls = False
game_screen = False
credits_screen = True
# Quit button clicked
if 315 <= mouse[0] <= 455 and 430 <= mouse[1] <= 470:
quit()
if settings or controls or credits_screen:
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
home_screen = True
settings = False
controls = False
game_screen = False
credits_screen = False
# KeyBoard Controls
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_x_change = -3
if event.key == pygame.K_RIGHT:
player_x_change = 3
if event.key == pygame.K_SPACE:
if bullet_state == 'ready':
bullet_sound.play()
bullet_x = player_x
fire_bullet(bullet_x, bullet_y)
# Reseting player's x axis speed when left or right key is lifted
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
player_x_change = 0
# Home Screen
if home_screen:
# Displaying main screen
screen.blit(home_screen_img, (0,0))
# Getting Mouse Position
mouse = pygame.mouse.get_pos()
# Changing color of text boxes on the basis of cursor position
# play game text
if 230 <= mouse[0] <= 370 and 270 <= mouse[1] <= 310:
pygame.draw.rect(screen, color_light, [230, 270, 140, 40])
else:
pygame.draw.rect(screen, color_dark,[230,270,140,40])
# instructions text
if 400 <= mouse[0] <= 540 and 270 <= mouse[1] <= 310:
pygame.draw.rect(screen, color_light, [400, 270, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [400, 270, 140, 40])
# settings text
if 230 <= mouse[0] <= 370 and 350 <= mouse[1] <= 390:
pygame.draw.rect(screen, color_light, [230, 350, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [230, 350, 140, 40])
# credits text
if 400 <= mouse[0] <= 540 and 350 <= mouse[1] <= 390:
pygame.draw.rect(screen, color_light, [400, 350, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [400, 350, 140, 40])
# quit game text
if 315 <= mouse[0] <= 455 and 430 <= mouse[1] <= 470:
pygame.draw.rect(screen, color_light, [315, 430, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [315, 430, 140, 40])
# Displaying text
screen.blit(game_text, (90, 100))
# Displaying buttons
screen.blit(play_text, (240, 280))
screen.blit(controls_text, (421, 280))
screen.blit(settings_text, (253, 360))
screen.blit(credits_text, (427, 360))
screen.blit(quit_text, (325, 440))
# Version Display
screen.blit(version_text, (325, 580))
# Updating Screen
pygame.display.update()
# Settings Screen
elif settings:
screen.blit(settings_img, (0, 0))
mouse = pygame.mouse.get_pos()
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
pygame.draw.rect(screen, color_light, [50, 30, 115, 40])
else:
pygame.draw.rect(screen, color_dark, [50, 30, 115, 40])
screen.blit(back_text, (60, 40))
screen.blit(under_development_text, (60, 250))
pygame.display.update()
# Controls Screen
elif controls:
screen.blit(controls_img, (0, 0))
mouse = pygame.mouse.get_pos()
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
pygame.draw.rect(screen, color_light, [50, 30, 115, 40])
else:
pygame.draw.rect(screen, color_dark, [50, 30, 115, 40])
screen.blit(back_text, (60, 40))
screen.blit(controls_1, (255, 240))
screen.blit(controls_2, (255, 290))
screen.blit(controls_3, (255, 340))
pygame.display.update()
# Credits Screen
elif credits_screen:
screen.fill((85, 107, 47))
mouse = pygame.mouse.get_pos()
if 50 <= mouse[0] <= 165 and 30 <= mouse[1] <= 70:
pygame.draw.rect(screen, color_light, [50, 30, 115, 40])
else:
pygame.draw.rect(screen, color_dark, [50, 30, 115, 40])
screen.blit(back_text, (60, 40))
screen.blit(credits_line_1, (40, 150))
screen.blit(credits_line_2, (40, 180))
screen.blit(credits_line_3, (40, 210))
screen.blit(credits_line_4, (40, 240))
screen.blit(credits_line_5, (40, 270))
screen.blit(credits_line_6, (40, 300))
screen.blit(credits_line_7, (40, 330))
screen.blit(credits_line_8, (40, 360))
screen.blit(credits_line_9, (40, 390))
screen.blit(credits_line_10, (40, 420))
screen.blit(credits_line_11, (40, 450))
pygame.display.update()
# Game Screen
else:
# Adding background image
screen.blit(game_background, (0,0))
# Player Movement
player_x += player_x_change
if player_x <= 0:
player_x = 0
elif player_x >= 736:
player_x = 736
# Handling movement of enemies
for i in range(num_of_enemies):
# Game Over
if enemy_y[i] > 450:
game_over_screen = True
# Hiding Characters
for j in range(num_of_enemies):
enemy_y[j] = 2000
player_y = -2000
bullet_y = -4000
screen.blit(game_over_img, (0, 0))
# Back button
if 250 <= mouse[0] <= 385 and 520 <= mouse[1] <= 560:
pygame.draw.rect(screen, color_light, [250, 520, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [250, 520, 140, 40])
# Quit Button
if 420 <= mouse[0] <= 560 and 520 <= mouse[1] <= 560:
pygame.draw.rect(screen, color_light, [420, 520, 140, 40])
else:
pygame.draw.rect(screen, color_dark, [420, 520, 140, 40])
mouse = pygame.mouse.get_pos()
screen.blit(back_text, (270, 530))
screen.blit(quit_text, (430, 530))
# Enemy Movement
enemy_x[i] += enemy_x_change[i]
if enemy_x[i] <= 0:
enemy_x_change[i] = 2
enemy_y[i] += enemy_y_change[i]
elif enemy_x[i] >= 736:
enemy_x_change[i] = -2
enemy_y[i] += enemy_y_change[i]
# Collision control
collision = is_collision(enemy_x[i], enemy_y[i], bullet_x, bullet_y)
if collision:
explosion_sound.play()
bullet_y = 480
bullet_state = 'ready'
score_value += 1
enemy_x[i] = random.randint(0, 735)
enemy_y[i] = random.randint(50, 200)
# drawing enemy
enemy(enemy_x[i], enemy_y[i], i)
# Bullet Movement
if bullet_y <= 0:
bullet_y = 480
bullet_state = 'ready'
if bullet_state == "fire":
fire_bullet(bullet_x, bullet_y)
bullet_y -= bullet_y_change
# drawing player
player(player_x, player_y)
# Version Display
screen.blit(version_text, (325, 580))
# drawing score card
show_score(text_X, text_y)
# Updates screen
pygame.display.update()
我尝试使用命令 python setup.py bdist_msi
但同样的事情发生了。
我正在使用 python 版本 3.8.6rc1 我也尝试过使用 pyinstaller 但是每当我尝试 运行 pyinstaller 制作的可执行文件时它说执行失败游戏文件.
我知道这需要阅读很多内容并且很难理解。但我真的需要一些帮助。 如果有人可以建议该怎么做或如何解决这个问题,那将非常有帮助。如果您需要更多信息来为我提供解决方案,请告诉我。
P.S。所有游戏文件都保存在同一个目录中,并且游戏 运行s 没有任何错误。我遇到的唯一麻烦是为这个问题创建这个可执行安装程序。
Thanks in Advance
我以前没有用过cxFreeze,所以我不能直接帮助你解决问题,但我真的很推荐使用pyinstaller
来打包python程序。我之前在 pygame 中使用过它,它运行良好,甚至不需要安装文件。
Pyinstaller可以使用pip安装,打包一个文件你调用:
pyinstaller file.py
,以及您可能需要的任何标志。通常,我使用 pyinstaller file.py --onefile --noconsole
,它创建一个可执行文件。
Pyinstaller 不打包资产文件,所以你必须在项目中提供它们,但是项目使用的所有 python 文件(包括库)都被打包,所以项目不需要提供任何代码.
Pyinstaller 有时会不稳定,所以我建议首先创建一个简单的 hello world 文件,并使用 pyinstaller helloworld.py --onefile
打包它,然后 运行 将文件 dist/
文件夹。
docs对pyinstaller的帮助并不总是很大,但我发现学习打包项目的最好方法是慢慢增加你尝试打包的项目的复杂性,并在打包后检查每个项目的工作情况.
如果您使用相关脚本和资产导入(例如 pygame.image.load('image.png')
),您需要将生成的 .exe
移动到原始脚本的位置(通常创建 .exe
在 dist/
文件夹中,如果您使用相对导入和 运行 那里的 .exe
将不起作用。
如果要添加图标,可以像这样使用 --icon
标志:pyinstaller file.py --icon=image.ico
(图标文件必须是 .ico
文件 - 您可以随时在线转换器(如果需要)