Python專案1“外星人入侵”遊戲(完整)及pyinstaller打包過程(含幾種報錯解決辦法)
一、專案環境背景介紹
1.Pycharm版本:社群2017.2.7版本
2.對應python版本:3.6.4版本
環境搭建的帖子(這位哥們寫得很細的 點贊):https://blog.csdn.net/wardseptember/article/details/79965836
3.基於以上環境開發一個遊戲
在遊戲《外星人入侵》中,玩家控制著一艘最初出現在螢幕底部中央的飛船。玩家可以使用箭頭鍵左右移動飛船,還可使用空格鍵進行射擊。遊戲開始時,一群外星人出現在天空中,他們在螢幕中向下移動。玩家的任務是射殺這些外星人。玩家將所有外星人都消滅乾淨後,將出現一群新的外星人,他們移動的速度更快。只要有外星人撞到了玩家的飛船或到達了螢幕底部,玩家就損失一艘飛船。玩家損失三艘飛船後,遊戲結束。(本遊戲附加各種音效)
4.遊戲專案的目錄結構如下
>D\Python-Projects
>a book of py
>Projects
>Project 1(alien_invasion) chapter 12-14
>alien_invasion
>images
>alien.bmp
>ship.bmp
>musics
>Bullet_biu.wav
>Explo_Large.wav
>Explo_Small.wav
>order_music.mp3
>alien_invasion.py(主檔案)
>game_functions.py(功能函式)
>alien.py(外星人)
>ship.py(飛船)
>bullet.py(子彈)
>button.py(play按鈕)
>settings.py(遊戲屬性設定)
>scoreboard.py(分數)
>game_stats.py(遊戲狀態)
>music.py(音效)
>Max_score.json(歷史最高分記錄檔案)
二、專案過程中所有的.py檔案程式碼
1.alien_invasion.py(主檔案)
# coding: UTF-8
# 專案1:外星人入侵
# 系統自帶的類或函式
# import sys # 退出遊戲----集中在game_functions.py中使用,故這注釋掉
import pygame # 含有開發遊戲所需功能
from pygame.sprite import Group # 儲存所有有效子彈的類
# 自定義的類或函式
from settings import Settings # 對《外星人入侵》遊戲中所有設定的類,如螢幕寬高…
from ship import Ship # 建立飛船的類
from button import Button # 建立按鈕的類
from game_stats import Game_Stats # 建立跟蹤遊戲統計資訊的類
from scoreboard import Scoreboard # 建立得分類
from music import bg_music # 背景音樂
import game_functions as gf # 所有的功能函
def run_game():
# 初始化遊戲並建立一個螢幕物件
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode(
(ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("外星人入侵")
# 初始化聲音播放模組
pygame.mixer.init()
# 建立Play按鈕
play_button = Button(ai_settings, screen, "Play")
# 建立一艘飛船
ship = Ship(ai_settings, screen)
# 建立一個用於儲存子彈的編組
bullets = Group()
# 建立一個用於儲存外星人的編組
aliens = Group()
# 建立儲存遊戲統計資訊的例項
game_stats = Game_Stats(ai_settings)
# 建立記分牌
scoreb = Scoreboard(ai_settings, screen, game_stats)
# 建立外星人群
gf.create_fleet(ai_settings, screen, ship, aliens)
# 載入背景音樂
bg_music()
# 開始遊戲的主迴圈
while True:
# 呼叫響應滑鼠和鍵盤事件的函式
gf.check_events(ai_settings, screen, game_stats, scoreb, play_button, ship, aliens, bullets)
if game_stats.game_active:
# 呼叫背景音樂
gf.play_bg_music()
# 呼叫飛船水平持續移動的函式
ship.update()
# 呼叫關於子彈相關操作的函式
gf.update_bullets(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets)
# 呼叫外星人向右移動的函式
gf.update_aliens(ai_settings, game_stats, scoreb, screen, ship, aliens, bullets)
# 呼叫更新螢幕上的影像並切換到新螢幕的函式
gf.update_screen(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets, play_button)
run_game() # 此時執行的話 會彈出一個pygame視窗
2.game_functions.py(功能函式)
# coding: UTF-8
# 《外星人入侵》執行的所有函式
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep
import json
import music
def play_bg_music():
"""背景音樂"""
if not pygame.mixer.music.get_busy():
pygame.mixer.music.play()
def check_keydown_events(event, ai_settings, screen, ship, bullets, game_stats, scoreb, aliens):
""""
響應滑鼠按下操作
"""
# 按右箭頭飛船向右移動
if event.key == pygame.K_RIGHT:
ship.moving_right = True
# 按左箭頭飛船向左移動
elif event.key == pygame.K_LEFT:
ship.moving_left = True
# 按空格鍵建立一顆子彈並將其加入到編組bullets中
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)
# 按p開始遊戲
elif event.key == pygame.K_p:
start_game(ai_settings, screen, ship, bullets, game_stats, scoreb,
aliens)
# 按z暫停遊戲3s
elif event.key == pygame.K_z:
sleep(2)
# 按q退出遊戲並把最高分寫入檔案
elif event.key == pygame.K_q:
with open('Max_score.json', 'w', encoding='UTF-8') as file:
json.dump(game_stats.high_score, file)
sys.exit()
def fire_bullet(ai_settings, screen, ship, bullets):
"""
按照要求發射子彈數量
"""
if len(bullets) < ai_settings.bullet_allowed:
music.bullet_biu() # 發射子彈的聲音
new_bullet = Bullet(ai_settings, screen, ship) # 如果還沒有到達限制,就發射一顆子彈
bullets.add(new_bullet) # 建立一顆子彈,並將其加入到編組bullets中
def start_game(ai_settings, screen, ship, bullets, game_stats, scoreb,
aliens):
"""
P264中動手試一試14-1的練習:讓玩家按p開始遊戲
"""
# 重置遊戲統計資訊
game_stats.reset_stats()
game_stats.game_active = True
# 重置記分牌影像
scoreb.prep_score()
scoreb.prep_high_score()
scoreb.prep_level()
scoreb.prep_ships()
# 清空外星人列表和子彈列表
aliens.empty()
bullets.empty()
# 建立一群新的外星人,並讓飛船居中
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
# 暫停讓使用者反應一會
sleep(0.5)
def check_keyup_events(event, ship):
""""
響應滑鼠鬆開---飛船停下
"""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_play_button(ai_settings, screen, game_stats, scoreb, play_button, ship,
aliens, bullets, mouse_x, mouse_y):
"""
在玩家單擊Play按鈕時開始遊戲
"""
button_clicked = play_button.button_rect.collidepoint(mouse_x, mouse_y)
# 單擊Play按鈕且遊戲處於非活躍狀態時----避免了遊戲處於活躍狀態下單擊到了Play按鈕區域重啟遊戲
if button_clicked and not game_stats.game_active:
"""如果滑鼠單擊位置在msg_image_rect範圍內則將遊戲置於活躍狀態"""
# # 重置遊戲設定
ai_settings.initialize_dynamic_settings()
# 遊戲開始後Play按鈕隱藏起來
pygame.mouse.set_visible(False)
start_game(ai_settings, screen, ship, bullets, game_stats, scoreb, aliens)
def check_events(ai_settings, screen, game_stats, scoreb, play_button, ship, aliens, bullets):
"""
響應滑鼠和鍵盤事件
"""
# 遊戲退出並把最高分寫入檔案
for event in pygame.event.get():
if event.type == pygame.QUIT:
with open('Max_score.json', 'w', encoding='UTF-8') as file:
json.dump(game_stats.high_score, file)
sys.exit()
# 響應Play按鈕操作
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos() # 該函式返回一個元組--獲取滑鼠單擊Play按鈕時的位置
check_play_button(ai_settings, screen, game_stats, scoreb, play_button, ship,
aliens, bullets, mouse_x, mouse_y)
# 判讀飛船向左還是向右移動
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets, game_stats, scoreb, aliens)
# 飛船停下
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
def update_screen(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets, play_button):
"""
更新螢幕上的影像並切換到新螢幕
"""
# 每次迴圈時都重繪螢幕
screen.fill(ai_settings.bg_color) # 先填充背景後繪製飛船
ship.blitem()
aliens.draw(screen)
# 在飛船後重繪所有子彈
for bullet in bullets.sprites():
bullet.draw_bullet()
# 顯示得分
scoreb.show_score()
# 如果遊戲處於非活動狀態就繪製Play按鈕
if not game_stats.game_active:
play_button.draw_button()
# 讓最近繪製的螢幕可見
pygame.display.flip()
def start_new_level(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets):
"""
當消滅乾淨外星人提高一個等級
"""
if len(aliens) == 0:
# 刪除現有子彈
bullets.empty()
# 逐漸提高速度加快遊戲節奏
ai_settings.increase_speed()
# 當前螢幕外星人全部被消滅就提高一個等級
game_stats.level += 1
scoreb.prep_level()
# 建立一群新的外星人
create_fleet(ai_settings, screen, ship, aliens) # 呼叫建立外星人群的函式
def check_bullet_alien_collisions(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets):
"""子彈與外星人相撞後的操作"""
# 檢查是否有子彈擊中外星人
# 如果擊中了就刪除相應的子彈與外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
"""方法sprite.groupcollide()檢查兩個編組的成員之間的碰撞(碰撞是指遊戲元素重疊在一起):
將每顆子彈同每個外星人的rect作比較 並返回一個字典 字典中的鍵為子彈 值為被擊中的外星人"""
# 每消滅一個外星人都將加一個points且顯示最新得分的影像
if collisions:
music.voice_small() # 子彈與外星人相撞的聲音
for aliens in collisions.values(): # aliens指被同一顆子彈擊中的外星人---是一個列表
game_stats.score += ai_settings.alien_points * len(aliens)
scoreb.prep_score()
check_high_score(game_stats, scoreb)
start_new_level(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets)
def update_bullets(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets):
"""
更新子彈位置並刪除已消失的子彈
"""
# 更新子彈位置
bullets.update()
# 刪除已消失的子彈
for bullet in bullets.copy():
if bullet.rect.bottom <= 0: # 當子彈底部越過螢幕頂部(0)時刪除子彈
bullets.remove(bullet)
check_bullet_alien_collisions(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets)
def get_number_aliens_X(ai_settings, alien_width):
"""
計算每行可容納多少個外星人
"""
availabble_space_x = ai_settings.screen_width - 2 * alien_width # 一行可可容納的水平長度
number_aliens_x = int(availabble_space_x / (2 * alien_width)) # 一行可容納多少個外星人
return number_aliens_x
def get_number_rows(ai_settings, alien_height, ship_height):
"""
計算螢幕可容納多少行外星人
"""
availables_space_y = (ai_settings.screen_height-ship_height-
(3*alien_height))
number_rows = int(availables_space_y / (2 * alien_height))
return number_rows
def create_alien(ai_settings, screen, aliens, alien_number, row_number):
"""
建立一個外星人並將其放在當前行
"""
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
alien_height = alien.rect.height + 3 # 讓外星人之間間隔大些
alien.x = alien_width + 2 * alien_width * alien_number # 獲取新建外星人所移動的位置
alien.rect.x = alien.x # 新建外星人的位置
alien.rect.y = alien_height + 2 * alien_height * row_number # 新行的位置
aliens.add(alien)
def create_fleet(ai_settings, screen, ship, aliens):
"""
建立外星人群
"""
# 建立一個外星人並計算一行可容納多少個外星人
# 外星人間距為外星人的寬度
alien = Alien(ai_settings, screen)
number_aliens_x = get_number_aliens_X(ai_settings, alien.rect.width) # 一行可容納外星人的個數
number_rows = get_number_rows(ai_settings, alien.rect.height,
ship.rect.height) # 螢幕上可容納外星人的行數
# 內外雙迴圈建立外星人群
for row_number in range(number_rows): # 外迴圈建立外星人行數
for alien_number in range(number_aliens_x): # 內迴圈建立外星人
create_alien(ai_settings, screen, aliens, alien_number, row_number) # 呼叫建立外星人的函式
def check_fleet_edges(ai_settings, aliens):
"""
有外星人到達邊緣時採取相應的措施
"""
for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
break
def change_fleet_direction(ai_settings, aliens):
"""
將整全外星人下移並改變它們的方向
"""
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1
def check_aliens_bottom(ai_settings, game_stats, scoreb, screen, ship, aliens, bullets):
"""檢測外星人是否到達螢幕底部"""
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# 外星人觸底爆炸聲
music.voice_large()
# 有外星人到達螢幕後進行像飛船被撞後一樣的操作
ship_aliens_hit(ai_settings, game_stats, scoreb, screen, ship, aliens, bullets)
break
def ship_aliens_hit(ai_settings, game_stats, scoreb, screen, ship, aliens, bullets):
"""
響應外星人飛船相撞的後續操作
"""
# 外星人飛船相撞時 發出碰撞聲音 ship_left減1
if game_stats.ships_left > 0:
music.voice_large()
game_stats.ships_left -= 1
# 更新螢幕上飛船的艘數
scoreb.prep_ships()
else:
game_stats.game_active = False
ai_settings.increase_wen() # 遊戲結束後alien的速度得回到最初為
pygame.mouse.set_visible(True) # 遊戲結束後Play按鈕顯示出來
# 清空外星人列表和子彈列表
aliens.empty()
bullets.empty()
# 建立一群新的外星人並將飛船重新出現在螢幕在底部中央
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
# 暫停讓使用者反應一會
sleep(0.5)
def update_aliens(ai_settings, game_stats, scoreb, screen, ship, aliens, bullets):
"""
更新外星人群中所有外星人的位置
"""
check_fleet_edges(ai_settings, aliens)
aliens.update()
if pygame.sprite.spritecollideany(ship, aliens):
"""
接收倆個實參--檢測飛船和外星人是否發生碰撞:發生了---往下走;沒發生---返回None
"""
ship_aliens_hit(ai_settings, game_stats, scoreb, screen, ship, aliens, bullets)
# 檢測是否有外星人到達螢幕底部
check_aliens_bottom(ai_settings, game_stats, scoreb, screen, ship, aliens, bullets)
def check_high_score(game_stats, scoreb):
"""檢查是否誕生了新的最高得分"""
if game_stats.score > game_stats.high_score:
game_stats.high_score = game_stats.score
scoreb.prep_high_score()
3.alien.py(外星人)
# coding: UTF-8
# 建立外星人Alien類
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
"""
表示單個外星人的類
"""
def __init__(self, ai_sttings, screen):
super(Alien, self).__init__()
self.screen = screen
self.ai_settings = ai_sttings
# 載入外星人的圖片並設定其rect屬性
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
# 設定外星人之間的間隔
self.rect.x = self.rect.width # 將外星人左邊距設定為外星人的寬度
self.rect.y = self.rect.height # 將上邊距設定為外星人的高度
# 儲存外星人的準確位置
self.x = float(self.rect.x)
def check_edges(self):
"""
如果外星人位於螢幕邊緣就返回True
"""
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right: # 外星人元素右邊將要越過螢幕右邊時的狀態---此時處於觸及螢幕右邊緣
return True
elif self.rect.left <= 0: # 外星人元素左邊<= 0時代表將要越過螢幕左邊---此時處於觸及螢幕的左邊緣
return True
def update(self):
"""
向左或向右移動外星人
"""
self.x += (self.ai_settings.alien_speed_factor
* self.ai_settings.fleet_direction) # 速度 * 移動方向
self.rect.x = self.x
def blitem(self):
"""
在指定位置繪製外星人的位置
"""
self.screen.blit(self.image, self.rect)
4.ship.py(飛船)
# coding: UTF-8
# 建立飛船Ship類
import pygame
from pygame.sprite import Sprite
class Ship(Sprite):
"""
初始化飛船並設定其初始位置
"""
def __init__(self, ai_settings, screen):
super().__init__()
self.screen = screen
self.ai_settings = ai_settings
# 載入飛船影像並獲取其外接矩形
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect() # 獲取飛船圖片外接矩形(即是讓其可以像矩形一樣被處理)
self.screen_rect = self.screen.get_rect() # 獲取螢幕圖片外接矩形(即是讓其可以像矩形一樣被處理)
# 將每搜新飛船放在螢幕底部中央
self.rect.centerx = self.screen_rect.centerx # 將飛船的centerx與螢幕的centerx捆綁在一起
self.rect.bottom = self.screen_rect.bottom # 將飛船的bottom與螢幕的bottom捆綁在一起
# 在飛船的屬性center中儲存小數值
self.center = float(self.rect.centerx)
# 飛船水平移動標誌
self.moving_right = False
self.moving_left = False
def update(self):
"""
根據移動標誌調整飛船水平位置
"""
# 飛船持續向右移動
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
# 飛船持續向左移動
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
# 根據self.center更新image_rect物件
self.rect.centerx = self.center
def blitem(self):
"""
在指定位置繪製飛船
"""
self.screen.blit(self.image, self.rect)
def center_ship(self):
"""讓飛船在螢幕底部居中"""
self.ship_center = self.screen_rect.centerx
5.bullet.py(子彈)
# coding: UTF-8
# 建立子彈Bullet類
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
"""
一個對飛船發射的子彈進行管理的類
"""
def __init__(self, ai_settings, screen, ship):
"""
在飛船所處的位置建立一個子彈物件
"""
super(Bullet, self).__init__() # 繼承Sprite
self.screen = screen
# 在(0, 0)位置上建立一個表示子彈的矩形,並設定其位置
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx # 將子彈的centerx設定為飛船的centerx
self.rect.top = ship.rect.top # 將子彈的top屬性設定為飛船的top屬性 讓子彈看起來是從飛船中射出的
# 將子彈的垂直位置用小數表示,方便調節速度
self.y = float(self.rect.y)
# 獲取子彈其他屬性
self.bullet_color = ai_settings.bullet_color
self.bullet_speed_factor = ai_settings.bullet_speed_factor
def update(self):
"""
向上移動子彈
"""
# 更新表示子彈位置的小數值
self.y -= self.bullet_speed_factor
# 更新表示子彈的rect的位置
self.rect.y = self.y
def draw_bullet(self):
"""
在螢幕上繪製子彈
"""
pygame.draw.rect(self.screen, self.bullet_color, self.rect) # 順序為1 2 3 :2填充3,出現在1螢幕上
6.button.py(play按鈕)
# coding: UTF-8
# 建立開啟遊戲的play按鈕
import pygame.font
class Button():
"""初始化按鈕的屬性"""
def __init__(self, ai_settings, screen, msg):
self.screen = screen
self.screen_rect = screen.get_rect()
# 設定按鈕的尺寸和其他屬性
self.width, self.height = 200, 50
self.button_color = (0, 208, 0) # 按鈕框的顏色--和外星人一樣的顏色
self.text_color = (255, 0, 0) # 文字顏色--紅色
self.font = pygame.font.SysFont(None, 48) # 使用預設字型,字號為48
# 設定按鈕的rect並使其居中
self.button_rect = pygame.Rect(0, 0, self.width, self.height)
self.button_rect.center = self.screen_rect.center
# 按鈕的標籤只需要建立一次
self.prep_msg(msg)
def prep_msg(self, msg):
"""
將文字渲染成影像並使其在按鈕上居中
"""
self.msg_image = self.font.render(msg, True, self.text_color) # 將儲存在msg中的文字轉換成影像
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.button_rect.center
def draw_button(self):
"""繪製一個用顏色填充的按鈕,然後繪製文字"""
self.screen.fill(self.button_color, self.button_rect)
self.screen.blit(self.msg_image, self.msg_image_rect)
7.settings.py(遊戲屬性設定)
# coding: UTF-8
# 建立Settings設定類---功能對應的設定
class Settings():
"""
《外星人入侵》的所有設定的類
"""
def __init__(self):
"""
初始化遊戲的靜態設定
"""
# 螢幕寬度和高度、背景顏色設定
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
# 飛船數量的設定
self.ship_limit = 3
# 子彈設定
self.bullet_width = 3
self.bullet_height = 10
self.bullet_color = 255, 0, 0
# 設定螢幕上可同時出現的子彈數
self.bullet_allowed = 8
# 外星人設定
self.fleet_drop_speed = 10
# 加快遊戲的節奏的速度
self.speedup_scale = 1.1
# 提高外星人得分節奏
self.score_scale = 1.5
self.initialize_dynamic_settings()
def initialize_dynamic_settings(self):
"""初始化隨遊戲進行而變化的動態設定"""
# 飛船移動速度
self.ship_speed_factor = 2.5
# 子彈移動速度
self.bullet_speed_factor = 2
# 外星人移動速度
self.alien_speed_factor = 1
# 每個外星人初始得分點
self.alien_points = 50
# fleet_direction為1表示向右移動 為-1表示向左移動
self.fleet_direction = 1
def increase_wen(self):
"""返回最初速度"""
self.alien_speed_factor = 1
# print("遊戲重新開始後的初始速度:" + str(self.alien_speed_factor))
def increase_speed(self):
"""逐漸提高速度設定"""
self.ship_speed_factor *= self.speedup_scale
self.bullet_speed_factor *= self.speedup_scale
self.alien_speed_factor *= self.speedup_scale
# print("遊戲過程中依次累加的速度:" + str(self.alien_speed_factor) + "\n")
# 逐漸提高外星人單次得分
self.alien_points = int(self.alien_points * self.score_scale)
# print(self.alien_points)
8.scoreboard.py(分數)
# # coding: UTF-8
# # 建立得分Score類
import pygame
from pygame.sprite import Group
from ship import Ship
class Scoreboard():
"""顯示得分資訊的類"""
def __init__(self, ai_settings, screen, game_stats):
"""初始化顯示得分涉及的屬性"""
self.screen = screen
self.screen_rect = screen.get_rect()
self.ai_settings = ai_settings
self.game_stats = game_stats
# 顯示得分資訊時使用的字型設定
self.text_color = (30, 30, 30)
self.font = pygame.font.SysFont(None, 48)
self.prep_images()
def prep_images(self):
"""準備包含 最高得分、當前得分、遊戲等級、飛船 的影像"""
# 當前得分影像
self.prep_score()
# 最高得分影像
self.prep_high_score()
# 等級影像
self.prep_level()
# 飛船組影像
self.prep_ships()
def prep_score(self):
"""將當前得分轉換為一幅渲染的影像"""
round_score = round(self.game_stats.score, -1) # 使得分為10的倍數 -1----10的倍數 -2--100的倍數 -3--1000的倍數
score_str = "score:" + "{:,}".format(round_score)
self.score_image = self.font.render(score_str, True, self.text_color,
self.ai_settings.bg_color)
# 將當前得分放在螢幕右上角
self.score_image_rect = self.score_image.get_rect()
self.score_image_rect.right = self.screen_rect.right - 20
self.score_image_rect.top = 20
def prep_high_score(self):
"""將最高得分轉換為一幅渲染的影像"""
high_round_score = round(self.game_stats.high_score, -1) # 使得分為10的倍數 -1----10的倍數 -2--100的倍數 -3--1000的倍數
high_score_str = "Mscore:" + "{:,}".format(high_round_score)
self.high_score_image = self.font.render(high_score_str, True, self.text_color,
self.ai_settings.bg_color)
# 將最高得分放在頂部螢幕中央
self.high_score_image_rect = self.high_score_image.get_rect()
self.high_score_image_rect.centerx = self.screen_rect.centerx
self.high_score_image_rect.top = self.score_image_rect.top
def prep_level(self):
"""將等級轉換為一幅渲染的影像"""
self.level_image = self.font.render(("lev:" + str(self.game_stats.level)), True,
self.text_color, self.ai_settings.bg_color)
# 將等級放在等分下面
self.level_image_rect = self.level_image.get_rect()
self.level_image_rect.right = self.score_image_rect.right
self.level_image_rect.top = self.score_image_rect.bottom + 10
def prep_ships(self):
"""顯示還剩下多少艘飛船"""
self.ships = Group()
for ship_number in range(self.game_stats.ships_left):
ship = Ship(self.ai_settings, self.screen)
ship.rect.x = 10 + ship_number * ship.rect.width
ship.rect.top = 10
self.ships.add(ship)
def show_score(self):
"""在螢幕上顯示當前得分和最高得分"""
self.screen.blit(self.score_image, self.score_image_rect)
self.screen.blit(self.high_score_image, self.high_score_image_rect)
self.screen.blit(self.level_image, self.level_image_rect)
# 繪製飛船
self.ships.draw(self.screen)
9.game_stats.py(遊戲狀態)
# coding: UTF-8
# 建立跟蹤遊戲統計資訊的Game_Stats類
import json
class Game_Stats():
"""跟蹤遊戲統計資訊的類"""
def __init__(self, ai_settings):
self.ai_settings = ai_settings
self.reset_stats()
# 遊戲剛啟動時處於活動狀態
self.game_active = False
# 在任何情況情況下都不應重置最高得分,載入歷史最高分
self.high_score = 0
with open('Max_score.json', encoding='UTF-8') as file:
self.high_score = json.load(file)
def reset_stats(self):
"""初始化在遊戲執行期間可能變化的統計資訊"""
self.ships_left = self.ai_settings.ship_limit
self.score = 0 # 每次有新的分數都應該重置
self.level = 1 # 設定遊戲等級
10.music.py(音效)
# coding: UTF-8
# 關於遊戲中各種聲音效果的模組
import pygame
def voice_large():
# 外星人到達了螢幕底部或者撞到飛船的大爆炸聲
explosion_large = pygame.mixer.Sound("musics/Explo_Large.wav")
explosion_large.play()
def voice_small():
# 增加子彈和外星人碰撞的小爆炸聲
explosion_small = pygame.mixer.Sound("musics/Explo_Small.wav")
explosion_small.play()
def bullet_biu():
# 增加子彈射出的biu聲
bullet_whiz = pygame.mixer.Sound("musics/Bullet_biu.wav")
bullet_whiz.play()
def bg_music():
# 遊戲背景音樂(若遊戲開始就一直播放)
pygame.mixer.music.load("musics/order_music.mp3")
11.遊戲圖片/音效素材獲取
(1)連結:https://pan.baidu.com/s/1A4VS59igzuEQi1JoDBabnA
提取碼:8lp3 (包括圖片以及音效)
(2)另外如果讀者想換音效 可進下面連結進行尋找
連結:https://www.aigei.com/music(本人也是從這扒的)
12.針對遊戲過程中各種報錯解決辦法思路的提醒
(1)最關鍵的一點:要抓住最終報錯語句 那句很很很關鍵 根據這句能夠快速定位報錯位置以及原因
(2)學會百度篩選有效解決辦法----這個能力至關重要
(3)找檔案中邏輯錯誤或書寫前後不統一的錯誤—這個是大部分人會犯的錯誤的 你以為是那樣的 實際不是那樣的
13.遊戲完成階段總結
從開始動手編寫到遊戲功能較完善的階段 花了2周 我現階段還是大學生每天有課要上 每天抽時間學 python也是自學一步一步慢慢走過來的 這其中遇到的問題也是千奇百怪的 讓人頭大 (難怪民間有種說法–計算機是玄學!!!)但很慶幸的是每個當時看起來艱難不可理解的報錯都被我ko了 這種感覺 經歷過的就會大大的懂 我個人是很享受那個過程的 進展緩慢每天打怪但每天都有收穫 如該遊戲過程中出現幾次無某某庫的時候 用“進入cmd 用pip install 報錯缺少的庫名”辦法基本能夠解決 嘻嘻…好啦 接下來讓遊戲放在朋友電腦上也可以玩 即使在沒有相應的pycharm/python的環境也可。
三、主.py檔案轉可執行.exe檔案
1.安裝pyinstaller:
win+r進入cmd介面→pip install pyinstaller→等待成功(pip list可檢測是否安裝pyinstaller)
2.主.py檔案轉可執行.exe檔案
(1)在cmd介面中進入遊戲中所有.py檔案同在的那個資料夾:
d:→cd Python-Projects\a book of py\Projects\Project1(alien_invasion) chapter 12-14\alien_invasion
(2)打包主.py檔案:
pyinstaller -F -w --add-data "musics/*.mp3;./musics" --add-data "musics/*.mav;./musics" alien_invasion.py
幾點說明:
i.*萬用字元,表示music資料夾裡所有的mp3檔案、所有的wav檔案 要使用雙引號
ii.windows系統要使用分號作為檔案原本的路徑和要存放的路徑的分隔符,這一點和linux系統不一樣,linux系統使用冒號
iii.要存放的路徑 ./music表示最外層目錄下的music目錄
引數解析:
pyinstaller xxx.py 打包成一個需要依賴檔案的exe
pyinstaller -F xxx.py 打包成一個單獨的exe,但是會有黑視窗
pyinstaller -F -w xxx.py 打包成一個單獨的exe去且除黑視窗==(遊戲中沒有用多媒檔案用這條命令)==
3.轉後事件處理
打包成功後 在alien_invasion資料夾在新出現三個檔案—build資料夾、dist資料夾、alien_invasion.spec檔案 :
可執行.exe檔案在dish資料夾中 雙擊執行它就可:
最終出現遊戲執行介面 play it 哈哈哈…看著蠻順利的是不 其實不然
各種報錯後面詳說
四、報錯情況分析以及解決辦法
1.雙擊alien_invasion.exe執行檔案出現閃退
(1)閃退理由:打包的時候只打包了alien_invasion.py主檔案 生成的alien_invasion.exe在dist資料夾 與遊戲所依賴的其他.py不在同一個目錄下 所以所以所以!.exe檔案在執行的時候找!不!到!相關的模組!故而不能執行!閃退
(.exe在黃色箭標頭檔案夾中 其他.py檔案在紅色框框所在資料夾中)
(2)解決辦法:把.exe檔案抬到所匯入模組所在的資料夾內就可以了。當然也可以把匯入的模組搬到.exe檔案所在的資料夾下,同一個道理的。
2.雙擊alien_invasion.exe執行檔案彈出“Faied to execute script ***”錯誤
(1)分析:出現這個錯誤的時候 一頭的霧水 就是簡單一句話 錯誤定位也無處下手 度娘上針對這個錯誤也是各種說法
(2)思路:為了看到具體報錯情況 後面所性把打包新出現的三個檔案刪除 重回到打包步驟----還記得上面有個“引數解析”不 把命令中的-w去掉:
pyinstaller -F --add-data "musics/*.mp3;./musics" --add-data "musics/*.mav;./musics" alien_invasion.py
這個時候再雙擊.exe可看到具體報錯情況以及定位:
(3)看到沒 說打不開音效檔案 報錯理由其實和報錯情況1(1)是一樣一樣的 故解決辦法也和報錯情況1(2)一樣一樣的
(當然啦如果你解決了報錯情況1的問題 原則上是不會出現情況2的錯誤的 —因為你都移動到同一個目錄下去啦)
五、壓縮.exe相關素材
終於!終於!終於!—要發給朋友玩啦(要記得把相關素材放進去哦 什麼圖片呀、音效呀等 使用說明是我自己為了朋友愉快的玩耍加進去哈)
這裡我也把遊戲放上來了哈 想試玩的朋友 可以下載玩玩
連結:https://pan.baidu.com/s/1lu9RHKrxjyBC7vfxMALQZA
提取碼:2qn0
後期有時間 會對遊戲改進完善的 可能到時候也會發帖子的呢
ps:在看這篇帖子的朋友有什麼疑問或能指出錯誤點的等等 都歡迎歡迎來訪 大家共同進步!!!
相關文章
- IDEA專案已新增jar包,pom檔案,打包Maven卻一直報錯的幾種解決方法IdeaJARMaven
- pyinstaller打包python成.exe檔案Python
- ROS 安裝過程中出現“hash校驗和不符”報錯解決辦法ROS
- docker 打包 opencv-python,libGL.so.1 報錯解決方法DockerOpenCVPython
- cnpm link 報錯解決辦法NPM
- 虛擬機器ping不通的幾種原因及解決辦法虛擬機
- 【python】打包神器--pyinstallerPython
- Python---pyinstaller打包Python
- python互動式專案例項 外星人入侵Python
- git報錯400的解決辦法Git
- Python專案實踐之二:外星人(1)Python
- python檔案打包利器之pyinstaller的使用Python
- Python-安裝部分包報錯解決辦法彙總Python
- Python AI小專案打包通關:Pyinstaller和Wix都用上了PythonAI
- 使用PyInstaller打包Python程式Python
- 適合小白練習的幾個Python小遊戲專案-含開發思路Python遊戲
- Mybatis批量更新SQL報錯☞解決辦法MyBatisSQL
- msfconsole,OpenSSL::PKey::PKeyError報錯解決辦法Error
- iOS路上遇到的錯誤及解決辦法iOS
- ORA-39006錯誤原因及解決辦法
- Python:使用pyinstaller打包含有gettext locales語言環境的專案Python
- 安裝wsl錯誤的一種解決辦法
- CSS元素高度塌陷的幾種常見解決辦法!CSS
- PyInstaller打包Python程式為exePython
- Jsp Unescaped xml character報錯的解決辦法JSXML
- 關於python操作帶有中文檔名報錯的解決辦法Python
- Python中的棧溢位及解決辦法Python
- npm啟動vue專案報錯error:0308010C:digital envelope routines::unsupported的解決辦法NPMVueErrorGit
- tensorflow安裝使用過程錯誤及解決方法
- 日常python報錯及解決方法記錄Python
- 幾種解決“藍芽不可用”問題的辦法藍芽
- python3.9安裝wordcloud出錯解決辦法PythonCloud
- eclipse :報錯 ‘XXXX‘ does not name a type的解決辦法Eclipse
- Laravel Mix - 執行 NPM install 報錯解決辦法LaravelNPM
- C語言中幾種報錯型別的解決方案C語言型別
- webpack打包過程如何除錯?Web除錯
- 【保姆級】Python專案(Flask網頁)部署到Docker的完整過程PythonFlask網頁Docker
- tplogin.cn登陸頁面進不去的幾種常見原因及解決辦法