首先,我們說了,飛機大戰和植物大戰殭屍差不多,有碰撞檢測啊、音效播放啊、等等一些東西
好,廢話不多說,開始
首先我們知道遊戲程式碼較多,我在這裏用小甲魚的吧,開啓
首先,我們是沒有下載pygame的。
我們看到了,這裏面有好多的import
我們一個一個的看
import random
表示進口隨機的意思
random是隨機的意思
裏邊有好多執行語句,我就不一一講解了
from pygame.locals import *
from random import *
import traceback
import tkinter as tk
import pygame
import math
import sys
"""\/\/\/\/\/\/\/\/------我的飛機類------\/\/\/\/\/\/\/\/"""
class MyPlane (pygame.sprite.Sprite): #定義我的飛機類,繼承動畫精靈類(因爲之後要進行碰撞檢測)
def __init__(self,bg_size,me1_image,me2_image) :
pygame.sprite.Sprite.__init__(self)
self.me1_image = me1_image
self.me2_image = me2_image
self.image1 = pygame.image.load(me1_image).convert_alpha() #第一張飛機圖片
self.image2 = pygame.image.load(me2_image).convert_alpha() #第二張飛機圖片 兩張圖片是爲了做出飛機噴氣的效果
#新增墜機圖片
self.destroy_images = []
self.me_destory_1_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\me_destroy_1.png").convert_alpha() #自身飛機炸燬第1張圖片
self.me_destory_2_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\me_destroy_2.png").convert_alpha() #自身飛機炸燬第2張圖片
self.me_destory_3_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\me_destroy_3.png").convert_alpha() #自身飛機炸燬第3張圖片
self.me_destory_4_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\me_destroy_4.png" ).convert_alpha() #自身飛機炸燬第4張圖片
self.destroy_images.extend([self.me_destory_1_image,self.me_destory_2_image,self.me_destory_3_image,self.me_destory_4_image])
self.rect = self.image1.get_rect() #獲得飛機圖片的尺寸
self.width , self.height = bg_size[0] , bg_size[1] #設定飛機允許活動地點
self.rect.left , self.rect.top = [ (self.width - self.rect.width) // 2 , \
(self.height - self.rect.height - 60) ] #設定我方飛機出現的位置
self.mask = pygame.mask.from_surface(self.image1) #給類新增上mask屬性,之後可以按照完美碰撞
self.speed = 10 #設定飛機出現的速度
self.active = True#設定飛機是否生存的狀態
self.invincible = True #是否處於無敵狀態
def moveup(self): #飛機向上飛的函數
if self.rect.top > 0: #如果我方飛機沒有飛出 上方邊界
self.rect.top -= 10 #那麼我方飛機朝上飛10個畫素
else : #飛出 上方邊界
self.rect.top = 0 #鎖定在0的位置,不再發生變化
def movedown(self): #飛機向下飛的函數
if self.rect.bottom < (self.height - 60) : #如果我方飛機沒有飛出 上方邊界
self.rect.bottom += 10 #那麼我方飛機朝下飛10個畫素
else : #飛出 下方邊界
self.rect.bottom = (self.height - 60) #鎖定在底邊界上方60的位置,不再發生變化
def moveleft(self): #飛機向左飛的函數
if self.rect.left > 0 : #如果我方飛機沒有飛出 左方邊界
self.rect.left -= 10 #那麼我方飛機朝下左10個畫素
else : #飛出 左方邊界
self.rect.left = 0 #鎖定在左邊界的位置,不再發生變化
def moveright(self): #飛機向下飛的函數
if self.rect.right < self.width : #如果我方飛機沒有飛出 上方邊界
self.rect.right += 10 #那麼我方飛機朝下飛10個畫素
else : #飛出 下方邊界
self.rect.right = self.width #鎖定在底邊界的位置,不再發生變化
def reset(self):
self.active = True#設定飛機是否生存的狀態
self.invincible = True #重新設定飛機處於無敵狀態
self.rect.left , self.rect.top = [ (self.width - self.rect.width) // 2 , \
(self.height - self.rect.height - 60) ] #設定我方飛機出現的位置
"""\/\/\/\/\/\/\/\/------敵機類------\/\/\/\/\/\/\/\/"""
"""本來這裏其實可以使用類的繼承,然後三種敵機分別繼承這個敵機類生成新的敵機,但是在這裏、
沒有這樣做的必要,因爲三個類的差別並不是很大,所以不用那麼繁雜"""
class SmallEnemy(pygame.sprite.Sprite): #定義我的低敵機類,繼承自動畫精靈
def __init__(self,bg_size,enemy1_image):
pygame.sprite.Sprite.__init__(self)
self.enemy1_image = enemy1_image
self.enemy1 = pygame.image.load(enemy1_image).convert_alpha() #載入低階敵機照片
#新增墜機圖片
self.destroy_images = []
self.enemy1_down1_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy1_down1.png").convert_alpha() #低階敵機撞到爆炸第1張圖片
self.enemy1_down2_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy1_down2.png").convert_alpha() #低階敵機撞到爆炸第2張圖片
self.enemy1_down3_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy1_down3.png").convert_alpha() #低階敵機撞到爆炸第3張圖片
self.enemy1_down4_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy1_down4.png").convert_alpha() #低階敵機撞到爆炸第4張圖片
self.destroy_images.extend([self.enemy1_down1_image,self.enemy1_down2_image,self.enemy1_down3_image,self.enemy1_down4_image])
self.width ,self.height = bg_size[0] , bg_size[1] #獲取生成低階敵機的活動範圍
self.rect = self.enemy1.get_rect() #獲得低階敵機的尺寸
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在視窗的5倍之上的距離中產生飛機
self.mask = pygame.mask.from_surface(self.enemy1) #給類新增上mask屬性,之後可以按照完美碰撞
self.speed = 3 #設定小敵機移動的速度
self.active = True #設定飛機是否生存的狀態
def move(self) : #小敵機的移動函數
if self.rect.top < self.height : #如果小飛機的底超出視窗的下邊框
self.rect.top += self.speed #小飛機向下移動他的速度
else : #如果小飛機已經超出視窗的下邊界框
self.reset() #重置小飛機
def reset(self) : #重置小飛機函數
self.active = True#設定飛機是否生存的狀態
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在視窗的5倍之上的距離中產生飛機
class MiddleEnemy(pygame.sprite.Sprite): #定義我的中敵機類,繼承自動畫精靈
energy = 8
def __init__(self,bg_size,enemy2_image):
pygame.sprite.Sprite.__init__(self)
self.enemy2_image = enemy2_image
self.enemy2 = pygame.image.load(enemy2_image).convert_alpha() #載入中級敵機照片
#新增墜機圖片
self.destroy_images = []
self.enemy2_down1_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy2_down1.png").convert_alpha() #中級敵機撞到爆炸第1張圖片
self.enemy2_down2_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy2_down2.png").convert_alpha() #中級敵機撞到爆炸第2張圖片
self.enemy2_down3_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy2_down3.png").convert_alpha() #中級敵機撞到爆炸第3張圖片
self.enemy2_down4_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy2_down4.png").convert_alpha() #中級敵機撞到爆炸第4張圖片
self.enemy2_hit_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy2_hit.png").convert_alpha() #中級敵機被子彈打到後圖片
self.destroy_images.extend([self.enemy2_down1_image,self.enemy2_down2_image,self.enemy2_down3_image,self.enemy2_down4_image])
self.width ,self.height = bg_size[0] , bg_size[1] #獲取生成低階敵機的活動範圍
self.rect = self.enemy2.get_rect() #獲得中級敵機的尺寸
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-10*self.height , 0) ] #在視窗的5倍之上的距離中產生飛機
self.mask = pygame.mask.from_surface(self.enemy2) #給類新增上mask屬性,之後可以按照完美碰撞
self.speed = 2 #設定中敵機移動的速度
self.active = True #設定飛機是否生存的狀態
self.energy = MiddleEnemy.energy #設定敵機的生命值
self.hit = False #敵機是否被撞的狀態
def move(self) : #中敵機的移動函數
if self.rect.top < self.height : #如果中飛機的底超出視窗的下邊框
self.rect.top += self.speed #中飛機向下移動他的速度
else : #如果中飛機已經超出視窗的下邊界框
self.reset() #重置中飛機
def reset(self) : #重置中飛機函數
self.active = True#設定飛機是否生存的狀態
self.hit = False
self.energy = 8
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-10*self.height , 0) ] #在視窗的5倍之上的距離中產生飛機
class BigEnemy(pygame.sprite.Sprite): #定義我的大敵機類,繼承自動畫精靈
energy = 20
def __init__(self,bg_size,enemy3_n1_image,enemy3_n2_image):
pygame.sprite.Sprite.__init__(self)
self.enemy3_n1_image = enemy3_n1_image
self.enemy3_n1 = pygame.image.load(enemy3_n1_image).convert_alpha() #載入高階敵機照片
self.enemy3_n2_image = enemy3_n1_image
self.enemy3_n2 = pygame.image.load(enemy3_n2_image).convert_alpha() #載入高階敵機照片
#新增墜機圖片
self.destroy_images = []
self.enemy3_down1_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_down1.png").convert_alpha() #高階敵機撞到爆炸第1張圖片
self.enemy3_down2_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_down2.png").convert_alpha() #高階敵機撞到爆炸第2張圖片
self.enemy3_down3_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_down3.png").convert_alpha() #高階敵機撞到爆炸第3張圖片
self.enemy3_down4_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_down4.png").convert_alpha() #高階敵機撞到爆炸第4張圖片
self.enemy3_down5_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_down5.png").convert_alpha() #高階敵機撞到爆炸第5張圖片
self.enemy3_down6_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_down6.png").convert_alpha() #高階敵機撞到爆炸第6張圖片
self.enemy3_hit_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_hit.png").convert_alpha() #高階敵機被子彈打到後圖片
self.destroy_images.extend([self.enemy3_down1_image,self.enemy3_down1_image,self.enemy3_down3_image,self.enemy3_down4_image,\
self.enemy3_down5_image,self.enemy3_down6_image ])
self.width ,self.height = bg_size[0] , bg_size[1] #獲取生成低階敵機的活動範圍
self.rect = self.enemy3_n1.get_rect() #獲得低階敵機的尺寸
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-15*self.height , 0) ] #在視窗的5倍之上的距離中產生飛機
self.mask = pygame.mask.from_surface(self.enemy3_n1) #給類新增上mask屬性,之後可以按照完美碰撞
self.speed = 1 #設定大敵機移動的速度
self.active = True#設定飛機是否生存的狀態
self.energy = BigEnemy.energy #設定敵機的生命值
self.hit = False #敵機是否被撞的狀態
def move(self) : #大敵機的移動函數
if self.rect.top < self.height : #如果大飛機的底超出視窗的下邊框
self.rect.top += self.speed #大飛機向下移動他的速度
else : #如果大飛機已經超出視窗的下邊界框
self.reset() #重置大飛機
def reset(self) : #重置大飛機函數
self.active = True#設定飛機是否生存的狀態
self.hit = False
self.energy = 20
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-15*self.height , 0) ] #在視窗的5倍之上的距離中產生飛機
"""\/\/\/\/\/\/\/\/------子彈類------\/\/\/\/\/\/\/\/"""
class Bullet1 (pygame.sprite.Sprite): #定義子彈類,繼承動畫精靈類(因爲之後要進行碰撞檢測)
def __init__(self,bullet1_image,position) :
pygame.sprite.Sprite.__init__(self)
self.bullet1_image = bullet1_image #子彈1圖的路徑
self.image = pygame.image.load(bullet1_image).convert_alpha() #載入子彈1圖
self.rect = self.image.get_rect() #獲得子彈1圖的尺寸
self.rect.left , self.rect.top = position #把飛機的位置傳給子彈
self.speed = 12 #子彈運動的速度
self.active = True #用來表示這顆子彈是或否失效
self.mask = pygame.mask.from_surface(self.image) #給類新增上mask屬性
def move(self) :
self.rect.top -= self.speed #子彈的運動
if self.rect.top < 0: #射出螢幕外
self.active = False #將子彈設定爲失效
def reset(self, position):
self.rect.left, self.rect.top = position
self.active = True
class Bullet2(pygame.sprite.Sprite):
def __init__(self,bullet2_image,position):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(bullet2_image).convert_alpha()
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
self.speed = 14
self.active = False
self.mask = pygame.mask.from_surface(self.image)
def move(self):
self.rect.top -= self.speed
if self.rect.top < 0:
self.active = False
def reset(self, position):
self.rect.left, self.rect.top = position
self.active = True
"""\/\/\/\/\/\/\/\/------補給類------\/\/\/\/\/\/\/\/"""
class Bullet_Supply(pygame.sprite.Sprite):
def __init__(self,bg_size) :
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load( r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\bullet_supply.png").convert_alpha() #補給子彈圖
self.rect = self.image.get_rect()
self.width , self.height = bg_size[0] ,bg_size[1]
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100 #隨機生成補給的位置
self.speed = 5 #補給下落的速度
self.active = False #補給是否啓用
self.mask = pygame.mask.from_surface(self.image)
def move (self) : #運動函數
if self.rect.top < self.height :
self.rect.top += self.speed
else :
self.active = False
def reset(self): #重置函數
self.active = True
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100
class Bomb_Supply(pygame.sprite.Sprite):
def __init__(self,bg_size) :
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load( r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\bomb_supply.png").convert_alpha() #全螢幕炸彈補給圖
self.rect = self.image.get_rect()
self.width , self.height = bg_size[0] ,bg_size[1]
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100 #隨機生成補給的位置
self.speed = 5 #補給下落的速度
self.active = False #補給是否啓用
self.mask = pygame.mask.from_surface(self.image)
def move (self) : #運動函數
if self.rect.top < self.height :
self.rect.top += self.speed
else :
self.active = False
def reset(self): #重置函數
self.active = True
self.rect.left ,self.rect.top = randint(0,self.width-self.rect.width) , -100
def main() :
pygame.init() #初始化
pygame.mixer.init() #混音器初始化
clock = pygame.time.Clock() #設定一個計時器
transform = False #設定一個是否改變的變數
delay = 100 #類似於微控制器,設定一個延時變數,讓飛機的改變看起來更加的順滑
switch_image = True # 用於切換圖片
running = True
#建立字型的標誌
font = pygame.font.Font(r'D:\Code\Python\Pygame\font\font.ttf',35)
#初始化分數
score = 0
score_font = pygame.font.Font(r"D:\Code\Python\Pygame\font\font.ttf", 36)
#初始化我方飛機數量,生命爲3條
life_num = 3
#設定難度等級
level = 1
black = ([0,0,0]) #黑色
green = ([0,255,0]) #綠色
red = ([255,0,0]) #紅色
white = ([255,255,255]) #白色
"""載入音樂檔案"""
#背景音樂
pygame.mixer.music.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\game_music.ogg") #設定背景音樂
pygame.mixer.music.set_volume(1) #設定音量
#遊戲音效
bullet_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\bullet.wav") #子彈特效
bullet_sound.set_volume(0.5)
button_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\button.wav") #按鍵特效
button_sound.set_volume(0.5)
enemy1_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\enemy1_down.wav") #低等敵機被擊毁音效
enemy1_down_sound.set_volume(0.5)
enemy2_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\enemy2_down.wav") #中等敵機被擊毁音效
enemy2_down_sound.set_volume(0.5)
enemy3_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\enemy3_down.wav") #高等敵機被擊毁音效
enemy3_down_sound.set_volume(0.5)
enemy3_fly_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\enemy3_flying.wav") #高等敵機出現音效
enemy3_fly_sound.set_volume(0.5)
get_bomb_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\get_bomb.wav") #獲得全螢幕炸彈補給音效
get_bomb_sound.set_volume(0.5)
get_bullet_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\get_bullet.wav") #獲得雙倍子彈補給音效
get_bullet_sound.set_volume(0.5)
myself_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\me_down.wav") #自身飛機被擊毁(死亡)音效
myself_down_sound.set_volume(0.5)
supply_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\supply.wav") #補給產生音效
supply_sound.set_volume(0.5)
upgrade_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\upgrade.wav") #升級音效
upgrade_sound.set_volume(0.5)
use_bomb_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飛機大戰\sound\use_bomb.wav") #使用全螢幕炸彈音效
use_bomb_sound.set_volume(0.5)
"""圖片檔案路徑"""
background_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\background.png" #背景圖的路徑
bullet1_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\bullet1.png" #第一種子彈圖
bullet2_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\bullet2.png" #第二種子彈圖
enemy1_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy1.png" #低階敵機圖片
enemy2_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy2.png" #中級敵機圖片
enemy3_n1_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_n1.png" #高階敵機圖片1
enemy3_n2_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\enemy3_n2.png" #高階敵機圖片2
me1_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\me1.png" #自身飛機第一張圖片
me2_image = r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\me2.png" #自身飛機第二張圖片
#設定背景
bg_size = width , height = 430 , 700 #背景大小
screen = pygame.display.set_mode(bg_size) #這是背景大小
background = pygame.image.load(background_image).convert_alpha() #畫背景
pygame.mixer.music.set_volume(1) #設定音量
pygame.mixer.music.play(-1) #播放背景音樂,-1 表示無限回圈播放
# 標誌是否暫停遊戲
paused = False
pause_nor_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\pause_nor.png" ).convert_alpha() #暫停的時候圖片
pause_pressed_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\pause_pressed.png" ).convert_alpha() #暫停到繼續的中間變換圖
resume_nor_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\resume_nor.png").convert_alpha() #繼續的時候的圖片
resume_pressed_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\resume_pressed.png" ).convert_alpha() #繼續到暫停的中間變換圖
paused_rect = pause_nor_image.get_rect()
paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10
paused_image = pause_nor_image
#補給包
bullet_supply = Bullet_Supply(bg_size)
bomb_supply = Bomb_Supply(bg_size)
supply_timer = USEREVENT
pygame.time.set_timer(supply_timer,30000) #設定自定義事件每隔30s返回一個使用者自定義事件屬性
#超級子彈定時器
double_bullet_timer = USEREVENT + 1
# 標誌是否使用超級子彈
is_double_bullet = False
# 全螢幕炸彈
bomb_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\bomb.png").convert_alpha()
bomb_rect = bomb_image.get_rect()
bomb_font = pygame.font.Font(r"D:\Code\Python\Pygame\font\font.ttf", 48)
bomb_num = 3
#載入生命圖片
life_image =pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\life.png").convert_alpha() #表示生命值的圖片
life_image_rect = life_image.get_rect()
#中彈圖片索引
e1_destroy_index = 0
e2_destroy_index = 0
e3_destroy_index = 0
myself_destroy_index = 0
#生成自己飛機
myself = MyPlane(bg_size,me1_image,me2_image)
#無敵時間計時器
myself_invincible_timer = USEREVENT + 2
pygame.time.set_timer(myself_invincible_timer, 3*1000) #3秒
#建立子彈
bullet1 = [] #建立一個子彈列表
bullet1_index = 0 #建立一個搜尋子彈的下標
bullet1_num = 4 #一次性建立子彈的數量
for i in range (bullet1_num) : #回圈生成子彈
bullet1.append(Bullet1(bullet1_image,myself.rect.midtop)) #使用子彈類生成子彈
# 生成超級子彈
bullet2 = []
bullet2_index = 0
bullet2_num = 8
for i in range(bullet2_num//2):
bullet2.append(Bullet2(bullet2_image,(myself.rect.centerx-33, myself.rect.centery)))
bullet2.append(Bullet2(bullet2_image,(myself.rect.centerx+30, myself.rect.centery)))
#生成敵機組
def add_smallenemies(group1, group2, num):
for i in range(num):
e1 = SmallEnemy(bg_size,enemy1_image)
group1.add(e1)
group2.add(e1)
def add_middleenemies(group1, group2, num):
for i in range(num):
e2 = MiddleEnemy(bg_size,enemy2_image)
group1.add(e2)
group2.add(e2)
def add_bigenemies(group1, group2, num):
for i in range(num):
e3 = BigEnemy(bg_size,enemy3_n1_image,enemy3_n2_image)
group1.add(e3)
group2.add(e3)
#提升所有飛機的速度
def inc_speed(group,addspeed):
for each in group :
each.speed += addspeed
#生成敵機組
enemies = pygame.sprite.Group() #生成整個飛機組
smallenemies = pygame.sprite.Group() #生成小飛機組
add_smallenemies(smallenemies,enemies,20) #生成小型飛機
middleenemies = pygame.sprite.Group() #生成中飛機組
add_middleenemies(middleenemies,enemies,10) #生成中型飛機
bigenemies = pygame.sprite.Group() #生成大飛機組
add_bigenemies(bigenemies,enemies,4) #生成大型飛機
# 用於阻止重複開啓記錄檔案
recorded = False
#結束的全部東西
gameover_font = pygame.font.Font(r"D:\Code\Python\Pygame\font\font.ttf", 48)
again_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\again.png" ).convert_alpha()
again_rect = again_image.get_rect()
gameover_image = pygame.image.load(r"D:\Code\Python\Pygame\pygame11:飛機大戰\images\gameover.png").convert_alpha()
gameover_rect = gameover_image.get_rect()
while running :
for event in pygame.event.get() :
if event.type == QUIT :
sys.exit()
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1 and paused_rect.collidepoint(event.pos): #如果檢測到滑鼠在暫停位置按下點選按鈕
paused = not paused #puase標誌鍵變爲True
if paused_rect.collidepoint(event.pos): #讓暫停圖示在滑鼠按下時立即改變
if paused:
paused_image = resume_pressed_image
else:
paused_image = pause_pressed_image
else:
if paused:
paused_image = resume_nor_image
else:
paused_image = pause_nor_image
screen.blit(paused_image,(width - paused_rect.width,5)) #繪製此時的暫停按鈕
if paused : #如果暫停了
pygame.time.set_timer(supply_timer,0)
pygame.mixer.music.pause()
pygame.mixer.pause()
else :
pygame.time.set_timer(supply_timer,30000)
pygame.mixer.music.unpause()
pygame.mixer.unpause()
elif event.type == MOUSEMOTION: #滑鼠是否移動到暫停照片上顯示不同的圖片
if paused_rect.collidepoint(event.pos):
if paused:
paused_image = resume_pressed_image
else:
paused_image = pause_pressed_image
else:
if paused:
paused_image = resume_nor_image
else:
paused_image = pause_nor_image
elif event.type == KEYDOWN :
if event.key == K_SPACE: #如果按下空格鍵,投放超級炸彈
if bomb_num : #如果還有超級炸彈,那麼炸彈數量-1
bomb_num -= 1
use_bomb_sound.play()
for each in enemies:
if each.rect.bottom > 0:
each.active = False
if event.key == K_0 : #如果按下0鍵
bomb_num += 1
elif event.type == supply_timer : #響應補給包事件
supply_sound.play() #播放補給的聲音
if choice([True,False]) : #隨機生成子彈補給或者炸藥補給
bullet_supply.reset()
else :
bomb_supply.reset()
elif event.type == double_bullet_timer: #響應超級子彈事件
is_double_bullet = False
pygame.time.set_timer(double_bullet_timer, 0)
elif event.type == myself_invincible_timer: #響應無敵事件
myself.invincible = False
# 根據使用者的得分增加難度
if level == 1 and score > 50000:
level = 2
upgrade_sound.play()
# 增加3架小型敵機、2架中型敵機和1架大型敵機
add_smallenemies(smallenemies, enemies, 3)
add_middleenemies(middleenemies, enemies, 2)
add_bigenemies(bigenemies, enemies, 1)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
elif level == 2 and score > 300000:
level = 3
upgrade_sound.play()
# 增加5架小型敵機、3架中型敵機和2架大型敵機
add_smallenemies(smallenemies, enemies, 5)
add_middleenemies(middleenemies, enemies, 3)
add_bigenemies(bigenemies, enemies, 2)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
inc_speed(middleenemies, 1)
elif level == 3 and score > 600000:
level = 4
upgrade_sound.play()
# 增加5架小型敵機、3架中型敵機和2架大型敵機
add_smallenemies(smallenemies, enemies, 5)
add_middleenemies(middleenemies, enemies, 3)
add_bigenemies(bigenemies, enemies, 2)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
inc_speed(middleenemies, 1)
elif level == 4 and score > 1000000:
level = 5
upgrade_sound.play()
# 增加5架小型敵機、3架中型敵機和2架大型敵機
add_smallenemies(smallenemies, enemies, 5)
add_middlenemies(middleenemies, enemies, 3)
add_bigenemies(bigenemies, enemies, 2)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
inc_speed(middleenemies, 1) # 根據使用者的得分增加難度
if level == 1 and score > 50000:
level = 2
upgrade_sound.play()
# 增加3架小型敵機、2架中型敵機和1架大型敵機
add_smallenemies(smallenemies, enemies, 3)
add_middleenemies(middleenemies, enemies, 2)
add_bigenemies(bigenemies, enemies, 1)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
elif level == 2 and score > 300000:
level = 3
upgrade_sound.play()
# 增加5架小型敵機、3架中型敵機和2架大型敵機
add_smallenemies(smallenemies, enemies, 5)
add_middleenemies(middleenemies, enemies, 3)
add_bigenemies(bigenemies, enemies, 2)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
inc_speed(middleenemies, 1)
elif level == 3 and score > 600000:
level = 4
upgrade_sound.play()
# 增加5架小型敵機、3架中型敵機和2架大型敵機
add_smallenemies(smallenemies, enemies, 5)
add_middleenemies(middleenemies, enemies, 3)
add_bigenemies(bigenemies, enemies, 2)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
inc_speed(middleenemies, 1)
elif level == 4 and score > 1000000:
level = 5
upgrade_sound.play()
# 增加5架小型敵機、3架中型敵機和2架大型敵機
add_smallenemies(smallenemies, enemies, 5)
add_middlenemies(middleenemies, enemies, 3)
add_bigenemies(bigenemies, enemies, 2)
# 提升小型敵機的速度
inc_speed(smallenemies, 1)
inc_speed(middleenemies, 1)
#如果沒有暫停
if life_num and not paused:
screen.blit(background,(0,0)) #繪製背景
#檢查是否有上下左右或wsad按下,如有則對飛機進行相應的控制
key_press = pygame.key.get_pressed()
if key_press[K_w] or key_press[K_UP] : #如果按下上鍵或者↑
myself.moveup() #飛船向上飛行
elif key_press[K_s] or key_press[K_DOWN] : #如果按下下鍵或者↓
myself.movedown() #飛船向下飛行
elif key_press[K_a] or key_press[K_LEFT] : #如果按下左鍵或者←
myself.moveleft() #飛船向左飛行
elif key_press[K_d] or key_press[K_RIGHT] : #如果按下右鍵或者→
myself.moveright() #飛船向右飛行
#繪製暫停和繼續按鈕
screen.blit(paused_image,(width - paused_rect.width,5)) #繪製暫停按鈕
#繪製我方飛機
if life_num :
# 繪製大型敵機
for each in bigenemies:
if each.active: #如果大型敵機爲生存狀態
each.move()
pygame.draw.line(screen, black, \
(each.rect.left, each.rect.top - 5), \
(each.rect.right, each.rect.top - 5), \
2)
# 當生命大於20%顯示綠色,否則顯示紅色
energy_remain = each.energy / BigEnemy.energy
if energy_remain > 0.2:
energy_color = green
else:
energy_color = red
pygame.draw.line(screen, energy_color, \
(each.rect.left, each.rect.top - 5), \
(each.rect.left + each.rect.width * energy_remain, \
each.rect.top - 5),2)
if each.hit : #如果被撞
screen.blit(each.enemy3_hit_image,each.rect)
each.hit = False
else : #如果沒有被撞
if switch_image: #判斷是否交換圖片
screen.blit(each.enemy3_n1, each.rect)
else:
screen.blit(each.enemy3_n2, each.rect)
# 即將出現在畫面中,播放音效
if each.rect.bottom == -50:
enemy3_fly_sound.play()
else:
#如果大型敵機爲撞毁狀態
if not (delay % 3) :
if e3_destroy_index == 0: #當索引再次變爲0時
enemy3_down_sound.play() #播放聲音
screen.blit(each.destroy_images[e3_destroy_index], each.rect)
e3_destroy_index = (e3_destroy_index + 1) % 6
if e3_destroy_index == 0: #當索引再次變爲0時
enemy3_down_sound.stop()
score += 10000 #打掉大型飛機+10000分
each.reset() #重置飛機
# 繪製中型敵機:
for each in middleenemies:
if each.active : #如果此敵機的爲存活狀態
each.move()
if each.hit : #如果被撞
screen.blit(each.enemy2_hit_image,each.rect)
each.hit = False
else : #如果沒有被撞
screen.blit(each.enemy2, each.rect)
pygame.draw.line(screen, black, \
(each.rect.left, each.rect.top - 5), \
(each.rect.right, each.rect.top - 5), \
2)
# 當生命大於20%顯示綠色,否則顯示紅色
energy_remain = each.energy / MiddleEnemy.energy
if energy_remain > 0.2:
energy_color = green
else:
energy_color = red
pygame.draw.line(screen, energy_color, \
(each.rect.left, each.rect.top - 5), \
(each.rect.left + each.rect.width * energy_remain, \
each.rect.top - 5),2)
else :
#敵機撞毁
if not (delay % 3) :
if e2_destroy_index == 0: #當索引再次變爲0時
enemy2_down_sound.play() #播放聲音
screen.blit(each.destroy_images[e2_destroy_index], each.rect)
e2_destroy_index = (e2_destroy_index + 1) % 4
if e2_destroy_index == 0: #當索引再次變爲0時
score += 6000 #打掉大型飛機+6000分
each.reset() #重置飛機
# 繪製小型敵機:
for each in smallenemies:
if each.active : #如果此敵機的爲存活狀態
each.move()
screen.blit(each.enemy1, each.rect)
else :
#敵機撞毁
if not (delay % 3) :
if e1_destroy_index == 0: #當索引再次變爲0時
enemy1_down_sound.play() #播放聲音
screen.blit(each.destroy_images[e1_destroy_index], each.rect)
e1_destroy_index = (e1_destroy_index + 1) % 4
if e1_destroy_index == 0: #當索引再次變爲0時
score += 1000 #打掉小型飛機+1000分
each.reset() #重置飛機
if myself.active : #如果我方飛機active的屬性爲真,即未和其他飛機發生碰撞
if transform : #如果改變屬性爲真 畫第一張飛機圖
screen.blit(myself.image1,myself.rect) #繪製第一張飛機圖
else : #如果改變屬性爲假 畫第二張飛機圖
screen.blit(myself.image2,myself.rect) #繪製第二張飛機圖
else:
#我方飛機撞毁
myself_down_sound.play()
if not (delay % 3) :
screen.blit(myself.destroy_images[myself_destroy_index], myself.rect)
myself_destroy_index = (myself_destroy_index + 1) % 4
if myself_destroy_index == 0:
life_num -= 1
myself.reset()
#繪製從飛機中出現的子彈
if not (delay % 10) : #設定每10幀射出一個子彈
bullet_sound.play()
if is_double_bullet:
bullets = bullet2
bullets[bullet2_index].reset((myself.rect.centerx-33, myself.rect.centery))
bullets[bullet2_index+1].reset((myself.rect.centerx+30, myself.rect.centery))
bullet2_index = (bullet2_index + 2) % bullet2_num
else:
bullets = bullet1
bullet1[bullet1_index].reset(myself.rect.midtop) #將子彈的座標初放到飛機的前面
bullet1_index = (bullet1_index + 1) % bullet1_num #使子彈的下標始終處於0-4間不斷回圈
score_text = font.render('score = %s' %str(score),True,white) #繪製分數
screen.blit(score_text,(10,5)) #繪製分數
# 繪製全螢幕炸彈數量
bomb_text = bomb_font.render("× %d" % bomb_num, True, white)
text_rect = bomb_text.get_rect()
screen.blit(bomb_image, (10, height - 10 - bomb_rect.height))
screen.blit(bomb_text, (20 + bomb_rect.width, height - 5 - text_rect.height))
#繪製我方飛機生命數量
if life_num :
for i in range(life_num):
screen.blit(life_image,(width-((i+1)*life_image_rect.width) , height - 5- life_image_rect.height))
#檢測子彈是否擊中敵機
for b in bullets: #對於列表中的的所有子彈
if b.active : #如果子彈有效
b.move() #子彈移動
screen.blit(b.image,b.rect) #把子彈繪製在背景上
enemies_hit = pygame.sprite.spritecollide(b,enemies,False,collided=pygame.sprite.collide_mask) #將所有與子彈發生碰撞的敵方飛機都加入到組中
if enemies_hit : #如果有敵機與子彈相碰
b.active = False #將碰撞後在子彈設定爲未啓用,使其消失,不再繼續存在在畫面中
for e in enemies_hit : #對於所有相撞的敵機
if (e in middleenemies) or (e in bigenemies) : #如果敵機是中型飛機或者大型飛機
e.hit = True #將敵機的撞擊屬性設定爲已碰撞
e.energy -= 1 #生命值-1
if e.energy == 0 : #如果生命值變爲0
e.active = False #將敵機的生命屬性設定爲死亡
e.hit = False #重新降低及的撞擊屬性變爲未撞擊
else : #小型敵機
e.active = False #將他們的狀態設定爲死亡
if not (delay % 5) :
transform = not transform #改變transform的屬性來打到改變圖片的效果
switch_image = not switch_image #改變switch_image 來改變大型飛機的圖片
if not delay : #如果delay值變爲0那麼重新調回100
delay = 100
delay -= 1
#檢查雙方飛機是否發生碰撞
if not myself.invincible :
enemies_down = pygame.sprite.spritecollide(myself, enemies, False,collided=pygame.sprite.collide_mask) #將所有與我們的飛機發生碰撞的敵方飛機都加入到組中
if enemies_down: #如果組中有成員,說明又發生碰撞
myself.active = False #我放飛機存活狀態變成False
for e in enemies_down:
e.active = False #對於與我相撞的飛機的也設爲False
#繪製全螢幕炸彈補給並檢測是否發生碰撞
if bomb_supply.active : #如果炸彈補給是啓用的
bomb_supply.move() #補給移動
supply_sound.play() #播放炸彈補給出現音樂
screen.blit(bomb_supply.image,bomb_supply.rect) #繪製補給圖片
if pygame.sprite.collide_mask(bomb_supply,myself): #檢測補給和我放飛機是否發送碰撞
bomb_supply.active = False #如果發生碰撞,那麼補給變爲未啓用狀態
get_bomb_sound.play()#播放得到補給的音效
if bomb_num < 3: #如果炸彈數小於3
bomb_num += 1 #炸彈數+1
#繪製子彈補給並檢測是否發生碰撞
if bullet_supply.active : #如果子彈補給是啓用的
bullet_supply.move() #補給移動
screen.blit(bullet_supply.image,bullet_supply.rect) #繪製補給圖片
if pygame.sprite.collide_mask(bullet_supply,myself): #檢測補給和我放飛機是否發送碰撞
bullet_supply.active = False #如果發生碰撞,那麼補給變爲未啓用狀態
get_bullet_sound.play()#播放得到補給的音效
# 繪製超級子彈補給並檢測是否獲得
if bullet_supply.active:
bullet_supply.move()
screen.blit(bullet_supply.image, bullet_supply.rect)
if pygame.sprite.collide_mask(bullet_supply, myself):
get_bullet_sound.play()
#發射超級子彈18秒
is_double_bullet = True
pygame.time.set_timer(double_bullet_timer, 18 * 1000)
bullet_supply.active = False
elif life_num and paused : #如果暫停了
pygame.mixer.music.pause() #暫停背景音樂
screen.blit(background,(0,0)) #繪製背景
#繪製暫停和繼續按鈕
screen.blit(paused_image,(width - paused_rect.width,5)) #繪製暫停按鈕
# 繪製遊戲結束畫面
elif life_num == 0:
# 背景音樂停止
pygame.mixer.music.stop()
# 停止全部音效
pygame.mixer.stop()
# 停止發放補給
pygame.time.set_timer(supply_timer, 0)
if not recorded:
recorded = True
# 讀取歷史最高得分
with open(r"D:\Code\Python\Pygame\pygame11:飛機大戰\record.txt", "r") as f:
record_score = int(f.read())
# 如果玩家得分高於歷史最高得分,則存檔
if score > record_score:
with open(r"D:\Code\Python\Pygame\pygame11:飛機大戰\record.txt", "w") as f:
f.write(str(score))
screen.blit(background,(0,0)) #繪製背景
# 繪製結束畫面
record_score_text = score_font.render("Best : %d" % record_score, True, (255, 255, 255))
screen.blit(record_score_text, (50, 50))
gameover_text1 = gameover_font.render("Your Score", True, (255, 255, 255))
gameover_text1_rect = gameover_text1.get_rect()
gameover_text1_rect.left, gameover_text1_rect.top = \
(width - gameover_text1_rect.width) // 2, height // 3
screen.blit(gameover_text1, gameover_text1_rect)
gameover_text2 = gameover_font.render(str(score), True, (255, 255, 255))
gameover_text2_rect = gameover_text2.get_rect()
gameover_text2_rect.left, gameover_text2_rect.top = \
(width - gameover_text2_rect.width) // 2, \
gameover_text1_rect.bottom + 10
screen.blit(gameover_text2, gameover_text2_rect)
again_rect.left, again_rect.top = \
(width - again_rect.width) // 2, \
gameover_text2_rect.bottom + 50
screen.blit(again_image, again_rect)
gameover_rect.left, gameover_rect.top = \
(width - again_rect.width) // 2, \
again_rect.bottom + 10
screen.blit(gameover_image, gameover_rect)
# 檢測使用者的滑鼠操作
# 如果使用者按下滑鼠左鍵
if pygame.mouse.get_pressed()[0]:
# 獲取滑鼠座標
pos = pygame.mouse.get_pos()
# 如果使用者點選「重新開始」
if again_rect.left < pos[0] < again_rect.right and \
again_rect.top < pos[1] < again_rect.bottom:
# 呼叫main函數,重新開始遊戲
main()
# 如果使用者點選「結束遊戲」
elif gameover_rect.left < pos[0] < gameover_rect.right and \
gameover_rect.top < pos[1] < gameover_rect.bottom:
# 退出遊戲
pygame.quit()
sys.exit()
pygame.display.flip() #不停的重新整理畫面,不停的繪畫
clock.tick(60) #設定影格率
if __name__ == "__main__":
# 這樣做的好處是雙擊開啓時如果出現異常可以報告異常,而不是一閃而過!
try:
main()
except SystemExit: #這是按下 × 的異常,直接忽略
pass
except:
traceback.print_exc()
pygame.quit()
input()
好吧,說完了。
內容中的一個註釋:# 這樣做的好處是雙擊開啓時如果出現異常可以報告異常,而不是一閃而過!
很好