如何在pygame中创建受到伤害/红色小插图效果

时间:2019-05-27 23:16:56

标签: python pygame

我正在使用pygame模块在python中制作2D游戏。每当玩家在我的游戏中受到伤害时,我想创建一个红色的小插图/出血效果。在当今的许多游戏中都可以看到这一点,其中屏幕边缘将闪烁红色一秒钟并迅速消失。

我曾尝试将我在photoshop中制作的图像放大,并在动画周期中对其进行相应缩放,但这确实是一项繁重的操作,随后会导致很多延迟。我正在寻找这种方法的替代方法。

声明一些变量的代码:

bgX = 0
bgY = 0
damage = pygame.image.load("defensiveGameHUD.png").convert_alpha()
dimensions = [1920,1080]

然后我在游戏的主循环中拥有这个:

win.blit(background,(0,0))

if dimensions[0] != 4020:
    dimensions[0] += 30
    bgX -= 15
if dimensions[1] != 4600:
    dimensions[1] += 40
    bgY -= 20

if dimensions[1] != 4600:
    screenDamage = pygame.transform.scale(damage, dimensions)
    win.blit(screenDamage, (bgX, bgY))
else:
    screenDamage = None

这只是一个可以缩放图像的动画,但是缩放比例不正确,这在性能上非常昂贵。

1 个答案:

答案 0 :(得分:2)

通过将pygame.Surface.fill()设置为special_flags = BLEND_MULT,可以将屏幕着色为红色。
以下函数将scale从0到1以红色“着色”整个表面。如果scale为0,则不着色该表面;如果scale为1,则整个表面为红色。用(红色)颜色(255,0,0)着色:

def tintDamage(surface, scale):
    GB = min(255, max(0, round(255 * (1-scale))))
    surface.fill((255, GB, GB), special_flags = pygame.BLEND_MULT)

该函数必须在pygame.display.flip()pygame.display.update()之前被调用:

例如

tintDamage(win, 0.5)
pygame.display.flip()

注意,使用pygame.Surface.blit()时也可以设置special_flags = BLEND_MULT

win.blit(damage, (bgX, bgY), special_flags = pygame.BLEND_MULT)

甚至两种效果都可以组合。


  

那并不是我一直在寻找的效果[...]我希望这种效果先向内扩展​​再向外扩展,...

您想要做的事情很棘手,因为您必须动态更改损坏表面的每个像素。那太慢了。

但是您可以根据效果等级来预先计算不同的损坏表面:

def smmothstep(edge0, edge1, x):
    t = min(1, max(0, (x - edge0) / (edge1 - edge0)))
    return t * t * (3.0 - 2.0 * t)

def gen_damage_image(scale, source):
    dest = source.copy()
    img_size = dest.get_size()
    for i in range(img_size[0]):
        for j in range(img_size[1]):
            fx = smmothstep(0, img_size[0]/2*scale, min(i, img_size[0]-i))
            fy = smmothstep(0, img_size[1]/2*scale, min(j, img_size[1]-j))
            color =  dest.get_at((i, j))
            fade_color = [int(255 - (1-fx*fy)*(255 - c)) for c in color]
            dest.set_at((i, j), fade_color)
    return dest

damage = pygame.image.load("defensiveGameHUD.png").convert_alpha()
max_dmg_img = 10
dmg_list = [gen_damage_image((i+1)/max_dmg_img, damage) for i in range(max_dmg_img)]

tintDamage根据比例选择列表中的损坏图像:

def tintDamage(surface, scale):
    i = min(len(dmg_list)-1, max(0, int(scale*(len(dmg_list)-0.5))))
    c.blit(dmg_list[i], (0, 0), special_flags = pygame.BLEND_MULT)

向内/向外效果可以通过正弦函数实现。请参见示例,当按下 x 时,该示例开始生效:

run = True
start_time = 0
tint = 0
damage_effect = False
while run:
    clock.tick(60)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_x:
                damage_effect = True
                tint = 0

    win.fill((196, 196, 196))

    # [...]

    if damage_effect:
        scale = math.sin(tint)
        tintDamage(win, scale)
        tint += 0.1
        damage_effect = scale >= 0
    pygame.display.flip()