pygame实例——飞机大战

main.py

'''
游戏框架:
1.导入python程序运行所需的环境模块sys,pygame模块,以及pygame.locals模块提供常用的常量和函数。
2.定义窗口大小,并创建窗口,设置游戏标题,以及加载背景。
3.定义主函数main(),设置程序退出机制,绘制背景图像,flip()方法刷新所有待显示的图像(更新整个窗口),设置程序运行的帧率。
'''

# 首先导入三个pygame的基本模块,以及其他附加模块
import sys	# sys模块提供了一系列python程序运行环境的变量和函数(方法),比如退出程序的函数:sys.exit()
import pygame	# pygame模块提供了游戏设计中用到的加载图片、声音等函数(方法)
from pygame.locals import *	 #pygame.locals模块包含了一些程序常用的常量,使用from modulename import *的方式导入模块,使得后期使用模块中的函数或变量时更加方便,直接使用变量的名字就可以,不用modulename(模块名).variable(变量)这样复杂的格式。比如QUIT常量直接使用,而不是pygame.locals.QUIT。
import myplane  #导入我方飞机模块
import enemy   #导入敌方飞机模块
import bullet 	#导入子弹模块

# 然后初始化pygame及其一些模块(音频,字体)。
pygame.init()		     #初始化pygame,只有初始化pygame了我们才能使用
pygame.mixer.init()		#初始化pygame中的音频模块
pygame.font.init()		   #初始化pygame中的字体

# 设置游戏窗口(宽度、长度,标题名字),加载所有的声音文件(音乐、音效)并设置音量
screen_size = width, height = 480, 700	 #定义表示窗口大小的变量screen_size
screen = pygame.display.set_mode(screen_size)	  #将元组变量screen_size传给set_mode()函数,来设定窗口的宽和高。调用该函数将返回一个”pygame.surface对象”,并起名字为screen
pygame.display.set_caption("飞机大战")	#定义一个标题名字,将显示在游戏窗口的左上角。
background=pygame.image.load("images/background.png").convert() # 用pygame的image模块导入一张背景图片备用,# 利用surface对象的convert_alpha()方法或convert()方法,加载图片并转换图片的像素格式,使得程序效率更高,小飞机移动的会快一点

#加载背景音乐
pygame.mixer.music.load("sound/game_music.ogg")  #加载背景音乐文件
pygame.mixer.music.set_volume(0.1)  #设置音量,括号中传入的参数为从0到1的小数,0.5表示最大音量的50%
#加载大型飞机飞行声音
enemy3_fly_sound=pygame.mixer.Sound("sound/enemy3_flying.wav")
enemy3_fly_sound.set_volume(0.2)
#加载敌机坠毁的声音
small_down_sound=pygame.mixer.Sound("sound/enemy1_down.wav")
small_down_sound.set_volume(0.3)
mid_down_sound=pygame.mixer.Sound("sound/enemy2_down.wav")
mid_down_sound.set_volume(0.3)
big_down_sound=pygame.mixer.Sound("sound/enemy3_down.wav")
big_down_sound.set_volume(0.6)
#加载我方飞机撞毁的声音
me_down_sound=pygame.mixer.Sound("sound/me_down.wav")
me_down_sound.set_volume(0.2)

#定义将敌方小飞机添加到组的函数(这一步和下面两步就是写一个方法方便下面飞机添加到组里)

def add_small_enemies(group1, group2, num):#定义方法,名字(参数)
for small_enemy_num in range(num):#定义变量遍历给定范围
        each_small_enemy = enemy.SmallEnemy(screen_size) #定义生成小飞机
        group1.add(each_small_enemy)#将生成的小飞机添加到一个组
        group2.add(each_small_enemy)#将生成的小飞机添加到另一个组

#定义将敌方中型飞机添加到组的函数
def add_mid_enemies(group1, group2, num):
    for mid_enemy_num in range(num):
        each_mid_enemy = enemy.MidEnemy(screen_size)
        group1.add(each_mid_enemy)
        group2.add(each_mid_enemy)

#定义将敌方大型飞机添加到组的函数
def add_big_enemies(group1, group2, num):
    for big_enemy_num in range(num):
        each_big_enemy = enemy.BigEnemy(screen_size)
        group1.add(each_big_enemy)
        group2.add(each_big_enemy)

# 函数主要部分开始,将主要功能包含在main主函数中!
#定义一个main()函数用来管理主程序
def main():
    pygame.mixer.music.play(-1)    # 一直循环播放背景音乐,我们可以在调用play()方法时,在括号内传入一个特殊值 -1,这样音乐就会永远重复下去;如果传入其他数值,可以让音乐播放一定的次数,比如 3,可以让音乐重复播放3次。
clock = pygame.time.Clock()	# pygame中的时间模块,用来延迟时间(python中也有时间模块,主要用来延迟事件的发生或结束)
# 下面是生成部分,生成(从其他子模块中调用)我方飞机、敌机、子弹…
    #生成我方飞机
    heroPlane = myplane.myPlane(screen_size)
    #创建敌方飞机组(动画精灵组)
    enemies = pygame.sprite.Group()#创建一个组用来添加所有敌机
    #生成小敌方飞机(创建小型敌机组,并执行之前添加到组的方法)
    small_enemies = pygame.sprite.Group()  #创建敌方小飞机组(动画精灵组)添加敌方小飞机
    add_small_enemies(small_enemies, enemies, 15)   #将生成的多个敌方小飞机添加到敌方小飞机组以及敌方飞机组
    #生成中型敌方飞机
    mid_enemies = pygame.sprite.Group()  #创建敌方小飞机组(动画精灵组)
    add_mid_enemies(mid_enemies, enemies, 4)   #将生成的多个中型飞机添加到敌方中型飞机组以及敌方飞机组
    #生成大型敌方飞机
    big_enemies = pygame.sprite.Group()  #创建敌方大型飞机组(动画精灵组)
add_big_enemies(big_enemies, enemies, 2)   #将生成的多个大型飞机添加到敌方大型飞机组以及敌方飞机组

    #生成普通子弹
    bullet1 = []		#创建一个空列表
    bullet1_index = 0		#子弹列表索引值变量,初始位为0
    BULLET1_NUM = 4    #子弹数量为4时,按照循环10次发射一发,差不多占满窗口的高度
     #生成4发子弹并放入bullet1列表
    for i in range(BULLET1_NUM):		# 循环遍历子弹数量
       bullet1.append(bullet.Bullet1(heroPlane.rect.midtop)) #将子弹放入刚才创建的空列表中,((…))中为添加子弹的位置(我方飞机中上) 
# 下面是定义一些索引,方便下面切换飞机形态、判断条件、…使用
	switch_image = True#用于切换飞机特效(给一个变量,满足不同条件时切换不同的飞机形象达到切换飞机图片的效果)
    #碰撞后,敌机坠毁及我方飞机撞毁动画图片索引标志定义(同上)
    small_destroy_index = 0#小型飞机坠毁的索引
    mid_destroy_index = 0#中型飞机坠毁的索引
    big_destroy_index = 0#大型飞机坠毁的索引
hero_destroy_index = 0#我方飞机坠毁的索引
# 下面是游戏开始前的准备工作,加载、设置飞机生命值、得分、字体、游戏结束等需要的(图片、坐标、初始值、固定值…)
    #我方飞机生命数量
life_image=pygame.image.load("images/life.png").convert_alpha()#加载生命数量图片
    life_rect = life_image.get_rect()#加获取生命数量图片的坐标
    life_NUM = 3#定义生命数量初始为3
    #用于切换特效的延迟(就是规定一定时间范围来切换图片)
    delay = 100
    #统计得分
    score = 0  # 开始分数设为0
    score_font = pygame.font.Font("font/font.ttf", 36)   #创建一个Font对象,分数字体
    WhiteFont = (255, 255, 255)	  #字体颜色

    #绘制游戏结束界面
    gameover_font = pygame.font.Font("font/font.ttf", 48)   #显示最终得分
again_image=pygame.image.load("images/again.png").convert_alpha()  #加载重新开始按钮图像
    again_rect = again_image.get_rect()
    gameover_image = pygame.image.load("images/gameover.png").convert_alpha()   #加载游戏结束按钮图像
    gameover_rect = gameover_image.get_rect()
# 刚才游戏开始前的各种准备工作做完啦,接下来,进入游戏主循环,我们利用无限循环实现,除非玩家把窗口关闭,中断游戏,方可退出
    while True:			
        for event in pygame.event.get():	 #通过for循环遍历获取到的游戏事件。
            if event.type == QUIT:#如果获取到的游戏事件是退出,则将pygame退出,将python程序环境退出,关闭游戏软件。
                pygame.quit()  # 退出pygame
                sys.exit()  # 退出环境
            #当ESC按键被按下时,游戏暂停
            if event.type == KEYDOWN:    #事件类型为按键的按下
                if event.key == K_ESCAPE :
                    pause_flag = not(pause_flag)

        screen.blit(background,(0,0)) #设置前面加载的背景图片
# 下面是我方飞机和敌机的条件判断和操作方法
        #当我方飞机还有生命数量,则正常运行,如果没有生命数量了,则游戏停止
        if life_NUM > 0: #如果我方飞机生命值大于0。这是整个游戏的第一个判断!
            #检测用户的键盘操作,并让我方飞机向上、向下、向左、向右移动
            key_pressed = pygame.key.get_pressed()
            if key_pressed[ K_w ] or key_pressed[ K_UP ]:   #按下w键或下箭头
                heroPlane.moveUp()  # 飞机向上移动
            if key_pressed[ K_s ] or key_pressed[ K_DOWN ]: #按下s键或上箭头
                heroPlane.moveDown()  # 飞机往下移动
            if key_pressed[ K_a ] or key_pressed[ K_LEFT ]: #按下a键或左箭头
                heroPlane.moveLeft()  # 飞机往左移动
            if key_pressed[ K_d ] or key_pressed[ K_RIGHT ]: #按下d键或右箭头
                heroPlane.moveRight()	# 飞机往右移动

            #绘制小型敌机,添加敌机坠毁动画
            for each in small_enemies:  #生成变量each遍历刚才生成的小敌机组
                if each.active == True:  #each.active是飞机的存活标志,True代表存活
                    each.move()  #调用enemy.SmallEnemy模块中的小型敌机移动方法
                    screen.blit(each.image, each.rect)   #将小敌机绘制到屏幕上
                else:  #如果小型敌机没有存活
                    #动画图片的切换稍作延时,主循环三次切换一幅图
                    if not True:  #判断语句,这一行多余,可以省略
                        #播放坠毁声音
                        if small_destroy_index == 0:  #小敌机坠毁的索引,前面设置过
                            small_down_sound.play()  #播放声音
                        #切换坠毁动画图像
screen.blit(each.destroy_images[small_destroy_index], each.rect)  #绘制动画图像
                            small_destroy_index=(small_destroy_index + 1) % 4 #动画图像切换索引递变,因为小敌机坠毁图片有四张,所以要判断四次,然后再生成新的敌机
                        #重新生成敌机
                        if small_destroy_index == 0:
                            score += 100    #击中一架小型敌机得分加100
                            each.reset()    # 调用方法重新生成敌机
            #绘制中型敌机(和小敌机方法一样,不再重复注释了)
            for each in mid_enemies:
                if each.active == True:
                    each.move()
                    screen.blit(each.image, each.rect)
                else:
                    #动画图片的切换稍作延时,主循环三次切换一幅图
                    if not(delay % 3):
                        if mid_destroy_index == 0:
                            mid_down_sound.play()
screen.blit(each.destroy_images[mid_destroy_index], each.rect)  #绘制动画图像
                        										 mid_destroy_index=(mid_des
troy_index + 1) % 4   #动画图像切换索引递变
                        if mid_destroy_index == 0:
                            score += 300    #击中一架中型敌机得分加300
                            each.reset()
            #绘制大型飞机(详见绘制小型敌机)
            for each in big_enemies:
                if each.active == True:
                    each.move()
                    if switch_image:
                       screen.blit(each.image, each.rect)
                    else:
                       screen.blit(each.image2,each.rect)
                    #在大型敌机出现在窗口之前,开始有飞行声音
                    if each.rect.bottom == -50:
                        enemy3_fly_sound.play()
                else:
                    #动画图片的切换稍作延时,主循环三次切换一幅图
                    if not(delay % 3):
                        if big_destroy_index == 0:
                            big_down_sound.play()
screen.blit(each.destroy_images[b
ig_destroy_index], each.rect)
                        #绘制动画图像
big_destroy_index=(big_destroy_i
ndex + 1) % 6 #大型敌机的动画是6张图
                        if big_destroy_index == 0:
                            enemy3_fly_sound.stop()   #当坠毁时,飞行的声音停止
                            score += 500    #击中一架大型敌机得分加500
                            each.reset()
# 下面该绘制我方飞机了,我方飞机是碰到敌机会坠毁(播放声音然后切换图片)
                #绘制我方飞机
                if heroPlane.active == True:  # 如果我方飞机存活
                    if switch_image:  #每循环5次切换一次特效图像
                       screen.blit(heroPlane.image,heroPLan.rect)
                    else:
                       screen.blit(heroPlane.image2,heroPlane.rect)
                else:
                    #动画图片的切换稍作延时,主循环三次切换一幅图(这一步小飞机有)
                    if not True:
                        if hero_destroy_index == 0:
                            me_down_sound.play()
                       screen.blit(each.destroy_images[hero_destroy_index], each.rect)  #绘制动画图像
                        hero_destroy_index=(hero_destroy_index + 1) % 4   #动画图像切换索引递变
                        if hero_destroy_index == 0:
                            life_NUM -= 1   #撞毁后,我方飞机生命减1
                            heroPlane.reset()
                #每循环5次切换一次特效图像
                if not(delay % 5):
                    switch_image = not switch_image  # switch变量前面设置过
                delay -= 1
                if delay == 0:
                    delay = 100

                #显示我方飞机生命数量
                if life_NUM > 0:
                    for i in range(life_NUM):  #遍历生命值
                        screen.blit(life_image,(width - 10 - (i+1)*life_rect.width,\height - 10 - life_rect.height))  #将生命值绘制在屏幕中
                #发射子弹,每循环10次,发射一枚子弹
                if not(delay % 10): #非0即为真
bullet1[bullet1_index].reset(heroPlane.rect.midtop) #重新发射子弹
                    bullet1_index = (bullet1_index + 1) % BULLET1_NUM#将原本子弹索引值+1除以子弹数量取余
                #检测子弹击中敌机
                for each in bullet1:  #生成each变量遍历子弹
                    #如果子弹状态标记为True,则子弹移动
                    if each.active == True:
                        each.move()   #子弹移动
                        screen.blit(each.image,each.rect)   #绘制子弹
                        enemies_hit=pygame.sprite.sprite
collide(each,enemies,False,pygame.sprite.collide_mask) #检测子弹与敌机碰撞(动画精灵)
                        #如果有敌机被击中,则子弹状态标记改为False,被击中的敌机的状态标记也改为False
                        if enemies_hit:
                            for e in enemies_hit:
                                #如果被击中的敌机是中型或大型敌机,则每击中一次血量减1,当血量变为0时,敌机状态标记改为False
                                if e in mid_enemies or e in big_enemies:
                                    e.energy -= 1
                                    if e.energy == 0:
                                        e.active = False
                                #如果是小型敌机,一发子弹搞定
                                else:
                                    e.active = False
                    #如果子弹状态标记为False,则重新生成子弹(原来子弹消失)
                    else:
                       each.reset(heroPlane.rect.midtop)

                #添加碰撞检测,检测我方飞机与所有敌机发生碰撞
                #将发生碰撞的敌机(动画精灵)保存到enemies_collided列表, return得到的是所有在group里有参加碰撞的东西的列表,在这里,及为所有与player碰撞的alien的列表 这是官方的解释	           
enemies_collided=pygame.sprite.spritecollide(heroPlane,enemies,False,pygame.sprite.collide_mask)
                #将发生碰撞的敌机复位(消失并重新绘制)
                if enemies_collided:  #如果enemies_collided列表有值
                    heroPlane.active = False #将我方飞机存活状态改为False
                    for each in enemies_collided:
                        each.active = False  #碰撞后,将敌机状态设置为False

            #显示得分
            score_surface =score_font.render("Score : %s" % str(score), True, WhiteFont)
            screen.blit(score_surface, (10,5))  #在左上角(10,5)的位置显示
        #游戏结束
        elif life_NUM == 0:  #我方飞机生命值为0时,停止所有动作,跳转结束界面
            #背景音乐停止
            pygame.mixer.music.stop()
            #停止全部音效
            pygame.mixer.stop()
            #显示最终得分
             #这四行代码是创建字体”Your Score”,获取坐标,设置起始位置,并添加到屏幕中
            gameover_TXT1 = gameover_font.render("Your Score", True, WhiteFont)
            gameoverTXT1_rect = gameover_TXT1.get_rect()
gameoverTXT1_rect.left,gameoverTXT1_rect.top=(width-gameoverTXT1_rect.width)//2, height//3
            screen.blit(gameover_TXT1, gameoverTXT1_rect)
            #这四行代码是创建字体(分数),获取坐标,设置起始位置,并添加到屏幕中
            gameover_TXT2 = gameover_font.render(str(score), True, WhiteFont)
            gameoverTXT2_rect = gameover_TXT2.get_rect()
            gameoverTXT2_rect.left, gameoverTXT2_rect.top = (width - gameoverTXT2_rect.width)//2, gameoverTXT1_rect.bottom + 10
            screen.blit(gameover_TXT2, gameoverTXT2_rect)

            #绘制重新开始和游戏结束的按钮
again_rect.left,again_rect.top=(width-again_rect.width)//2,gameoverTXT2_rect.bottom + 30
            screen.blit(again_image, again_rect)
            gameover_rect.left, gameover_rect.top = (width - gameover_rect.width)//2, again_rect.bottom + 30
            screen.blit(gameover_image, gameover_rect)

            #获取鼠标操作
            mouse_down = pygame.mouse.get_pressed()
            #如果玩家按下鼠标左键
            if mouse_down[0]:
                pos = pygame.mouse.get_pos()  #获取鼠标光标的位置(x,y)
                if again_rect.left < pos[0] 

myplan.py

'''
定义我方飞机的对象,并在对象中定义飞机图像的矩形、位置、速度等特性值,以及定义我方飞机移动的方法,重新生成的方法
'''
# 导入pygame模块
import pygame
# 创建动画精灵的子类,命名为myPlane 
class myPlane(pygame.sprite.Sprite):		
    def __init__(self,screen_size):
        pygame.sprite.Sprite.__init__(self)   #动画精灵初始化
        self.image = pygame.image.load("images/me1.png").convert_alpha()   #加载我方飞机的图像
        self.image2 = pygame.image.load("images/me2.png").convert_alpha()  #加载喷气特效图像
        self.destroy_images = []  #创建一个空列表用来放置我方飞机坠毁图片
# 这一步就是加载四张我方飞机坠毁图到刚才创建的空列表里
        self.destroy_images.extend([\
            pygame.image.load("images/me_destroy_1.png").convert_alpha(),\
            pygame.image.load("images/me_destroy_2.png").convert_alpha(),\
            pygame.image.load("images/me_destroy_3.png").convert_alpha(),\
            pygame.image.load("images/me_destroy_4.png").convert_alpha()])
        self.rect = self.image.get_rect()  #获取我方飞机的rect对象
        self.width,self.height = screen_size[0], screen_size[1]    #定义窗口大小的内部参数
        #设置我方飞机最初的位置
        self.rect.left, self.rect.bottom = (self.width- self.rect.left)//2, self.height - 60

        self.speed = 10   # 设置我方飞机的速度
        self.active = True  # 设置我方飞机初始为存活状态
        self.mask = pygame.mask.from_surface(self.image)   #将图像非透明部分保存为mask,实现完美碰撞(参考碰撞检测ppt)
    #定义我方飞机移动的方法
    def moveUp(self):  # 定义向上移动的方法
        if self.rect.top > 0:  # 如果上边界>0
            self.rect.top -= self.speed  # 将飞机的顶部坐标大小减去速度大小
        else:		# 如果上边界<=0
            self.rect.top = 0  	# 将飞机的顶部坐标设为0
  
    def moveDown(self):		# 定义向下移动的方法
        if self.rect.bottom < self.height - 60:  # 如果飞机下边界<屏幕长度减去飞机自身的长度
            self.rect.bottom += self.speed  # 将飞机的底部坐标大小减去速度坐标大小
        else:  # 如果飞机下边界>=屏幕长度减去飞机自身的长度
            self.rect.bottom = self.height – 60  # 将飞机的底部坐标设为屏幕长度-飞机长度

    def moveLeft(self):  # 定义向左移动的方法
        if self.rect.left > 0:  # 如果飞机左边界>0
            self.rect.left -= self.speed  # 将飞机的左边坐标大小减去速度
        else:  # 如果飞机左边界<0
            self.rect.left = 0  # 将飞机的左边坐标大小设为0

    def moveRight(self): # 定义向右移动的方法
        if self.rect.right < self.width:  # 如果飞机右边界坐标<屏幕宽度
            self.rect.right += self.speed  # 将飞机的右边坐标大小加上速度
        else:  # 如果飞机右边界坐标>屏幕宽度
            self.rect.right = self.width  # 将飞机的右边坐标大小设为屏幕宽度
    def reset(self): # 定义重新生成飞机的方法
        self.active = True  # 将飞机的存活状态重新设为True
        self.rect.left, self.rect.bottom = (self.width- self.rect.left)//2, self.height – 60 # 定义飞机重新生成的位置

enemy.py

'''
定义敌方飞机的对象,并在对象中定义飞机图像的矩形、位置、速度等特性值,以及定义敌方飞机移动的方法、重新生成的方法
敌方飞机包含小型飞机、中型飞机、大型飞机
'''
import pygame  # 导入模块
from random import  *  # 导入随机模块

#定义小型敌机的对象
class SmallEnemy(pygame.sprite.Sprite):  # 定义小型敌机的类
    def __init__(self, screen_size):  # 类初始化方法,添加属性(screen_size)
        pygame.sprite.Sprite.__init__(self)  # 动画精灵初始化
        self.image = pygame.image.load("images/enemy1.png").convert_alpha() #加载小型敌机图片
        #加载小型敌机坠毁动画图片,并保存到列表中,动画即几幅图片的顺序切换
        self.destroy_images = [] #创建一个空列表用来放置我方飞机坠毁图片
# 这一步就是加载四张小型敌机坠毁图到刚才创建的空列表里
        self.destroy_images.extend([\
            pygame.image.load("images/enemy1_down1.png").convert_alpha(),\
            pygame.image.load("images/enemy1_down2.png").convert_alpha(),\
            pygame.image.load("images/enemy1_down3.png").convert_alpha(),\
            pygame.image.load("images/enemy1_down4.png").convert_alpha()])
        self.rect = self.image.get_rect() #获取我方飞机的rect对象
        self.width, self.height = screen_size[0], screen_size[1]  #定义窗口大小的内部参数
        self.speed = 8  #可以通过修改速度来提高游戏的难度
        self.active = True  #敌机的状态标记

        #小型敌机出现的位置是随机的  
                       self.rect.left,self.rect.top=randint(0,self.width-self.rect.width),\randint(-5*self.height,0)
        self.mask = pygame.mask.from_surface(self.image)   #将图像非透明部分保存为mask,实现完美碰撞

    #定义小型敌机移动的方法
    def move(self):
        if self.rect.top < self.height - 60:  # 如果上边界<屏幕高度-飞机大小
            self.rect.top +=  self.speed  # 飞机的上边界大小+速度大小
        else:
            self.reset()   #当某一个小型敌机飞出窗口后,重新生成
    #定义重新生成小型敌机的方法,重新生成敌机的位置是随机的
    def reset(self):  # 重新生成飞机的方法
        self.active = True   #敌机重生时,状态标记重置为True
# 设置飞机的初始位置
        self.rect.left, self.rect.top = randint(0, self.width - self.rect.width),\
                                        randint(-5*self.height,0)

#定义中型敌机(注释与小型敌机相仿,参见小型敌机)
class MidEnemy(pygame.sprite.Sprite):
    ENERGY = 10   #定义中型敌机的血量,使用类中的全局变量
    def __init__(self,screen_size):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load("images/enemy2.png").convert_alpha()
        #加载中型敌机坠毁动画图片,并保存到列表中
        self.destroy_images = []
        self.destroy_images.extend([\
            pygame.image.load("images/enemy2_down1.png").convert_alpha(),\
            pygame.image.load("images/enemy2_down2.png").convert_alpha(),\
            pygame.image.load("images/enemy2_down3.png").convert_alpha(),\
            pygame.image.load("images/enemy2_down4.png").convert_alpha()])
        self.rect = self.image.get_rect()
        self.width, self.height = screen_size[0], screen_size[1]
        self.speed = 1
        self.active = True   #定义敌机状态标记
        self.energy = MidEnemy.ENERGY
        self.rect.left, self.rect.top = randint(0, self.width - self.rect.width),\
                                        randint(-10*self.height, -self.height)
        self.mask = pygame.mask.from_surface(self.image)   #将图像非透明部分保存为mask,实现完美碰撞

    def move(self):
        if self.rect.top < self.height - 60:
            self.rect.top +=  self.speed
        else:
            self.reset()

    def reset(self):
        self.active = True #重置敌机状态标记
        self.energy = MidEnemy.ENERGY # 重置中型敌机血量
        self.rect.left, self.rect.top = randint(0, self.width - self.rect.width),\
                                        randint(-10*self.height,0)

#定义大型敌机
class BigEnemy(pygame.sprite.Sprite):
    ENERGY = 20   #定义大型敌机的血量,使用类中的全局变量
    def __init__(self,screen_size):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load("images/enemy3_n1.png").convert_alpha()
        self.image2 = pygame.image.load("images/enemy3_n2.png").convert_alpha()
        #加载小型敌机坠毁动画图片,并保存到列表中
        self.destroy_images = []
        self.destroy_images.extend([\
            pygame.image.load("images/enemy3_down1.png").convert_alpha(),\
            pygame.image.load("images/enemy3_down2.png").convert_alpha(),\
            pygame.image.load("images/enemy3_down3.png").convert_alpha(),\
            pygame.image.load("images/enemy3_down4.png").convert_alpha(),\
            pygame.image.load("images/enemy3_down5.png").convert_alpha(),\
            pygame.image.load("images/enemy3_down6.png").convert_alpha()])
        self.rect = self.image.get_rect()
        self.width, self.height  = screen_size[0], screen_size[1]
        self.speed = 1
        self.active = True  #定义敌机状态标记
        self.energy = BigEnemy.ENERGY
        self.rect.left, self.rect.top = randint(0, self.width - self.rect.width),\
                                        randint(-15*self.height, -5*self.height)
        self.mask = pygame.mask.from_surface(self.image)   #将图像非透明部分保存为mask,实现完美碰撞

    def move(self):
        if self.rect.top < self.height - 60:
            self.rect.top +=  self.speed
        else:
            self.reset()

    def reset(self):
        self.active = True  # 重置敌机状态标记
        self.energy = BigEnemy.ENERGY  # 重置大型敌机血量
        self.rect.left, self.rect.top = randint(0, self.width - self.rect.width),\
                                        randint(-15*self.height, -5*self.height)

bullet.py

'''
定义我方飞机发射子弹的对象
'''

import pygame	 # 导入pygame模块

class Bullet1(pygame.sprite.Sprite):  # 创建动画精灵的子类,命名为Bullet
    def __init__(self,position):
        pygame.sprite.Sprite.__init__(self)  # 动画精灵初始化
 # 加载子弹图片
        self.image = pygame.image.load("images/bullet1.png").convert_alpha()
  	    # 动画精灵初始化
        self.rect = self.image.get_rect()  # 获取子弹坐标
        self.rect.left, self.rect.top = position    #position应该为我方飞机中央机头位置
        self.speed = 12  # 设置子弹速度为12
        self.active = True  # 设置子弹存活状态为True
        self.mask = pygame.sprite.from_surface(self.image)  # 完美碰撞检测

    def move(self):  # 定义移动方法
        self.rect.top -= self.speed  
        if self.rect.top < 0:  # 如果上边界<0
            self.active = False  # 子弹存活状态为False

    def reset(self,position):  # 定义子弹重生方法
        self.rect.left, self.rect.top = position    #重新生成子弹时,需要根据我方飞机最新的位置来生成
        self.active = True   # 将重新生成的子弹状态改为True

你可能感兴趣的:(pygame实例——飞机大战)