之前我们实现了游戏的背景和背景音乐,接下来,我们应该让主角闪亮登场了,创建一个名为 myplane 的模块,然后把我方飞机的所有属性和方法定义在里边。(在这里我就是直接写在一个模块里了。图片啥的也都一开始全部导入了,先单独分开把,之后整合到一起)
from pygame.locals import *
from random import *
import pygame
import sys
"""\/\/\/\/\/\/\/\/------我的飞机类------\/\/\/\/\/\/\/\/"""
me1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me1.png" #自身飞机第一张图片
me2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me2.png" #自身飞机第二张图片
class MyPlane (pygame.sprite.Sprite): #定义我的飞机类,继承动画精灵类(因为之后要进行碰撞检测)
def __init__(self,bg_size,me1_image,me2_image) :
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.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.speed = 10 #设置飞机出现的速度
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 #锁定在底边界的位置,不再发生变化
那么接下来我们就需要在 main 模块中响应用户的键盘操作,响应用户的键盘操作有两种方法:
1、通过检测事件消息,检测到如果有 KEYDOWN 或者 KEYUP 事件,我们就知道是用户按下了键盘按键。(这是我们之前常用的一种方法)
2、调用 key 模块里的 get_pressed() 方法,会返回一个序列,该序列包含键盘上所有按键的布尔类型的值,如果这个值是True 的话,表示该按键被按下。
我们这里有一个建议:对于检测偶然触发的键盘事件,我们推荐使用方法1,例如该游戏中会设置一个全屏炸弹,按下空格键时爆炸,这是偶然触发的,没有经常触发,这时使用第1种方法较好;对于频繁触发的键盘事件,我们则建议使用第二种方法,例如控制飞机移动的4个方向键,我们就使用方法2。
接着来改一下我们的 main 函数:(已经将myplane()放入到主函数中)
from pygame.locals import *
from random import *
import traceback
import tkinter as tk
import pygame
import math
import sys
from pygame.locals import *
from random import *
import pygame
import sys
"""\/\/\/\/\/\/\/\/------我的飞机类------\/\/\/\/\/\/\/\/"""
class MyPlane (pygame.sprite.Sprite): #定义我的飞机类,继承动画精灵类(因为之后要进行碰撞检测)
def __init__(self,bg_size,me1_image,me2_image) :
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.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.speed = 10 #设置飞机出现的速度
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 main() :
pygame.init() #初始化
pygame.mixer.init() #混音器初始化
clock = pygame.time.Clock() #设置一个计时器
"""载入音乐文件"""
#背景音乐
pygame.mixer.music.load(r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\game_music.ogg") #设置背景音乐
pygame.mixer.music.set_volume(1) #设置音量
#游戏音效
bullet_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\bullet.wav" #子弹特效
button_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\button.wav" #按键特效
enemy1_down_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy1_down.wav" #低等敌机被击毁音效
enemy2_down_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy2_down.wav" #中等敌机被击毁音效
enemy3_down_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy3_down.wav" #高等敌机被击毁音效
enemy3_fly_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy3_flying.wav" #高等敌机出现音效
get_bomb_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\get_bomb.wav" #获得全屏炸弹补给音效
get_bullet_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\get_bullet.wav" #获得双倍子弹补给音效
me_down_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\me_down.wav" #自身飞机被击毁(死亡)音效
supply_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\supply.wav" #补给产生音效
upgrade_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\upgrade.wav" #升级音效
use_bomb_music = r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\use_bomb.wav" #使用全屏炸弹音效
"""图片文件路径"""
again_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\again.png" #重新开始图片路径
background_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\background.png" #背景图的路径
bomb_supply_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bomb_supply.png" #全屏炸弹补给图
bomb_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bomb.png" #全屏炸弹图
bullet_supply_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bullet_supply.png" #补给子弹图
bullet1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bullet1.png" #第一种子弹图
bullet2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bullet2.png" #第二种子弹图
enemy1_down1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down1.png" #低级敌机撞到爆炸第一张图片
enemy1_down2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down2.png" #低级敌机撞到爆炸第二张图片
enemy1_down3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down3.png" #低级敌机撞到爆炸第三张图片
enemy1_down4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down4.png" #低级敌机撞到爆炸第四张图片
enemy1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1.png" #低级敌机图片
enemy2_down1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down1.png" #中级敌机撞到爆炸第一张图片
enemy2_down2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down2.png" #中级敌机撞到爆炸第二张图片
enemy2_down3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down3.png" #中级敌机撞到爆炸第三张图片
enemy2_down4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down4.png" #中级敌机撞到爆炸第四张图片
enemy2_hit_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_hit.png" #中级敌机碰撞图片
enemy2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2.png" #中级敌机图片
enemy3_down1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down1.png" #高级敌机撞到爆炸第四张图片
enemy3_down2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down2.png" #高级敌机撞到爆炸第四张图片
enemy3_down3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down3.png" #高级敌机撞到爆炸第四张图片
enemy3_down4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down4.png" #高级敌机撞到爆炸第四张图片
enemy3_down5_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down5.png" #高级敌机撞到爆炸第四张图片
enemy3_down6_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down6.png" #高级敌机撞到爆炸第四张图片
enemy3_hit_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_hit.png" #高级敌机碰撞图片
enemy3_n1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_n1.png" #高级敌机图片1
enemy3_n2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_n2.png" #高级敌机图片2
gameover_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\gameover.png" #游戏结束图片
life_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\life.png" #表示生命值的图片
me_destory_1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_1.png" #自身飞机炸毁第一张图片
me_destory_2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_2.png" #自身飞机炸毁第二张图片
me_destory_3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_3.png" #自身飞机炸毁第三张图片
me_destory_4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_4.png" #自身飞机炸毁第四张图片
me1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me1.png" #自身飞机第一张图片
me2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me2.png" #自身飞机第二张图片
pause_nor_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\pause_nor.png" #暂停的时候图片
pause_pressed_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\pause_pressed.png" #暂停到继续的中间变换图
resume_nor_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\resume_nor.png" #继续的时候的图片
resume_pressed_image =r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\resume_pressed.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.play(-1) #播放背景音乐,-1 表示无限循环播放
#生成飞机类
myself = MyPlane(bg_size,me1_image,me2_image)
while True :
for event in pygame.event.get() :
if event.type == QUIT :
sys.exit()
screen.blit(background,(0,0)) #绘制背景
#绘制飞机
screen.blit(myself.image2,myself.rect) #绘制第一张飞机图
#检查是否有上下左右或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() #飞船向右飞行
pygame.display.flip() #不停的刷新画面,不停的绘画
clock.tick(60) #设置帧率
if __name__ == "__main__":
# 这样做的好处是双击打开时如果出现异常可以报告异常,而不是一闪而过!
try:
main()
except SystemExit: #这是按下 × 的异常,直接忽略
pass
except:
traceback.print_exc()
pygame.quit()
input()
我们的飞机就生成了,也可以根据键盘上的 AWSD 或者方向键进行移动控制。
我们刚才说过,为了增加我方飞机的动态效果,我们可以通过两张图片(me1,png 和 me2.png)的切换来实现飞机冒烟的效果。
我们就只需要:
1、在 myplane.py中加多一种图片
from pygame.locals import *
from random import *
import pygame
import sys
"""\/\/\/\/\/\/\/\/------我的飞机类------\/\/\/\/\/\/\/\/"""
me1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me1.png" #自身飞机第一张图片
me2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me2.png" #自身飞机第二张图片
class MyPlane (pygame.sprite.Sprite): #定义我的飞机类,继承动画精灵类(因为之后要进行碰撞检测)
def __init__(self,bg_size,me1_image,me2_image) :
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.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.speed = 10 #设置飞机出现的速度
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 #锁定在底边界的位置,不再发生变化
2、在main.py中
首先计算一个布尔类型的变量用于控制切换图片;然后在绘制我方飞机这里交叉显示两张图片。
#绘制飞机
if transform : #如果改变属性为真 画第一张飞机图
screen.blit(myself.image1,myself.rect) #绘制第一张飞机图
transform = False #改变transform的属性来打到改变图片的效果
else : #如果改变属性为假 画第二张飞机图
screen.blit(myself.image2,myself.rect) #绘制第一张飞机图
transform = True
但是我们这样改,飞机还是没有理想中 “突突突” 的感觉,毕竟我们的帧率为60(每秒切换60次),我们最好在不影响游戏性能的情况来延迟图片的切换,这里我们就使用单片机开发中常常用到的一招,增加一个延时变量:
#绘制飞机
if transform : #如果改变属性为真 画第一张飞机图
if delay == 0:
delay = 100
delay -= 1
transform = False #改变transform的属性来打到改变图片的效果
else : #如果改变属性为假 画第二张飞机图
if delay == 0:
delay = 100
delay -= 1
transform = True
if delay % 5 :
screen.blit(myself.image2,myself.rect) #绘制第二张飞机图
elif not delay % 5 :
screen.blit(myself.image1,myself.rect) #绘制第一张飞机图
接下来就来创造敌机啦:
敌机分为小中大三个尺寸,它们的速度一次就是快中慢(越小越快),在页面上方,我们就需要随机创建一些敌机,可以通过在页面外部上方5个屏幕高度范围内随机生成一个敌机以保证不让敌机在一排出现。
from pygame.locals import *
from random import *
import pygame
import sys
enemy1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1.png" #低级敌机图片
enemy2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2.png" #中级敌机图片
enemy3_n1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_n1.png" #高级敌机图片1
enemy3_n2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_n2.png" #高级敌机图片2
"""\/\/\/\/\/\/\/\/------敌机类------\/\/\/\/\/\/\/\/"""
"""本来这里其实可以使用类的继承,然后三种敌机分别继承这个敌机类生成新的敌机,但是在这里、
没有这样做的必要,因为三个类的差别并不是很大,所以不用那么繁杂"""
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.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.speed = 3 #设置小敌机移动的速度
def move(self) : #小敌机的移动函数
if self.rect.top < self.height : #如果小飞机的底超出窗口的下边框
self.rect.top += self.speed #小飞机向下移动他的速度
else : #如果小飞机已经超出窗口的下边界框
self.reset() #重置小飞机
def reset(self) : #重置小飞机函数
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
class MiddleEnemy(pygame.sprite.Sprite): #定义我的敌机类,继承自动画精灵
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.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(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
self.speed = 2 #设置中敌机移动的速度
def move(self) : #小敌机的移动函数
if self.rect.top < self.height : #如果小飞机的底超出窗口的下边框
self.rect.top += self.speed #小飞机向下移动他的速度
else : #如果小飞机已经超出窗口的下边界框
self.reset() #重置小飞机
def reset(self) : #重置小飞机函数
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
class BigEnemy(pygame.sprite.Sprite): #定义我的敌机类,继承自动画精灵
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.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(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
self.speed = 1 #设置大敌机移动的速度
def move(self) : #大敌机的移动函数
if self.rect.top < self.height : #如果大飞机的底超出窗口的下边框
self.rect.top += self.speed #大飞机向下移动他的速度
else : #如果大飞机已经超出窗口的下边界框
self.reset() #重置大飞机
def reset(self) : #重置大飞机函数
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
敌机的定义有了,我们接下来就在main 模块中将它们实例化:
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.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.speed = 10 #设置飞机出现的速度
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 #锁定在底边界的位置,不再发生变化
"""\/\/\/\/\/\/\/\/------敌机类------\/\/\/\/\/\/\/\/"""
"""本来这里其实可以使用类的继承,然后三种敌机分别继承这个敌机类生成新的敌机,但是在这里、
没有这样做的必要,因为三个类的差别并不是很大,所以不用那么繁杂"""
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.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.speed = 3 #设置小敌机移动的速度
def move(self) : #小敌机的移动函数
if self.rect.top < self.height : #如果小飞机的底超出窗口的下边框
self.rect.top += self.speed #小飞机向下移动他的速度
else : #如果小飞机已经超出窗口的下边界框
self.reset() #重置小飞机
def reset(self) : #重置小飞机函数
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
class MiddleEnemy(pygame.sprite.Sprite): #定义我的敌机类,继承自动画精灵
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.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(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
self.speed = 2 #设置中敌机移动的速度
def move(self) : #小敌机的移动函数
if self.rect.top < self.height : #如果小飞机的底超出窗口的下边框
self.rect.top += self.speed #小飞机向下移动他的速度
else : #如果小飞机已经超出窗口的下边界框
self.reset() #重置小飞机
def reset(self) : #重置小飞机函数
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
class BigEnemy(pygame.sprite.Sprite): #定义我的敌机类,继承自动画精灵
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.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(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
self.speed = 1 #设置大敌机移动的速度
def move(self) : #大敌机的移动函数
if self.rect.top < self.height : #如果大飞机的底超出窗口的下边框
self.rect.top += self.speed #大飞机向下移动他的速度
else : #如果大飞机已经超出窗口的下边界框
self.reset() #重置大飞机
def reset(self) : #重置大飞机函数
self.rect.left , self.rect.top = [ randint(0 , self.width - self.rect.width ) ,\
randint(-5*self.height , 0) ] #在窗口的5倍之上的距离中产生飞机
def main() :
pygame.init() #初始化
pygame.mixer.init() #混音器初始化
clock = pygame.time.Clock() #设置一个计时器
transform = False #设置一个是否改变的变量
delay = 100 #类似于单片机,设置一个延时变量,让飞机的改变看起来更加的顺滑
switch_image = True # 用于切换图片
"""载入音乐文件"""
#背景音乐
pygame.mixer.music.load(r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\game_music.ogg") #设置背景音乐
pygame.mixer.music.set_volume(1) #设置音量
#游戏音效
bullet_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\bullet.wav") #子弹特效
bullet_sound.set_volume(0.2)
button_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\button.wav") #按键特效
button_sound.set_volume(0.3)
enemy1_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy1_down.wav") #低等敌机被击毁音效
enemy1_down_sound.set_volume(0.3)
enemy2_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy2_down.wav") #中等敌机被击毁音效
enemy2_down_sound.set_volume(0.3)
enemy3_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy3_down.wav") #高等敌机被击毁音效
enemy3_down_sound.set_volume(0.3)
enemy3_fly_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\enemy3_flying.wav") #高等敌机出现音效
enemy3_fly_sound.set_volume(0.3)
get_bomb_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\get_bomb.wav") #获得全屏炸弹补给音效
get_bomb_sound.set_volume(0.4)
get_bullet_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\get_bullet.wav") #获得双倍子弹补给音效
get_bullet_sound.set_volume(0.4)
me_down_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\me_down.wav") #自身飞机被击毁(死亡)音效
me_down_sound.set_volume(0.3)
supply_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\supply.wav") #补给产生音效
supply_sound.set_volume(0.4)
upgrade_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\upgrade.wav") #升级音效
upgrade_sound.set_volume(0.3)
use_bomb_sound = pygame.mixer.Sound( r"D:\Code\Python\Pygame\pygame11:飞机大战1\sound\use_bomb.wav") #使用全屏炸弹音效
use_bomb_sound.set_volume(0.4)
"""图片文件路径"""
again_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\again.png" #重新开始图片路径
background_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\background.png" #背景图的路径
bomb_supply_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bomb_supply.png" #全屏炸弹补给图
bomb_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bomb.png" #全屏炸弹图
bullet_supply_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bullet_supply.png" #补给子弹图
bullet1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bullet1.png" #第一种子弹图
bullet2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\bullet2.png" #第二种子弹图
enemy1_down1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down1.png" #低级敌机撞到爆炸第一张图片
enemy1_down2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down2.png" #低级敌机撞到爆炸第二张图片
enemy1_down3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down3.png" #低级敌机撞到爆炸第三张图片
enemy1_down4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1_down4.png" #低级敌机撞到爆炸第四张图片
enemy1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy1.png" #低级敌机图片
enemy2_down1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down1.png" #中级敌机撞到爆炸第一张图片
enemy2_down2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down2.png" #中级敌机撞到爆炸第二张图片
enemy2_down3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down3.png" #中级敌机撞到爆炸第三张图片
enemy2_down4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_down4.png" #中级敌机撞到爆炸第四张图片
enemy2_hit_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2_hit.png" #中级敌机被子弹打到后图片
enemy2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy2.png" #中级敌机图片
enemy3_down1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down1.png" #高级敌机撞到爆炸第四张图片
enemy3_down2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down2.png" #高级敌机撞到爆炸第四张图片
enemy3_down3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down3.png" #高级敌机撞到爆炸第四张图片
enemy3_down4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down4.png" #高级敌机撞到爆炸第四张图片
enemy3_down5_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down5.png" #高级敌机撞到爆炸第四张图片
enemy3_down6_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_down6.png" #高级敌机撞到爆炸第四张图片
enemy3_hit_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_hit.png" #高级敌机被子弹打到后图片
enemy3_n1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_n1.png" #高级敌机图片1
enemy3_n2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\enemy3_n2.png" #高级敌机图片2
gameover_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\gameover.png" #游戏结束图片
life_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\life.png" #表示生命值的图片
me_destory_1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_1.png" #自身飞机炸毁第一张图片
me_destory_2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_2.png" #自身飞机炸毁第二张图片
me_destory_3_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_3.png" #自身飞机炸毁第三张图片
me_destory_4_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me_destroy_4.png" #自身飞机炸毁第四张图片
me1_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me1.png" #自身飞机第一张图片
me2_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\me2.png" #自身飞机第二张图片
pause_nor_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\pause_nor.png" #暂停的时候图片
pause_pressed_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\pause_pressed.png" #暂停到继续的中间变换图
resume_nor_image = r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\resume_nor.png" #继续的时候的图片
resume_pressed_image =r"D:\Code\Python\Pygame\pygame11:飞机大战1\images\resume_pressed.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 表示无限循环播放
#生成自己飞机
myself = MyPlane(bg_size,me1_image,me2_image)
#生成敌机组
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)
#生成敌机组
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) #生成大型飞机
while True :
for event in pygame.event.get() :
if event.type == QUIT :
sys.exit()
screen.blit(background,(0,0)) #绘制背景
# 绘制大型敌机
for each in bigenemies:
each.move()
if switch_image:
switch_image = False
screen.blit(each.enemy3_n1, each.rect)
else:
switch_image = True
screen.blit(each.enemy3_n2, each.rect)
# 即将出现在画面中,播放音效
if each.rect.bottom > -50:
enemy3_fly_sound.play()
# 绘制中型敌机:
for each in middleenemies:
each.move()
screen.blit(each.enemy2, each.rect)
# 绘制小型敌机:
for each in smallenemies:
each.move()
screen.blit(each.enemy1, each.rect)
#绘制飞机
if transform : #如果改变属性为真 画第一张飞机图
if delay == 0:
delay = 100
delay -= 1
transform = False #改变transform的属性来打到改变图片的效果
else : #如果改变属性为假 画第二张飞机图
if delay == 0:
delay = 100
delay -= 1
transform = True
if delay % 5 :
screen.blit(myself.image2,myself.rect) #绘制第二张飞机图
elif not delay % 5 :
screen.blit(myself.image1,myself.rect) #绘制第一张飞机图
#检查是否有上下左右或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() #飞船向右飞行
pygame.display.flip() #不停的刷新画面,不停的绘画
clock.tick(60) #设置帧率
if __name__ == "__main__":
# 这样做的好处是双击打开时如果出现异常可以报告异常,而不是一闪而过!
try:
main()
except SystemExit: #这是按下 × 的异常,直接忽略
pass
except:
traceback.print_exc()
pygame.quit()
input()
我们可以看到敌机依次出来,由于我们现在还没有做碰撞检测,所以它们可以友好的交叉飞过,我们在下节课中会教大家如何做完美的碰撞检测,因为飞机是不规则的图形,所有我们没办法像之前讲小球一样弄一个半径。但是别担心,这种不规则的图形也可以做完美的碰撞检测,大家拭目以待吧。