【pygame实现星露谷物语风格游戏】12.砍树粒子效果的创建

 一.目标

在砍掉苹果或者砍死树木的时候,会发出如下的粒子效果

被砍掉的苹果或者树木会出现白色的闪光,闪一下再消失

二.代码的编写

这里的思路就是,每当砍掉树木的时候,新创建一个精灵,它的外形与原树木相同,只不过颜色变成了白色,绘制覆盖到原来的树木上,经过很短的时间(苹果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()

 

其中涉及到了一些新的API:

mask_surf = pygame.mask.from_surface()是根据传入的图片生成掩码,掩码会根据图片的透明情况生成,说白了就是一个由0和1组成的矩阵

矩阵的大小与图片大小相同,图片透明的部分数字为1,不透明的部分为0

mask_surf.to_surface()是根据这个掩码生成图片

这里有点类似CV里面的二值图,1代表黑色,0代表白色

我们生成的掩码透明的部分设为1,在经过to_surface变成了黑色,不透明的部分设为0,再经过to_surface变成白色

经过这种操作的图片,透明的部分会变成黑色,不透明的部分统一变成白色。

"""上面的一切都记反了,实际上是1代表白色,0代表黑色"""

如下图所示,如果把树木的图像作为原图传入进来,经过.mask.from_surface()和.to_surface()这两部操作后,图片会变成这样

接下来就是.set_colorkey((0,0,0)),这个函数是让图片在绘制的时候只显示某种颜色的部分,我们这里设置的是只显示白色的部分

完成了这个类之后,接下来就是在树木被摧毁的时候创建粒子效果这个对象

以及苹果被摧毁的时候创建粒子效果这个对象

至于为什么z值选择fruit,是因为作者在写LAYERS这个常量的时候忘记了粒子效果这种情况了,并没有给他单独设置Z值,不过把它与fruit设置为同一图层并不影响视觉效果,因为树木先绘制出来的,粒子效果后绘制出来的,粒子效果依旧会覆盖掉树木

三.完整代码

sprites.py

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()就是将该精灵删除

 

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

owooooow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值