Voltar para o Blog
Quest Log

Fazer o sprite piscar ao tomar dano na Godot 4

Sprite de personagem pixel art tingido de vermelho no instante em que recebe um golpe

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.

Ferramenta:Godot

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.

Curso de Godot
Quer fazer seu primeiro jogo na Godot?

No curso de Godot da CursoGame.Dev você vai do zero ao primeiro jogo, com um desafio prático em cada level e suporte individual no WhatsApp quando travar.

Conhecer o curso de Godot
Suporte no WhatsAppAcesso vitalícioGarantia de 7 dias

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.