Fazer o sprite piscar ao tomar dano na Godot 4
Aprenda a fazer o sprite piscar ao tomar dano na Godot 4 com modulate e Tween tipado: uma funcao piscar_dano() que da feedback de impacto ao combate.
Um golpe que não muda nada na tela não parece um golpe. O inimigo perde vida, o número cai em algum canto da interface, e o jogador não sente peso nenhum no impacto. Esse é um dos buracos mais comuns em protótipos: a lógica de combate funciona, mas o jogo parece morto. Fazer o sprite piscar ao tomar dano na Godot 4 é a correção mais barata para isso, e dá para resolver em poucas linhas mexendo só na propriedade modulate com um Tween tipado, sem tocar em shader nenhum.
Neste tutorial você vai montar uma função piscar_dano() completa, entender por que ela dá sensação de impacto, integrar ela com a lógica de dano do personagem e cobrir os casos em que o modulate não basta e vale subir para um shader. Todo o código é GDScript do Godot 4.x e tipado.
Por que a piscada dá sensação de impacto
Game feel é a soma de pequenos retornos que o jogo dá quando o jogador faz algo. Quando você aperta o botão e o personagem ataca, você espera ver, ouvir e sentir que o golpe aconteceu. A piscada de dano é a resposta visual mais imediata que existe: no frame em que o dano é aplicado, o sprite muda de cor por uma fração de segundo e o olho registra na hora que algo foi acertado.
O efeito funciona porque é curto e contrastante. Uma piscada de 0.15 segundo chama atenção sem poluir a tela. Combinada com um leve tranco, um som seco e alguns frames de invencibilidade, ela transforma uma troca de números em um combate que o jogador sente. E o melhor: o custo em código é mínimo, roda em qualquer hardware e não depende de arte nova.
A ideia: mexer no modulate
Todo nó que herda de CanvasItem (e isso inclui Sprite2D e AnimatedSprite2D) tem uma propriedade chamada modulate. Ela é uma cor que multiplica a cor de cada pixel do sprite na hora de desenhar. No estado de repouso, modulate vale Color.WHITE, ou seja, Color(1, 1, 1, 1), que multiplica tudo por 1 e não altera nada.
A sacada é simples: no instante do dano, você troca o modulate por uma cor de flash e depois devolve ele para Color.WHITE. Se usar um vermelho, o personagem fica tingido de vermelho por um instante, o que combina muito bem com a ideia de dano e sangue. Como modulate é uma propriedade animável, um Tween consegue devolver o valor ao normal de forma suave e cuidar do tempo sozinho.
A estrutura de cena do personagem pode ser simples assim:
Player (CharacterBody2D)
├── CollisionShape2D
└── Sprite2D
A função piscar_dano() com Tween tipado
Aqui está a função completa. Ela tinge o sprite de vermelho na hora e deixa o Tween desbotar de volta para o branco:
extends CharacterBody2D
## Cor do flash no momento do dano (vermelho avermelhado)
@export var cor_dano: Color = Color(1.0, 0.3, 0.3, 1.0)
## Quanto tempo a piscada leva para voltar ao normal
@export var duracao_flash: float = 0.15
@onready var sprite: Sprite2D = $Sprite2D
var tween_dano: Tween = null
func piscar_dano() -> void:
# Se uma piscada anterior ainda esta rodando, cancela ela
# para nao deixar o modulate preso num tom intermediario.
if tween_dano != null and tween_dano.is_running():
tween_dano.kill()
# Aplica o flash instantaneo e anima a volta para o branco.
sprite.modulate = cor_dano
tween_dano = create_tween()
tween_dano.tween_property(sprite, "modulate", Color.WHITE, duracao_flash)
O que cada parte faz:
A troca sprite.modulate = cor_dano é imediata: o personagem fica vermelho no frame em que a função roda. Esse corte seco é o que o olho precisa para registrar o impacto.
O tween_property(sprite, "modulate", Color.WHITE, duracao_flash) cria a animação de volta. O Tween interpola o modulate do vermelho atual até Color.WHITE ao longo de duracao_flash segundos, e some sozinho quando termina. Você não precisa de Timer, nem de contar frames, nem de desligar nada na mão.
A checagem com tween_dano.kill() no começo resolve um bug sutil: se o personagem toma dois golpes em sequência rápida, a segunda chamada criaria um Tween novo por cima do primeiro, e os dois brigariam pelo modulate. Matando o Tween anterior, a nova piscada sempre começa do zero e o sprite nunca fica preso num tom rosa esquisito.
Integrando com a função de tomar dano
A piscada sozinha não serve de nada: ela precisa rodar dentro da lógica que processa o dano. Conecte a chamada piscar_dano() na sua função de receber dano, junto com a subtração de vida:
var vida: int = 30
func receber_dano(quantidade: int) -> void:
vida -= quantidade
piscar_dano()
if vida <= 0:
morrer()
func morrer() -> void:
queue_free()
Quando qualquer parte do jogo chamar receber_dano(5) nesse nó, o personagem perde vida, pisca vermelho e, se a vida zerar, é removido da cena. Se você já tem um sistema de vida montado, é só plugar o piscar_dano() ali dentro. Se ainda não tem, dá para construir um passo a passo seguindo o guia de sistema de vida e dano no Godot, e depois só encaixar a piscada na função de dano.
Piscar várias vezes: o efeito de invencibilidade
Em muitos jogos, depois de tomar dano o personagem fica alguns instantes invencível, e a forma clássica de avisar o jogador disso é fazer o sprite piscar repetidas vezes. Dá para montar isso com o mesmo Tween encadeando idas e voltas na transparência. O canal alpha do modulate controla a opacidade, então animar ele entre 1.0 e 0.0 faz o personagem aparecer e sumir.
@export var duracao_invencivel: float = 1.0
@export var piscadas: int = 6
func piscar_invencivel() -> void:
var tween: Tween = create_tween()
var tempo_por_piscada: float = duracao_invencivel / float(piscadas * 2)
for i: int in range(piscadas):
# Some e volta, um ciclo por iteracao.
tween.tween_property(sprite, "modulate:a", 0.2, tempo_por_piscada)
tween.tween_property(sprite, "modulate:a", 1.0, tempo_por_piscada)
# Garante que o sprite termina totalmente visivel.
tween.tween_callback(func() -> void: sprite.modulate.a = 1.0)
Repare no "modulate:a": no Godot 4 você pode animar um subcomponente de uma propriedade usando essa sintaxe de dois pontos, então o Tween mexe só no alpha e deixa a cor intacta. O tween_callback no fim é uma rede de segurança: mesmo que a conta de tempo não feche redondo, o sprite acaba com alpha 1.0 e nunca fica semitransparente para sempre.
Você pode combinar as duas coisas: chamar piscar_dano() para o flash vermelho imediato do golpe e piscar_invencivel() para o pisca-pisca que dura enquanto o personagem está protegido. Uma dá o feedback do impacto, a outra comunica o estado.
Quando o modulate não basta: o caminho do shader
O modulate tem um limite honesto que vale conhecer antes de prometer demais para si mesmo: ele multiplica a cor da textura. Isso significa que ele nunca deixa o sprite mais claro do que a arte original. Um personagem de armadura preta com modulate branco continua preto, porque qualquer coisa multiplicada pela cor dele volta escura. O vermelho funciona bem porque é um tingimento, mas o clássico flash branco de porrada (aquele em que o inimigo inteiro vira uma silhueta branca no impacto) o modulate sozinho não entrega.
Para forçar branco puro independente da cor original do sprite, o caminho é um shader canvas_item que faz um mix entre a textura e a cor de flash. É um pouco mais de setup, mas o efeito fica muito mais forte em jogos de ação. O passo a passo completo, com o código do shader e o Tween que anima o parâmetro dele, está no guia de shader de hit flash de dano no Godot. A regra prática: para um RPG ou plataforma onde o tingimento vermelho já comunica bem, fique no modulate; para um jogo de pancadaria onde você quer o golpe estalando na tela, vá de shader.
Ajustes de feel que valem experimentar
O efeito certo depende do seu jogo, e o custo de testar é zero porque tudo são valores expostos. Alguns pontos de partida:
A duração entre 0.1 e 0.2 segundo cobre a maioria dos casos. Mais curto que isso quase não dá para ver. Mais longo começa a parecer que o personagem está mudando de cor de propósito em vez de levar um golpe.
A cor do flash não precisa ser vermelha. Vermelho passa dano físico. Um branco azulado dá um tom mais sci-fi. Um amarelo pode indicar um tipo específico de dano, tipo elétrico. Como cor_dano é exportada, dá para ajustar por inimigo direto no Inspector.
A piscada combina muito bem com os outros retornos de impacto. Um leve tranco para trás, um pequeno screen shake e um som seco somados à piscada transformam um golpe sem graça em algo que o jogador sente no corpo. Se o seu personagem muda de direção durante o combate, vale também conferir se o espelhamento está certo, e o guia de como virar o sprite na direção do movimento cobre esse detalhe sem conflitar com o flash.
Se você quiser entender melhor como o Tween funciona por baixo (encadeamento, paralelismo, curvas de transição), vale a leitura do guia dedicado de animação por código com Tween no Godot, porque o mesmo motor que faz a piscada move barras de vida, pop-ups de texto e transições de menu.
Fechando
O caminho da piscada de dano é curto: troca o modulate por uma cor de flash no instante do golpe, deixa um Tween devolver ele ao branco, e pluga a chamada piscar_dano() dentro da função que processa o dano. Com a variação de alpha você ainda ganha o pisca-pisca de invencibilidade de graça, usando o mesmo Tween.
É o tipo de detalhe que não aparece em nenhuma lista de features, mas que o jogador percebe na primeira vez que acerta um inimigo. Monte a função, ajuste a cor e a duração até o golpe parecer certo, e repare como o combate inteiro muda de peso com meia dúzia de linhas. Game feel é isso: pequenos retornos que, somados, fazem o jogo responder vivo.
Perguntas frequentes
Como fazer o sprite piscar ao tomar dano na Godot 4?
Mude a propriedade modulate do sprite para uma cor de flash no instante do dano e use um Tween para devolver ela ao branco (Color.WHITE) em alguns centesimos de segundo. Isso cria a piscada sem precisar de shader.
Da para fazer o sprite ficar branco de verdade so com modulate?
Nao de forma confiavel. O modulate multiplica a cor da textura, entao um sprite escuro continua escuro mesmo com modulate branco. Para pintar o sprite de branco puro independente da cor original, use um shader de hit flash.
Preciso de um Timer para a piscada voltar ao normal?
Nao. O Tween ja cuida do tempo e devolve o modulate ao estado de repouso sozinho. Timer so vale a pena se voce ja usa um no fluxo de dano ou precisa de controle por frame.

