Tutorial Space Shooter Godot: Colisões e Explosões - Parte 7

Aprenda a criar um jogo Space Shooter de forma simples e prática com a Godot. Aprenda as funcionalidades da Engine e faça seu jogo um sucesso.

Tutorial Space Shooter Godot: Colisões e Explosões - Parte 7
Photo by Erwan Hesry / Unsplash

Bem vindo de volta meu amigo Game Dev!!! Veio pra continuar seu treinamento Jedi pequeno Padawan? Muito bem, pois então vamos dar uma retomada rápida antes de começar. O que já fizemos até aqui:

  • Baixamos a Godot, Assets do Kenny e do OpenGameArt - Tudo isso no primeiro post da série, neste link aqui.
  • Criamos o fundo animado em Parallax - No nosso segundo post, tá aqui o link.
  • Criamos a cena do Player e dos Lasers, definimos como realizar os movimentos da nave e disparo dos tiros - Isso foi no nosso terceiro post da série, bem aqui.
  • Criamos o template de inimigos, dois tipos de inimigos diferentes e um Spawner para gerar eles automaticamente - Nosso quarto post, segue o link.
  • Criamos as cenas dos Power-Up's, definimos seus scripts de movimentação e como eles interagem com o Player, também criamos um Spawner para os poderes e fizemos alguma melhorias - Levamos dois posts para isso: nosso quinto post e sexto post.

Hoje vamos dar sequência à construção do nosso jogo incluíndo novas cenas para as explosões que podem acontecer, incluíndo partículas para ter um efeito visual bem interessante.

Passo 9 - Colisões e Explosões

Trataremos das colisões entre naves e adicionaremos efeitos visuais de explosão impressionantes.

Antes de começar o trabalho, vamos pensar quais eventos podem gerar explosões e com isso ter claridade de que ajustes precisamos fazer, adiantei essa lista aqui:

  • Colisão entre Jogador e Inimigo só deveria gerar explosão se um dos dois morrerem;
  • Colisão entre o Inimigo e o Escudo só deveria gerar explosão se o Inimigo morrer;
  • Colisão entre o Laser e o Inimigo só deveria gerar explosão se o Inimigo morrer;

Pela lista acima, a geração de explosões será feita sempre que houver a morte de um inimigo. No nosso caso sempre acontece com um tiro ou colisão dele com o inimigo ou escudo, mas você pode seguir os mesmo passos ajustando o evento em que as partículas acontecem caso seu código tenha outros comportamentos de número de hits no inimigo, no escudo, etc.

Acho que vc já sabe qual função do Inimigo que vai disparar os eventos, né? Na função die do Inimigo vamos gerar um sinal e no script do jogo, com base em tal sinal, vamos gerar explosões.

As nossas explosões serão simplificadas, apenas com a dispersão de partículas, mas tem muita coisa legal que dá pra ser feita com emissão de partículas, dá uma olhada nesse vídeo com alguns exemplos bem legais:

No Youtube tem muitos outros exemplos interessantes que você pode gostar.

Vamos começar criando a nossa nova cena da explosão, como a geração de partículas é um tabú pra muitas pessoas, vou tentar deixar o mais simples possível.

Nossa cena nova só precisa ter um nó do tipo CPUParticles2D, no inspector, você vai configurar como as partículas serão geradas, quantidade, direção de deslocamento, velocidade de deslocamento, tempo de vida, se sofrem ou não influência da gravidade, cor, formato da dispersão, tamanho, etc.

Vou indicar quais foram as configurações que eu achei interessante, mas sugiro à você brincar um pouco com a geração de partículas para ver o que mais te agrada. Então segue o fio das minhas configurações:

  • Emitting: falso (flag desmarcado);
  • Amount: 64
  • Time:
    • Lifetime: 1s (tempo padrão)
    • One shot: true (flag marcado)
    • Explosiveness: 100 (para que as partículas sejam dispersadas com um impulso como em uma explosão)
    • Randomness: 100 (para que em cada geração a posição de cada partícula seja diferente da anterior)
    • Lifetime Randomness: 0,5 (o tempo de vida de cada partícula vai variar entre esse número e o lifetime definido)
  • Emission Shape:
    • Shape: Sphere (formato da dispersão)
    • Sphere Radius: 64 px (raio da esfera que está como formato de emissão)
  • Gravity:
    • x: 0 (sem aplicação de gravidade em x)
    • y: 0 (sem aplicação de gravidade em y)
  • Radial Accell:
    • Accell Min: 10 (velocidade mínima do movimento das partículas do centro para a borda da esfera)
    • Accell Max: 100 (velocidade máxima do movimento das partículas do centro para a borda da esfera)
  • Scale:
    • Scale Amount Min: 1 (tamanho mínimo da partícula)
    • Scale Amount Max: 5 (tamanho máximo da partícula)
  • Color:
    • Color Ramp: dê uma olhada na imagem abaixo (gradiente com 4 pontos, formando 3 regiões: de transparente até amarelo, de amarelo até vermelho, de vermelho até transparente)
  • CanvasItem:
    • Material: (é obrigatório definir os itens abaixo para gerar partículas)
      • Material: CanvasItemMaterial
      • Particles Animation: true (flag ativo)

Os demais itens não foram alterados, pode deixar com os valores padrão ou ajustar conforme sua preferência. Abaixo um print da tela com o gradiente de cores:

Cena das partículas com destaque para o gradiente de cores.

Precisamos também incluir um script para esta cena, somente para eliminar as partículas da memória quando elas não forem mais necessárias, isso é importante para garantir a performance do seu jogo, lembre-se de sempre fazer este tipo de otimizações.

O script será bem simples, conecte o sinal de finished ao script e inclua um queue_free. Além disso, ative a emissão das partículas quando a cena foi criada:

extends CPUParticles2D

func _ready():
	emitting = true

func _on_finished():
	queue_free()

E sua cena de partículas está pronta, vamos para o próximo passo? Como nossas partículas serão geradas quando o inimigo for destruído, vamos fazer com que na sua função die um sinal seja emitido indicando a posição em que as partículas tem que ser geradas.

Serão dois ajustes no script do inimigo, um para criar o sinal à ser emitido e outro para emitir este sinal no momento da morte do inimigo indicando a sua posição. O código ficará desse jeitinho:

...
signal create_particles(location)
...
func die():
	emit_signal("create_particles", position)
	queue_free()

No Editor o código será apresentado dessa forma:

Ajustes no script do inimigo

E por último, na cena do game, precisamos fazer algo similar ao que fizemos com a geração dos lasers. Vamos incluir mais um container, só para que as explosões não fiquem largadas diretamente como filhas da cena principal.

Container para armazenar as explosões.

E no script vamos fazer os seguintes ajustes:

  • Criar uma variável referência ao novo container;
  • Criar uma variável com a cena de explosão pré-carregada;
  • Conectar o sinal ao inimigo criado na função do time de spawn de inimigos;
  • Criar uma função para gerar a explosão, essa função será chamada quando o sinal for recebido no momento da morte do inimigo.

Os ajustes são estes aqui:

...
@onready var particle_container = $ParticleContainer
...
var particles_scene = preload("res://scenes/particles.tscn")

...
func _on_enemy_spawn_timer_timeout():
	var e = enemy_scenes.pick_random().instantiate()
	e.global_position = Vector2(randf_range(60, 480), -50)
	e.create_particles.connect(_on_hit_explode)
	enemy_container.add_child(e)
	
...
func _on_hit_explode(location):
	var particle = particles_scene.instantiate()
	particle.global_position = location
	particle_container.add_child(particle)

Atenção aos ajustes para que as explosões funcionem corretamente, ok? São detalhes que podem fazer a diferença no comportamento do seu jogo. No editor os ajustes do script vão ficar desse jeito aqui:

Script do game com os ajustes para apresentar as explosões.

Rode seu jogo e veja se tudo funcionou direitinho, você deve ver algo parecido com fogos de artifício quando derrotar um dos inimigos. Revise o post e as configurações definidas caso as explosões não estejam como você esperava.

Caso ainda tenha algum problema, deixe uma mensagem pra gente. Lembre-se que estamos disponíveis também pelo Discord e WhatsApp, esperamos você por lá, beleza? Nos vemos na próxima semana, grande abraço!