Pygame:飞机大战2(详细解读)

文章目录

  • (一)完成玩家飞机生成的编写---myplane 模块和mian模块的修改
    • 1️⃣定义好一个玩家飞机类,类里编写move方法限制玩家飞机的移动范围
    • 2️⃣在main模块中响应用户的键盘操作
    • 3️⃣实现玩家飞机的动态效果
  • (二)完成敌机生成的编写---enemy模块和main模块的修改
    • 1️⃣完成三种敌机类模块的编写
    • 2️⃣在main模块中实例化敌机


大家好!我是近视的脚踏实地,虽然近视,但是脚踏实地。这一篇继续要完善飞机大战的游戏,这篇主要完成的内容是myplane 的模块模块玩家飞机的生产,以及实现玩家操控,还有就是要完成enemy.py敌机的生产,然后在main模块把这两个对象实例化生成出来

(一)完成玩家飞机生成的编写—myplane 模块和mian模块的修改

首先创建一个名为 myplane 的模块,然后把我方飞机的所有属性和方法定义在里边。

1️⃣定义好一个玩家飞机类,类里编写move方法限制玩家飞机的移动范围

#myplane.py
import pygame

class MyPlane(pygame.sprite.Sprite):
     def __init__(self,bg_size):
          pygame.sprite.Sprite.__init__(self)

          self.image = pygame.image.load("images/me1.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 = \
                                   (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 -= self.speed
          else:
               self.rect.top = 0
               
     #向下走
     def moveDown(self):
          if self.rect.bottom < self.height - 60:
               self.rect.top += self.speed
          else:
               self.rect.bottom = self.height - 60
               
     #向左走
     def moveLeft(self):
          if self.rect.left > 0:
               self.rect.left -= self.speed
          else:
               self.rect.left = 0

     #向右走
     def moveRight(self):
          if self.rect.right < self.width:
               self.rect.right += self.speed
          else:
               self.rect.right = self.width

代码解析:首先来 class Myplane(pygame.sprite.Sprite): 定义玩家类,当然这个类要继承Sprite类,因为后面我们是需要对这个飞机进行碰撞检测的

接着def init(self,bg_size): 这个在其他编程语言叫构造方法,就是用来初始化玩家飞机刚开始的状态的,那么它是需要一个bg_size参数的,就是背景的尺寸,也就是游戏窗口的尺寸,有这个尺寸,我们才能约束这个飞机不让他跑到游戏窗口外,限制在窗口内移动,接着Sprite也要来初始化一下

接着 self.image = pygame.image.load(“images/me1.png”).convert_alpha() 就是把飞机的图片给加载进来,然后这里飞机的png背景需要透明的,所以convert_alpha() 来转化一下,接着就得到一个Surface对象了

接着 self.rect = self.image.get_rect() 就是获取Surface对象的矩形对象咯,之前说过的,每一个Surface对象都会有一个rect矩形对象,是用来描述Surface对象的位置信息,而Surface对象其实就是图片,我们加载进来的图片。

接着self.width,self.height = bg_size[0],bg_size[1] 就是把传进来的bg_size参数即背景图片的尺寸,把它给本地化,意思就是说把传进来的背景图片的宽和高分别给这里面width和height,这两个在其他编程语言就是表示这个类的一个属性,含义是指飞机可以移动的宽和高,因为只有本地化了,在其他方法里才可以直接用到这两个属性,比如下面的方法需要来判断是否大于这个width或者这个height啊,大于就表示超出了游戏窗口,width和height就是这么一个意思

接着self.rect.left,self.rect.top = (self.width - self.rect.width )// 2,self.height - self.rect.height - 60 这里就是给玩家飞机初始化时出现在窗口的位置,那么我们知道,玩家飞机的位置在x轴上应该在中间位置,y轴上不能在最低下,下面要留下60像素的高度用于左部分显示全屏炸弹的剩余个数,右部分显示玩家还剩多少条生命,那么这里x轴就是游戏窗口的宽度减去这个飞机图像矩形对象的宽度再除以2,y轴就是用游戏窗口的高度减去矩形对象的高度再多减去60,然后把这两个值给,玩家飞机rect矩形对象的left,和top,其实这两个就是图片矩形对象左上角的坐标,因为知道了这个左上角的坐标,其余的pygame都会帮你计算好

接着self.speed = 10 就是初始化玩家的速度,这个speed也就是这个飞机类的一个属性,然后玩家飞机需要有一个比较灵敏的速度,给10就好了,这样子玩家控制他,就会觉得老快的亚子了

接下来就是分别来定义四个方法来描述这个飞机的上下左右移动

首先就是def moveUp(self): 来个判断往上走的情况, if self.rect.top > 0: 因为窗口左上角坐标是(0,0) ,如果矩形对象上部分不大于0,就是说没有超过游戏窗口的顶端位置,则self.rect.top -= self.speed 就是每次移动10个像素的位置,就是speed了,然后往上和往左走是减。往下和往右走是加

接着另一种情况就是小于等于0了,要超出游戏窗口的上方了,那么就 self.rect.top = 0 纠正它的位置,使得玩家飞机的矩形对象最高只能跑到这个位置,同样的道理,下面是判断向下、向左、向右的情况,需要注意的地方就是if self.rect.bottom < self.height - 60: 因为要留60像素的高度再下边。所以玩家飞机不可以最下边,这里的判断范围要注意一下,是self.height - 60 ,而不是self.height , 其他的都是照葫芦画瓢,认真敲代码就行了

2️⃣在main模块中响应用户的键盘操作

首先响应用户键盘操作有两种方法,第一汇种我们常用的,当然也是我们最熟悉的,就是通过从pygame的事件队列中检测出事件消息,然后检测如果有KEYDOWN、KEYUP事件,那么我们就知道是玩家按下了键盘按键,这样才会产生KEYDOWN和KEYUP消息

那么第二种就是调用key 模块里的 get_pressed() 方法,这个方法会返回一个序列,这个序列里边是包含你键盘上所有按键的一个布尔类型的值,如果这个值是True 的话,那表示该按键被按下,如果这个值是False的话,就表示该按键没有被按下。

然后这里有个建议就是,对于检测偶然触发的键盘事件,那推荐使用第一种方法,比如说我们有个全屏炸弹的功能,是按下空格键,bong~一声爆炸,这个就是偶然触发的,没有经常触发,那就是用第一种方法,但是对于频繁触发的键盘事件,在建议使用第二种方法,因为这个游戏整个过程都是经过我们的键盘灵活的小手指控制键盘来移动这个飞机,所以这里应该是一个频繁的事件,那么我们就依然决然地使用第二种方法,接下来就去改下main函数

import pygame
import sys
import traceback
import myplane
from pygame.locals import *

pygame.init()
pygame.mixer.init()

bg_size = width,height = 480,700
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption("飞机大战 -- Monster ZF")


background = pygame.image.load("images/background.png").convert()

# 载入游戏音乐
pygame.mixer.music.load("sound/game_music.ogg")
pygame.mixer.music.set_volume(0.2)
bullet_sound = pygame.mixer.Sound("sound/bullet.wav")
bullet_sound.set_volume(0.2)
bomb_sound = pygame.mixer.Sound("sound/use_bomb.wav")
bomb_sound.set_volume(0.2)
supply_sound = pygame.mixer.Sound("sound/supply.wav")
supply_sound.set_volume(0.2)
get_bomb_sound = pygame.mixer.Sound("sound/get_bomb.wav")
get_bomb_sound.set_volume(0.2)
get_bullet_sound = pygame.mixer.Sound("sound/get_bullet.wav")
get_bullet_sound.set_volume(0.2)
upgrade_sound = pygame.mixer.Sound("sound/upgrade.wav")
upgrade_sound.set_volume(0.2)
enemy3_fly_sound = pygame.mixer.Sound("sound/enemy3_flying.wav")
enemy3_fly_sound.set_volume(0.2)
enemy1_down_sound = pygame.mixer.Sound("sound/enemy1_down.wav")
enemy1_down_sound.set_volume(0.1)
enemy2_down_sound = pygame.mixer.Sound("sound/enemy2_down.wav")
enemy2_down_sound.set_volume(0.2)
enemy3_down_sound = pygame.mixer.Sound("sound/enemy3_down.wav")
enemy3_down_sound.set_volume(0.5)
me_down_sound = pygame.mixer.Sound("sound/me_down.wav")
me_down_sound.set_volume(0.2)


def main():
    pygame.mixer.music.play(-1)

    #生成玩家飞机
    me = myplane.MyPlane(bg_size)

    clock = pygame.time.Clock()

    running = True


    while running:
        for event in pygame.event.get():
            if event.type == QUIT:       
                pygame.quit()
                sys.exit()

        #检测用户的键盘操作
        key_pressed = pygame.key.get_pressed()
    
        if key_pressed[K_w] or key_pressed[K_UP]:
            me.moveUp()

        if key_pressed[K_s] or key_pressed[K_DOWN]:
            me.moveDown()
            
        if key_pressed[K_a] or key_pressed[K_LEFT]:
            me.moveLeft()
            
        if key_pressed[K_d] or key_pressed[K_RIGHT]:
            me.moveRight()
                  

        screen.blit(background,(0,0))
        # 绘制玩家飞机
        screen.blit(me.image,me.rect)

        pygame.display.flip()
        clock.tick(60)


if __name__ == "__main__":
    try:
        main()
    except SystemExit:
        pass
    except:
        traceback.print_exc()
        pygame.quit()
        input()

代码解析:首先import myplane 把刚刚我们写好的玩家飞机的模块导入主模块,接着me = myplane.MyPlane(bg_size) 把bg_size给传进去,这样就就初始化好了玩家飞机me了

接着key_pressed = pygame.key.get_pressed() 那么现在得到的key_pressed变量就是一个序列,序列里边包含整个键盘所有按键的一个布尔类型值。

接着 if key_pressed[K_w] or key_pressed[K_UP] ,刚刚说了,现在key_pressed变量就是一个序列,而这里K_w 事实上就是一个索引值,他事实上都是定义的,他背后都有一个数字,那这里就是他的一个索引值,就是表示当W这个键被按下时,还有一个或者UP就是方向键的⬆️被按下时,那么就me.moveUp() 调用飞机往上移动的方法,下面的就是对向下、向左、向右的键盘按键检测,也是照葫芦画瓢,这里就不赘述了

接着screen.blit(me.image,me.rect) 就是在绘制完背景后再来绘制出玩家的飞机

运行结果如下:
Pygame:飞机大战2(详细解读)_第1张图片

3️⃣实现玩家飞机的动态效果

Pygame:飞机大战2(详细解读)_第2张图片
那么,为了增加玩家飞机的动态效果,所以我们可以通过两张图片的不断切换,来实现玩家飞机"突突突"的这种飞行的感觉,事实上就是他们的尾气不同,那么就多加一张图片,如下添加和修改:
Pygame:飞机大战2(详细解读)_第3张图片

接着来修改main主模块的代码:

Pygame:飞机大战2(详细解读)_第4张图片
Pygame:飞机大战2(详细解读)_第5张图片
代码解析:那么这里就需要多加一个switch_image = True布尔类型的变量,接着在绘制玩家飞机的时候,那么我们就通过判断和变换这个变量,不断切换地绘制两张图片,if switch_image: 如果是True的话就绘制me1,如果是False就画m2,然后就是switch_image = not switch_image 每次循环取反一次,那么这样就实现了这两种图片不断的切换

此时运行的话可以看到有一些"突突突"的感觉了,但是并不是很明显,因为我们在设置游戏速度最高为60帧,我们不说能够跑到60帧,能跑40帧的话,那就是一秒切换了40次,你能看得清楚吗,那肯定是看不清楚的,所以我们需要增加一点延迟,才能使得效果更加理想,那就是得想办法,在不影响游戏正常速度的情况下来延迟图片的切换

Pygame:飞机大战2(详细解读)_第6张图片
那么这里就可以使用单片机开发中,常常普遍用到的一招,就是增加一个延时的变量,定义好之后,就在循环中,让delayme每一帧减1,接着if not delay: 他减完之后,他又恢复为100。
Pygame:飞机大战2(详细解读)_第7张图片
接着if not (delay % 5): ,这里就是说,因为你的delay是从100减到0,比如99不能被5整除,是有余数的,即 (delay % 5) 这里面为其他数1,2,3,4 再not他们为0也就False,简单来说就是只有是5的倍数才会switch_image = not switch_image 切换这个图片,那也就是说每5帧来切换一次,如果限定帧率为60 的话,那么一秒钟就最多切换12次,这样让肉眼更加明显地看到"突突突"飞机动态效果

下面运行看看效果:
Pygame:飞机大战2(详细解读)_第8张图片
这一部分的myplane.py源码

#myplane.py
import pygame

class MyPlane(pygame.sprite.Sprite):
     def __init__(self,bg_size):
          pygame.sprite.Sprite.__init__(self)

          self.image1 = pygame.image.load("images/me1.png").convert_alpha()
          self.image2 = pygame.image.load("images/me2.png").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 -= self.speed
          else:
               self.rect.top = 0
               
     #向下走
     def moveDown(self):
          if self.rect.bottom < self.height - 60:
               self.rect.top += self.speed
          else:
               self.rect.bottom = self.height - 60
               
     #向左走
     def moveLeft(self):
          if self.rect.left > 0:
               self.rect.left -= self.speed
          else:
               self.rect.left = 0

     #向右走
     def moveRight(self):
          if self.rect.right < self.width:
               self.rect.right += self.speed
          else:
               self.rect.right = self.width

这一部分的mian.py源码

import pygame
import sys
import traceback
import myplane
from pygame.locals import *

pygame.init()
pygame.mixer.init()

bg_size = width,height = 480,700
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption("飞机大战 -- Monster ZF")


background = pygame.image.load("images/background.png").convert()

# 载入游戏音乐
pygame.mixer.music.load("sound/game_music.ogg")
pygame.mixer.music.set_volume(0.2)
bullet_sound = pygame.mixer.Sound("sound/bullet.wav")
bullet_sound.set_volume(0.2)
bomb_sound = pygame.mixer.Sound("sound/use_bomb.wav")
bomb_sound.set_volume(0.2)
supply_sound = pygame.mixer.Sound("sound/supply.wav")
supply_sound.set_volume(0.2)
get_bomb_sound = pygame.mixer.Sound("sound/get_bomb.wav")
get_bomb_sound.set_volume(0.2)
get_bullet_sound = pygame.mixer.Sound("sound/get_bullet.wav")
get_bullet_sound.set_volume(0.2)
upgrade_sound = pygame.mixer.Sound("sound/upgrade.wav")
upgrade_sound.set_volume(0.2)
enemy3_fly_sound = pygame.mixer.Sound("sound/enemy3_flying.wav")
enemy3_fly_sound.set_volume(0.2)
enemy1_down_sound = pygame.mixer.Sound("sound/enemy1_down.wav")
enemy1_down_sound.set_volume(0.1)
enemy2_down_sound = pygame.mixer.Sound("sound/enemy2_down.wav")
enemy2_down_sound.set_volume(0.2)
enemy3_down_sound = pygame.mixer.Sound("sound/enemy3_down.wav")
enemy3_down_sound.set_volume(0.5)
me_down_sound = pygame.mixer.Sound("sound/me_down.wav")
me_down_sound.set_volume(0.2)


def main():
    pygame.mixer.music.play(-1)

    #生成玩家飞机
    me = myplane.MyPlane(bg_size)

    clock = pygame.time.Clock()

    #用于切换图片
    switch_image = True

    #用于延迟
    delay = 100

    
    running = True


    while running:
        for event in pygame.event.get():
            if event.type == QUIT:       
                pygame.quit()
                sys.exit()

        #检测用户的键盘操作
        key_pressed = pygame.key.get_pressed()
    
        if key_pressed[K_w] or key_pressed[K_UP]:
            me.moveUp()

        if key_pressed[K_s] or key_pressed[K_DOWN]:
            me.moveDown()
            
        if key_pressed[K_a] or key_pressed[K_LEFT]:
            me.moveLeft()
            
        if key_pressed[K_d] or key_pressed[K_RIGHT]:
            me.moveRight()
                  

        screen.blit(background,(0,0))
        # 绘制玩家飞机       
        if switch_image:
            screen.blit(me.image1,me.rect)
        else:
            screen.blit(me.image2, me.rect)
       
        #切换图片
        if not (delay % 5):
            switch_image = not switch_image
            
        delay -= 1
        if not delay:
            delay = 100
            

        pygame.display.flip()
        clock.tick(60)


if __name__ == "__main__":
    try:
        main()
    except SystemExit:
        pass
    except:
        traceback.print_exc()
        pygame.quit()
        input()

(二)完成敌机生成的编写—enemy模块和main模块的修改

1️⃣完成三种敌机类模块的编写

那么玩家的飞机现在有了,现在我们需要的就是创造敌机,敌机的话呢,分为小、中、大三个尺寸,他们的速度依次就是快、中、慢,越小越快,越大越慢,那么就是在页面上方,即游戏窗口顶部的上方,可以通过随机生成他们的位置来玩,比如说,上方可以在-5到0这段位置随机出现一个敌机,因为左上角的坐标是(0,0)嘛,那这样子随机就不会说他们在同一排里出现了

import pygame
from random import *

#小型敌机
class SmallEnemy(pygame.sprite.Sprite):
     def __init__(self,bg_size):
          pygame.sprite.Sprite.__init__(self)

          self.image = pygame.image.load("images/enemy1.png").convert_alpha()
          self.rect = self.image.get_rect()
          self.width,self.height = bg_size[0],bg_size[1]
          self.speed = 2

          self.rect.left,self.rect.top = \
                         randint(0, self.width - self.rect.width),\
                         randint(-5 * self.height, 0)


     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)

#中型敌机
class MidEnemy(pygame.sprite.Sprite):
     def __init__(self,bg_size):
          pygame.sprite.Sprite.__init__(self)

          self.image = pygame.image.load("images/enemy2.png").convert_alpha()
          self.rect = self.image.get_rect()
          self.width,self.height = bg_size[0],bg_size[1]
          self.speed = 1

          self.rect.left,self.rect.top = \
                         randint(0, self.width - self.rect.width),\
                         randint(-10 * self.height,-self.height)


     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(-10 * self.height,-self.height)

#大型敌机
class BigEnemy(pygame.sprite.Sprite):
     def __init__(self,bg_size):
          pygame.sprite.Sprite.__init__(self)

          self.image1 = pygame.image.load("images/enemy3_n1.png").convert_alpha()
          self.image2 = pygame.image.load("images/enemy3_n2.png").convert_alpha()
          self.rect = self.image1.get_rect()
          self.width,self.height = bg_size[0],bg_size[1]
          self.speed = 1

          self.rect.left,self.rect.top = \
                         randint(0, self.width - self.rect.width),\
                         randint(-15 * self.height,-5 * self.height)


     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(-15 * self.height,-5 * self.height)

代码解析:
Pygame:飞机大战2(详细解读)_第9张图片
首先上面导入啊,初始化啊,加载图片啊,获取Surface对象,矩形对象,bg_size本地化啊,前面完成myplane已经提到过了,这里就不赘述了,忘记了的可以回头看

接着self.speed = 2 这个小型敌机速度给2,大家可能觉得2太小,因为玩家的飞机有10,但是呢,其实大部分游戏都是这样的,刚开始简单,然后慢慢地你会发现对方怎么越跑越快,越跑越快,然后到最后就直接是下飞机雨了,所以这里我们从慢开始,后边会做一个级别的提升,提升级别,速度再来提升也不迟

接着self.rect.left,self.rect.top = randint(0, self.width - self.rect.width), randint(-5 * self.height,0) 接着这里就是来初始化小型敌机的初始位置,那么x方向就是在0,到self.width - self.rect.width 屏幕宽度减去敌机矩形宽度的范围随机生成,y轴就是让小型敌机在-5个屏幕到0之间随机生成就会好了,也就是游戏窗口上方看不见的位置初始化

接着由于敌机只会一个劲地往前冲,所以敌机的移动只是简单地增加rect.top的坐标就可以了,当敌机的坐标超出屏幕的低端的话,那么则修改敌机矩形对象rect.top的位置让他重新初始化,那么就是来写他的move方法了

那么就是定义def move(self): move方法,if self.rect.top < self.height: 判断如果敌机矩形对象的top小于屏幕的高度,就self.rect.top += self.speed 让他的top坐标一直增加就好了,否则就是超过了屏幕低端,那就调用reset() 方法来重新初始化,那么reset() 方法 实现也非常简单,就是初始化位置,直接把上面的copy过来就

那么同样的方法我们可以定义出中大型敌机,其中大型敌机作为BOSS级别的人物存在,他的飞行也是有特写和音效的,飞起来会有的噜噜噜声,另外对比起小型敌机,中大型敌机会显得更少一些,因此我们将生成的位置,纵轴的这个位置,把它再扩大,那么同样的数量就变得更稀了,因为到后边会根据难度的情况下不断增加,如果说你这个范围太小的话,因为随机的东西很难说,等下就有可能5、6个一起了,但是你扩大了范围就不会,这样他们堆在一起的范围就更低了
Pygame:飞机大战2(详细解读)_第10张图片
那么就是把定义小型那里copy下来,先修改加载的图片,改为中型飞机的图片, 在修改一下,self.speed = 1 速度改为1更慢一些,接着randint(-10 * self.height,-self.height) 初始化中型飞机的位置,在-10倍的屏幕宽度到-屏幕宽度,符号就表示实在游戏窗口顶部的上方,看不见的位置,这样定义就不会说一开始就跑出一个中型或大型的飞机出来,他最少也在一个屏幕之外,后面的reset方法初始化位置也要相应改一下

Pygame:飞机大战2(详细解读)_第11张图片

Pygame:飞机大战2(详细解读)_第12张图片

那么同样的方式再来定义一下大型飞机,还是copy一份,这里没有做代码的重用的封装,那么就是多打代码少动脑,实际开发中,最好封装一下重复度比较高的代码,然后这里也是先修改一下大型敌机的图片,刚刚也说了大型敌机飞行是有特效的,事实上就敌机前有一些改动,火焰,接着再改一下他初始化的位置就好了,下面的reset方法也要改一下,那么这个模块就完成了

2️⃣在main模块中实例化敌机

import pygame
import sys
import traceback
import myplane
import enemy
from pygame.locals import *

pygame.init()
pygame.mixer.init()

bg_size = width,height = 480,700
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption("飞机大战 -- Monster ZF")


background = pygame.image.load("images/background.png").convert()

# 载入游戏音乐
pygame.mixer.music.load("sound/game_music.ogg")
pygame.mixer.music.set_volume(0.2)
bullet_sound = pygame.mixer.Sound("sound/bullet.wav")
bullet_sound.set_volume(0.2)
bomb_sound = pygame.mixer.Sound("sound/use_bomb.wav")
bomb_sound.set_volume(0.2)
supply_sound = pygame.mixer.Sound("sound/supply.wav")
supply_sound.set_volume(0.2)
get_bomb_sound = pygame.mixer.Sound("sound/get_bomb.wav")
get_bomb_sound.set_volume(0.2)
get_bullet_sound = pygame.mixer.Sound("sound/get_bullet.wav")
get_bullet_sound.set_volume(0.2)
upgrade_sound = pygame.mixer.Sound("sound/upgrade.wav")
upgrade_sound.set_volume(0.2)
enemy3_fly_sound = pygame.mixer.Sound("sound/enemy3_flying.wav")
enemy3_fly_sound.set_volume(0.2)
enemy1_down_sound = pygame.mixer.Sound("sound/enemy1_down.wav")
enemy1_down_sound.set_volume(0.1)
enemy2_down_sound = pygame.mixer.Sound("sound/enemy2_down.wav")
enemy2_down_sound.set_volume(0.2)
enemy3_down_sound = pygame.mixer.Sound("sound/enemy3_down.wav")
enemy3_down_sound.set_volume(0.5)
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 i in range(num):
        e1 = enemy.SmallEnemy(bg_size)
        group1.add(e1)
        group2.add(e1)

def add_mid_enemies(group1,group2,num):
    for i in range(num):
        e2 = enemy.MidEnemy(bg_size)
        group1.add(e2)
        group2.add(e2)
        
def add_big_enemies(group1,group2,num):
    for i in range(num):
        e3 = enemy.BigEnemy(bg_size)
        group1.add(e3)
        group2.add(e3)


def main():
    pygame.mixer.music.play(-1)

    #生成玩家飞机
    me = myplane.MyPlane(bg_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)

    clock = pygame.time.Clock()

    #用于切换图片
    switch_image = True

    #用于延迟
    delay = 100

    
    running = True


    while running:
        for event in pygame.event.get():
            if event.type == QUIT:       
                pygame.quit()
                sys.exit()

        #检测用户的键盘操作
        key_pressed = pygame.key.get_pressed()
    
        if key_pressed[K_w] or key_pressed[K_UP]:
            me.moveUp()

        if key_pressed[K_s] or key_pressed[K_DOWN]:
            me.moveDown()
            
        if key_pressed[K_a] or key_pressed[K_LEFT]:
            me.moveLeft()
            
        if key_pressed[K_d] or key_pressed[K_RIGHT]:
            me.moveRight()

        screen.blit(background,(0,0))

        # 绘制大型敌机
        for each in big_enemies:
            each.move()
            if switch_image:
                screen.blit(each.image1,each.rect)
            else:
                screen.blit(each.image2,each.rect)
            #即将出现在画面中,播放音效
                if each.rect.bottom > -50:
                    enemy3_fly_sound.play()

        # 绘制中型敌机:
        for each in mid_enemies:
            each.move()
            screen.blit(each.image,each.rect)

        # 绘制小型敌机:
        for each in small_enemies:
            each.move()
            screen.blit(each.image,each.rect)
        
                              
        # 绘制玩家飞机       
        if switch_image:
            screen.blit(me.image1,me.rect)
        else:
            screen.blit(me.image2, me.rect)
       
        #切换图片
        if not (delay % 5):
            switch_image = not switch_image
            
        delay -= 1
        if not delay:
            delay = 100


        pygame.display.flip()
        clock.tick(60)


if __name__ == "__main__":
    try:
        main()
    except SystemExit:
        pass
    except:
        traceback.print_exc()
        pygame.quit()
        input()

Pygame:飞机大战2(详细解读)_第13张图片
代码解析:首先import enemy 把刚刚写好的模块导入,接着就是在创建出玩家飞机就来创建敌机,那么就先来enemies = pygame.sprite.Group() 创造一个enemies敌机的汇总,就是把所有的敌机都放到这个组里边去,然后待会检测的时候,就检测me 就是玩家飞机 跟所有的敌机是否会发生碰撞就了。

Pygame:飞机大战2(详细解读)_第14张图片
接着小、中、大他们分别也要有一个组,因为小的飞行模式,小的被撞,被打,是跟中的,大的不一样的,比如中性的敌机可以打8次,大型的可以打20次才会死,而小的是一枪一个,所以这里small_enemies = pygame.sprite.Group() ,这里待会会写出三个函数,分别是add_small_enemies()、add_mid_enemies()、add_big_enemies()、,因为后边的话随着难度的不断增加,我们会往这个组里边添加敌机的数量,所以我们把这个添加的过程抽象为一个函数,那么后边可以更加方便的调用,那么 这是添加到两个组,一个是small_enemies,另一个就是enemies,然后第三个参数刚开始添加15个飞机就好,中型飞机刚开始就给4个或者5个就好,大型的给2个就好

Pygame:飞机大战2(详细解读)_第15张图片
接着def add_small_enemies(group1,group2,num): 来定义刚刚说的那三个函数,先来小型飞机的, for i in range(num): 通过迭代,来一个一个实例化小型飞机,e1表示的就是小型敌机的实例化对象,接着 group1.add(e1) 把它添加到group1,这个group1就是pygame的Sprite的group,用来存所有类型飞机的,因为后面要做碰撞检测嘛,所以用的是add方法,而不是用append方法,append方法是给列表添加,接着在添加group2就可以了

接着中型和大型的也是换汤不换药,改下变量名就可以了,那么把飞机都初始化了,我们就可以把他们放到外面的界面上,把他们画出来,在显示到界面上

那么这里要注意的就是要先画大型敌机, 因为你先画大型敌机,那么后边画的小型敌机就会飞行在大型敌机上面,因为 大型敌机很大个,而且小型敌机的飞行速度比大型敌机的快,那肯定是要飞在大型敌机上边咯,因为在下边的话,就被大型敌机盖住了,看不到了,就有可能玩家好不容易把大型机打死了,诶呀,突然冒出一个小型机把你炸了,这样肯定不好,所以要先画大型机
Pygame:飞机大战2(详细解读)_第16张图片

那么for each in big_enemies: 这里就是从大型敌机的group里一个一个画出来,each.move() 先让他移动,然后之前说了大型敌机是BOOS级别的存在,所以也是有两张图片不停切换的,所以if switch_image: 这里就是和上面切换玩家飞机是一样的道理的,增加延迟效果更佳。 然后大型敌机还有自己的音效,之前已经把所有需要的音效都导入了,这个叫enemy3_fly_sound,所以我们要在他出现之前就要播放这个音效,因为这个音效也是有一定的时长的,那么if each.rect.bottom > -50 这里就表示大概在屏幕以上大概50像素的位置,就播放音效,然后伴随着音效华丽登场

接着绘制中型和小型就简单得多了。从对应的group组中遍历出来,然后代用move方法,在画出来就好了

运行效果如下:

为了看到大型和中型的飞机,我是等了一段时间才录的屏,刚开始一段是只有小型敌机的,可以看到他们现在可以出来了,因为还没有做碰撞检测,所以现在他们可以友好地接触,下一篇就会来完成完美的碰撞检测功能。

本篇博客到这就完啦,非常感谢您的阅读,下一篇继续来完成飞机大战游戏,如果对您有帮助,可以帮忙点个赞或者来波关注鼓励一下喔 ,嘿嘿

你可能感兴趣的:(Python)