pygame飞机大战用精灵组(sprite)的层(layer)编写(二)BOSS登场了

BOSS的编写方式是最复杂的,编写完这个,其他的飞机都是小菜。

先从BOSS的动态图形开始吧。

大部分的飞机一张从头到尾一张图片解决,也不觉得怎么样,但是BOSS就是得有BOSS的样子,自拍也比别人多,BOSS的形态就得多样化。

一般来说,BOSS的图片是好几种连续的动态图,后面的动态子弹也要用到,我们先干脆定义一个实现动态显示的类,一劳永逸。

精灵类的实现可以看前面的随笔

https://mp.csdn.net/postedit/88769971

根据要求抽象出来了一些基本的函数,对应有多张图片组成的动态图,用,load_images加载到 images ,单张图片切割成多张的,用load_image()加载到images  在调用类的update里,获取下当前的图片get_current_image,就会动态显示了。

""" 动态图的加载类
    用两种方式实现,一种是加载多张图片,一种是加载一张图片,按要求进行切割
    都是把图像存到  images 的列表里,每次取两张,取完后从头开始
    精灵类的self.image 是唯一的,但动态背景交接过程会同时存在两张image,无法使用精灵
    使用方法:在这个里的初设函数里直接加在images列表,也可以在主屏幕的函数里,用load_images或者load_image来加载
"""
import pygame
from pygame.locals import *
from setting import *

class Animation(object):
    def __init__(self):
        self.image = None
        self.images = []
        self.frame = 0
        self.first_frame = 0
        self.last_frame = 0
        self.columns = 1
        self.last_time = pygame.time.get_ticks()
        self.rate = 100

    def load_images(self, filename_prefix, begin_num, end_num,
                    filename_suffix):
        """ 加载一系列图片
            filename_prefix 图片的路径及图名一致部分,例如 "imagse/blast"

            begin_num 图名的数字编码开始,int 类型   例如 0

            end_num 图名数字编码结束,int 类型     例如 10
            
            filename_suffix 图名的后缀,例如 ".png"
        """
        self.images = [
            pygame.image.load(filename_prefix + str(v) + filename_suffix)
            for v in range(begin_num, end_num + 1)
        ]
        self.image = self.images[0]
        self.last_frame = end_num - 1
        return self.images

    def load_image(self, filename, width, height, rows, columns):
        """ 
        加载一张图,按照 rows 和 columns切割成多张
            filename 字符串,整个图名,含路径
            width 图的宽度,像素
            height 图的高度,像素
            rows 想要切割的行数
            columns 想要切割的列数
        """
        frame_width = width // columns
        frame_height = height // rows
        self.boom_picture = pygame.image.load(filename)
        #初始化的时候,已经加载了图像,先清空
        self.images.clear()
        # 根据行列数,切换成 row * col 个图片
        for row in range(rows):
            for col in range(columns):
                frame = self.boom_picture.subsurface([
                    col * frame_width, row * frame_height, frame_width,
                    frame_height
                ])
                self.images.append(frame)
        self.last_frame = rows * columns - 1
        self.image = self.images[0]
        return self.images


    def get_current_image(self):
        current_time = pygame.time.get_ticks()
        if current_time > self.last_time + self.rate:
            self.frame += 1
            if self.frame > self.last_frame:
                self.frame = self.first_frame
            self.last_time = current_time
            self.image = self.images[self.frame]
        return self.image
    

工具有了,BOSS该登场了。很简单的几行代码 boss.py

self.mask这行代码,是为了以后的碰撞检查用的,可以忽略透明像素,使检查更精确。

from setting import *
from animation import *


class BossPlane(pygame.sprite.Sprite):
    def __init__(self):
        self._layer = 2
        self.groups = allgroup, bossgroup
        pygame.sprite.Sprite.__init__(self, self.groups)
        #设置飞机动态图像
        self.animation = Animation()
        self.images = self.animation.load_images('images/boss/', 0, 10, '.png')
        self.image = self.images[1]
        self.mask = pygame.mask.from_surface(self.image)
        # 飞机矩形
        self.rect = self.image.get_rect()

    def update(self):
        #更新飞机当前图像
        self.image = self.animation.get_current_image()

最后在main.py 登场

和 加载动态背景图一样,两行代码解决

from boss import *

BossPlane()

至此,main.py的完整代码如下:

from setting import *
from background import *
from boss import *


class MainScene(object):
    #初始化
    def __init__(self):
        pygame.mixer.pre_init()
        pygame.init()
        pygame.mixer.init()
        pygame.font.init()
        # pygame.mouse.set_visible(False)
        self.scene = pygame.display.set_mode((SCENEWIDTH, SCENEHEIGHT), 1, 32)
        pygame.display.set_caption("自学飞机大战--精灵版")
        #载入地图
        Background(vect(0, 0))  # from (0,0),lefttop coordinate
        BossPlane()

    #绘制各个元素
    def draw(self):
        allgroup.draw(self.scene)

    def update(self):
        allgroup.update()

    def collideEvent(self):
        pass

    #处理键盘和鼠标相应
    def handleEvent(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pass
                elif event.key == pygame.K_p:  # print layer information in console
                    print("=========================")
                    print("-----Spritelist---------")
                    print("------------------------")
                    print("toplayer:", allgroup.get_top_layer())
                    print("bottomlayer:", allgroup.get_bottom_layer())
                    print("layers;", allgroup.layers())
                    print("=========================")

    def runScene(self):
        pygame.mixer.music.load('music/bgm.mp3')
        pygame.mixer.music.play(-1)
        clock = pygame.time.Clock()
        while True:
            clock.tick(60)
            self.draw()
            self.update()
            self.collideEvent()
            self.handleEvent()
            pygame.display.flip()


if __name__ == "__main__":
    play = MainScene()
    play.runScene()

else:
    print("i was imported by", __name__)

用到的所有资源图片和音效,可在置顶的链接里下载。

猜你喜欢

转载自blog.csdn.net/hailler1119/article/details/88927126