Criando o inimigo¶
Agora é hora de criarmos os inimigos de que nosso jogador terá que se desviar. Seu comportamento não será tão complexo: inimigos irão nascer aleatoriamente nos cantos da tela, escolher uma direção aleatória e irão se mover em linha reta.
Nós iremos construir uma cena Inimigo
, que poderemos então instanciar para criar uma quantidade de inimigos independentes no jogo.
Configuração de nós¶
Clique em Cena -> Nova Cena e adicione os seguintes nós:
RigidBody2D (chamado
Turba
)VisibilityNotifier2D (chamado
Visibilidade
)
Não se esqueça de configurar os filhos para que não possam ser selecionados, assim como você fez na cena Jogador.
Nas propriedades RigidBody2D, defina Gravity Scale
(escala da gravidade) para 0
, assim o bicho não vai cair. Além disso, na seção CollisionObject2D, clique na propriedade Mask
(máscara) e desmarque a primeira caixa. Isso garantirá que os bichos da turba não colidirão uns com os outros.
Configure o AnimatedSprite assim como você fez para o jogador. Desta vez, temos 3 animações: voar
(fly), nadar
(swim) e andar
(walk). Existem duas imagens para cada animação na pasta "art".
Ajuste "Speed (FPS)" (Velocidade) para 3
em todas as animações.
Defina a propriedade Playing
no Inspetor como ativa.
Vamos selecionar uma das animações aleatoriamente para que os inimigos tenham alguma variedade.
Assim como as imagens do jogador, essas imagens da turba precisam ser reduzidas. Defina a propriedade Scale
(escala) do AnimatedSprite
como sendo (0.75, 0.75)
.
Como na cena do Jogador
, adicione um CapsuleShape2D
para a colisão. Para alinhar a forma com a imagem, você precisará definir a propriedade Rotation Degrees
(graus de rotação) como 90
na seção Transform
no Inspetor.
Salve a cena.
Script do inimigo¶
Adicione um script à ``Turba``assim:
extends RigidBody2D
public class Mob : RigidBody2D
{
// Don't forget to rebuild the project.
}
// Copy `player.gdns` to `mob.gdns` and replace `Player` with `Mob`.
// Attach the `mob.gdns` file to the Mob node.
// Create two files `mob.cpp` and `mob.hpp` next to `entry.cpp` in `src`.
// This code goes in `mob.hpp`. We also define the methods we'll be using here.
#ifndef MOB_H
#define MOB_H
#include <AnimatedSprite.hpp>
#include <Godot.hpp>
#include <RigidBody2D.hpp>
class Mob : public godot::RigidBody2D {
GODOT_CLASS(Mob, godot::RigidBody2D)
godot::AnimatedSprite *_animated_sprite;
public:
void _init() {}
void _ready();
void _on_VisibilityNotifier2D_screen_exited();
static void _register_methods();
};
#endif // MOB_H
Agora, vamos ver o resto do script. Em ``_ready () ``, rodamos a animação e escolhemos aleatoriamente um dos três tipos de animação:
func _ready():
$AnimatedSprite.playing = true
var mob_types = $AnimatedSprite.frames.get_animation_names()
$AnimatedSprite.animation = mob_types[randi() % mob_types.size()]
public override void _Ready()
{
var animSprite = GetNode<AnimatedSprite>("AnimatedSprite");
animSprite.Playing = true;
string[] mobTypes = animSprite.Frames.GetAnimationNames();
animSprite.Animation = mobTypes[GD.Randi() % mobTypes.Length];
}
// This code goes in `mob.cpp`.
#include "mob.hpp"
#include <RandomNumberGenerator.hpp>
#include <SpriteFrames.hpp>
void Mob::_ready() {
godot::Ref<godot::RandomNumberGenerator> random = godot::RandomNumberGenerator::_new();
random->randomize();
_animated_sprite = get_node<godot::AnimatedSprite>("AnimatedSprite");
_animated_sprite->_set_playing(true);
godot::PoolStringArray mob_types = _animated_sprite->get_sprite_frames()->get_animation_names();
_animated_sprite->set_animation(mob_types[random->randi() % mob_types.size()]);
}
Primeiro, nós pegamos a lista dos nomes das animações a partir da propriedade frames
do AnimatedSprite. Isto retorna um Array contendo os nomes das três animações: ["andar", "nadar, "voar"]
.
Nós precisamos, então, de um número aleatório entre 0
e 2
para selecionar um dos nomes da lista (os índices de um vetor começam do 0
). randi() % n``seleciona aleatoriamente um inteiro entre ``0
e n-1
.
Nota
Você deve usar randomize()
se quiser que sua sequência de números "aleatórios" seja diferente toda vez que você executar a cena. Nós vamos usar randomize()
em nossa cena Principal
, então não precisaremos dessa função aqui.
A última parte é fazer os inimigo se autodestruirem ao sair da tela. Conecte o sinal screen_exited()
(saiu da tela) do nó VisibilityNotifier2D
e adicione este código:
func _on_VisibilityNotifier2D_screen_exited():
queue_free()
public void OnVisibilityNotifier2DScreenExited()
{
QueueFree();
}
// This code goes in `mob.cpp`.
void Mob::_on_VisibilityNotifier2D_screen_exited() {
queue_free();
}
Isto completa a cena Turba.
Com o jogador e os inimigos prontos, na próxima parte os juntaremos em uma nova cena. Faremos inimigos aparecerem aleatoriamente na área do jogo, moverem-se adiante, tornando nosso projeto um jogo de fato.