Creating the enemy
We’ll create a scene, which we can then instance to create any number of independent mobs in the game.
Click Scene -> New Scene and add the following nodes:
(named
Mob
)
Don’t forget to set the children so they can’t be selected, like you did with the Player scene.
In the RigidBody2D properties, set Gravity Scale
to 0
, so the mob will not fall downward. In addition, under the section, click the Mask
property and uncheck the first box. This will ensure the mobs do not collide with each other.
Adjust the “Speed (FPS)” to 3
for all animations.
Set the Playing
property in the Inspector to “On”.
We’ll select one of these animations randomly so that the mobs will have some variety.
Like the player images, these mob images need to be scaled down. Set the AnimatedSprite
‘s Scale
property to (0.75, 0.75)
.
As in the Player
scene, add a CapsuleShape2D
for the collision. To align the shape with the image, you’ll need to set the Rotation Degrees
property to 90
(under “Transform” in the Inspector).
Save the scene.
Enemy script
Add a script to the Mob
like this:
GDScript C#C++
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 <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
GDScript C#C++
public override void _Ready()
{
var animSprite = GetNode<AnimatedSprite>("AnimatedSprite");
animSprite.Playing = true;
string[] mobTypes = animSprite.Frames.GetAnimationNames();
animSprite.Animation = mobTypes[GD.Randi() % mobTypes.Length];
}
#include "mob.hpp"
#include <RandomNumberGenerator.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()]);
}
First, we get the list of animation names from the AnimatedSprite’s frames
property. This returns an Array containing all three animation names: ["walk", "swim", "fly"]
.
We then need to pick a random number between 0
and 2
to select one of these names from the list (array indices start at 0
). randi() % n
selects a random integer between 0
and n-1
.
Note
You must use randomize()
if you want your sequence of “random” numbers to be different every time you run the scene. We’re going to use randomize()
in our Main
scene, so we won’t need it here.
The last piece is to make the mobs delete themselves when they leave the screen. Connect the screen_exited()
signal of the VisibilityNotifier2D
node and add this code:
GDScript C#C++
public void OnVisibilityNotifier2DScreenExited()
{
QueueFree();
}
// This code goes in `mob.cpp`.
void Mob::_on_VisibilityNotifier2D_screen_exited() {
queue_free();
This completes the Mob scene.
With the player and enemies ready, in the next part, we’ll bring them together in a new scene. We’ll make enemies spawn randomly around the game board and move forward, turning our project into a playable game.