一.目标
二.代码的编写
这里的思路就是,每当砍掉树木的时候,新创建一个精灵,它的外形与原树木相同,只不过颜色变成了白色,绘制覆盖到原来的树木上,经过很短的时间(苹果200ms,树木300ms)后,再kill掉这个精灵,就能达到白光一闪的效果
class Particle(Generic):
def __init__(self, pos, surf, groups, z, duration = 200):
#其中duration是持续时间,默认为200ms
super().__init__(pos, surf, groups, z)
self.start_time = pygame.time.get_ticks()
self.duration = duration
#将图片透明的地方设为黑色(1),不透明的地方设为白色,来获取掩码
mask_surf = pygame.mask.from_surface(self.image)
#根据掩码生成图片,该图片只有黑白两种颜色
new_surf = mask_surf.to_surface()
#set_colorkey是在绘制图片的时候只绘制指定的颜色
new_surf.set_colorkey((0,0,0))
self.image = new_surf
def update(self,dt):
#经过一定的时间之后,这个精灵会被删除
current_time = pygame.time.get_ticks()
if current_time - self.start_time > self.duration:
self.kill()
mask_surf = pygame.mask.from_surface()是根据传入的图片生成掩码,掩码会根据图片的透明情况生成,说白了就是一个由0和1组成的矩阵
矩阵的大小与图片大小相同,图片透明的部分数字为1,不透明的部分为0
mask_surf.to_surface()是根据这个掩码生成图片
我们生成的掩码透明的部分设为1,在经过to_surface变成了黑色,不透明的部分设为0,再经过to_surface变成白色
经过这种操作的图片,透明的部分会变成黑色,不透明的部分统一变成白色。
"""上面的一切都记反了,实际上是1代表白色,0代表黑色"""
如下图所示,如果把树木的图像作为原图传入进来,经过.mask.from_surface()和.to_surface()这两部操作后,图片会变成这样
接下来就是.set_colorkey((0,0,0)),这个函数是让图片在绘制的时候只显示某种颜色的部分,我们这里设置的是只显示白色的部分
完成了这个类之后,接下来就是在树木被摧毁的时候创建粒子效果这个对象
至于为什么z值选择fruit,是因为作者在写LAYERS这个常量的时候忘记了粒子效果这种情况了,并没有给他单独设置Z值,不过把它与fruit设置为同一图层并不影响视觉效果,因为树木先绘制出来的,粒子效果后绘制出来的,粒子效果依旧会覆盖掉树木
三.完整代码
import pygame
from settings import *
from random import *
from timer import Timer
class Generic(pygame.sprite.Sprite):
def __init__(self,pos,surf,groups,z = LAYERS['main']):
super().__init__(groups)
self.image = surf
self.rect = self.image.get_rect(topleft = pos)
self.z = z
self.hitbox = self.rect.copy().inflate(-self.rect.width * 0.2, -self.rect.height * 0.75)
class Water(Generic):
def __init__(self, pos, frames, groups):
#传入的参数,fream是一个列表,存放了水流不同动作的五张图片
self.frames = frames
#fream_index是正在播放第几张图片
self.frame_index = 0
super().__init__(
pos = pos,
surf = self.frames[self.frame_index],
groups = groups,
z = LAYERS['water'])
def animate(self,dt):
self.frame_index += 5 * dt
if self.frame_index >= len(self.frames):
self.frame_index = 0
self.image = self.frames[int(self.frame_index)]
def update(self,dt):
self.animate(dt)
class WildFlower(Generic):
def __init__(self, pos, surf, groups):
super().__init__(pos, surf, groups)
self.hitbox = self.rect.copy().inflate(-20,-self.rect.height)
class Particle(Generic):
def __init__(self, pos, surf, groups, z, duration = 200):
#其中duration是持续时间,默认为200ms
super().__init__(pos, surf, groups, z)
self.start_time = pygame.time.get_ticks()
self.duration = duration
#将图片透明的地方设为黑色(1),不透明的地方设为白色,来获取掩码
mask_surf = pygame.mask.from_surface(self.image)
#根据掩码生成图片,该图片只有黑白两种颜色
new_surf = mask_surf.to_surface()
#set_colorkey是在绘制图片的时候只绘制指定的颜色
new_surf.set_colorkey((0,0,0))
self.image = new_surf
def update(self,dt):
#经过一定的时间之后,这个精灵会被删除
current_time = pygame.time.get_ticks()
if current_time - self.start_time > self.duration:
self.kill()
class Tree(Generic):
def __init__(self, pos, surf, groups, name):
super().__init__(pos, surf, groups)
#创建苹果用到的变量
#导入苹果的图像素材
self.apple_surf = pygame.image.load('../graphics/fruit/apple.png')
#苹果的坐标,是一个常量
self.apple_pos = APPLE_POS[name]
#创建苹果精灵组,这个精灵组会在砍树的时候用到
self.apple_sprites = pygame.sprite.Group()
self.groups = groups
self.create_fruit()
#为砍树用到的变量
self.health = 5#树的生命值
self.alive = True#树是否存活
stump_path = f'../graphics/stumps/{"small" if name == "Small" else "large"}.png'#树状的图片路径
self.stump_surf = pygame.image.load(stump_path).convert_alpha()#把树状图片导入进来
self.invul_timer = Timer(200)#创建一个计时器
def create_fruit(self):
for pos in self.apple_pos:
if randint(0,10) < 2:
#x坐标 = 偏移坐标 + 树的左边缘坐标
x = pos[0] + self.rect.left
#y坐标 = 偏移坐标 + 树的顶部边缘坐标
y = pos[1] + self.rect.top
Generic(
pos = (x,y),
surf = self.apple_surf,
#把它加入苹果精灵组和all_sprites精灵组
#all_sprites是传入的参数的self.group的第一个元素,所以是【0】
groups = [self.apple_sprites,self.groups[0]],
z = LAYERS['fruit'])
def damage(self):
#生命值减一
self.health -= 1
#看看生命值是否小于0了,如果小于0就把该改的东西都改一下就行可
if self.health <= 0:
if self.alive:
Particle(self.rect.topleft, self.image, self.groups[0], LAYERS['fruit'], 300)
self.image = self.stump_surf
self.rect = self.image.get_rect(midbottom = self.rect.midbottom)
self.hitbox = self.rect.copy().inflate(-10,-self.rect.height * 0.6)
self.alive = False
#如果树上还有苹果,随机选一个去除
if len(self.apple_sprites.sprites()) > 0:
random_apple = choice(self.apple_sprites.sprites())
Particle(
pos=random_apple.rect.topleft,
surf=random_apple.image,
groups=self.groups[0],
z=LAYERS['fruit'],
)
random_apple.kill()#Sprite.kill()就是将该精灵删除