Тонировать экран красным можно, набрав 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()
Обратите внимание, что special_flags = BLEND_MULT
также можно установить при использовании pygame.Surface.blit () :
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 :
![](https://i.stack.imgur.com/rQo5e.gif)
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()
Поскольку вычислениеизображения очень медленные, я предоставляю решение, которое генерирует масштабную маску для изображения 20x20.Маска масштабируется до размера изображения повреждения и смешивается с изображением повреждения:
def gen_damage_image(scale, source):
scale_size = (20, 20)
scale_img = pygame.Surface(scale_size, flags = pygame.SRCALPHA)
for i in range(scale_size[0]):
for j in range(scale_size[1]):
fx = smmothstep(0, scale_size[0]/2*scale, min(i, scale_size[0]-i))
fy = smmothstep(0, scale_size[1]/2*scale, min(j, scale_size[1]-j))
fade_color = [int(max(0, 255 - (1-fx*fy)*255)) for c in range(4)]
scale_img.set_at((i, j), fade_color)
dest = source.copy()
scale_img = pygame.transform.smoothscale(scale_img, dest.get_size())
dest.blit(scale_img, (0, 0), special_flags = pygame.BLEND_ADD)
return dest