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__)
用到的所有资源图片和音效,可在置顶的链接里下载。