我正在使用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
这只是一个可以缩放图像的动画,但是缩放比例不正确,这在性能上非常昂贵。
答案 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()