In this tutorial, we'll add a new enemy to the Windy Woods template.
Create a new project using the Windy Woods template. You can choose either GML Code or GML Visual:
You can use your existing Windy Woods project if you already have one.
Importing a Local Package
This tutorial will use two new sprites, spr_enemy2_defeated and spr_enemy2_walk. You can either create your own sprites, or download our asset package.
To import this package, click on Tools and select “Import Local Package”.
Open the asset package you just downloaded.
Choose “Add All”, and click “Import”.
You now have all the assets you need for this tutorial!
Creating the Enemy
Our new enemy will be a brand new object.
Create an object and name it obj_enemy2.
I've put this new object under Objects -> Characters -> Enemies.
Assign the sprite spr_enemy2_walk, found under Sprites -> Enemy2.
Make this object a child of obj_enemy_parent.
It now has the base functionality of an enemy, like movement and interaction with the player.
Place it in the rm_lvl_1 room, in front of the player, for easy testing (you can move it somewhere else later).
How to Defeat Your New Enemy
If you run the game now, and jump on the new enemy, you'll see something weird: the player itself will be duplicated and defeated.
This is because the new enemy doesn’t have its own “defeated object”, which it spawns when it’s defeated. Currently, it's using the player’s defeated object.
To fix this, we'll copy the defeated object of the first enemy, and repurpose it for the new one.
Duplicate obj_enemy1_defeated and rename it to obj_enemy2_defeated (I just changed the number).
Change its sprite to spr_enemy2_defeated (found under Sprites -> Enemy2).
Let's tell our enemy object that it now has its own defeated object. It'll be excited!
Go into obj_enemy2.
Right click on obj_enemy2's Create event and choose “Inherit Event”.
By inheriting an event, you add more functionality to a child object than its parent has. The Create event is specifically used to set the variables of an object.
Add the following code after the event_inherited() line or Call Parent Event action, to set the defeated_object variable to obj_enemy2_defeated.
defeated_object = obj_enemy2_defeated;
Run the game, and you can defeat your new enemy now! What's left is to make it move by jumping, not walking, as we originally planned.
Adding New Enemy Behaviour
The enemy walks left or right by default. Let's change this.
You’ll now program this enemy to jump towards the player, and define how far and high it can jump.
Add the following code to the Create event of obj_enemy2.
vel_x = 0;
image_speed = 0;
alarm[0] = 30;
This sets the enemy's X velocity to 0, so it stops moving, and also stops its animation.
It then sets Alarm 0 to 30. This is 30 frames, or half a second, at 60 frames per second.
Once Alarm 0 reaches zero, the Alarm 0 event will run, and all the code in that event will run.
Where's the Alarm 0 event? Let's create it!
How to Create an Alarm in GameMaker
Add an Alarm 0 event:
Add the following code.
vel_y = -21;
var _jump_x = choose(-1, 1);
vel_x = _jump_x * 4;
alarm[0] = 60;
This event runs 30 frames after the enemy is created.
It sets the Y velocity of the enemy to -21, so it jumps up. You can change this value to make it jump higher or lower.
It randomly chooses either -1 or 1, and stores that value in jump_x. This means the enemy will either move left or right.
To achieve that, it sets the X velocity of the enemy to jump_x multiplied by 4. You can change 4 to something else to make it move faster or slower.
Finally, it sets Alarm 0 to 60, so the same event runs again after one second. This way, the enemy will keep jumping in a random direction.
You can change 60 to some other value to change how often the enemy jumps.
If you run the game now, you'll see the enemy jump! But there's a problem: it keeps moving even after it's touched the ground.
Stopping the Enemy
Let's check if the enemy is on the ground, and if it is, stop it.
Inherit the Begin Step event, and add the following code after the event_inherited() line or Call Parent Event action:
if (grounded)
{
vel_x = 0;
}
When the player is grounded, this will set its X velocity to 0. This stops the enemy when it touches the ground again.
Run the game, and you will have your jumping enemy!
Targeting the Player
This is great, but randomness doesn’t always result in a fun game.
Our new enemy should always jump toward the player, so its movement is predictable.
Add this at the start of the Alarm 0 event:
if (instance_exists(obj_player) == false) {
exit;
}
This code checks if an instance of obj_player exists in the room. If it doesn't, it exits the event, so you're not looking for an instance that doesn't exist.
The event already has a "Choose" action/function which selects a random direction for the enemy to move in.
Let's change it so it always follows the player.
Replace the “Choose” action or line of code in the Alarm 0 event with the following code (or the highlighted action below):
var _jump_x = sign(obj_player.x - x);
This code figures out whether the player is to the left or the right of the enemy by subtracting the enemy's x from the player's x. Remember, if the player doesn't exist, then this code will not run at all.
Run your game, and see the enemy jump toward you:
Now place more of these enemies throughout the level, for an increased challenge!
Modify the enemy further, and create new enemies for more challenge. Publish to GX.games and share with your friends and family.
Summary
Some key takeaways from this tutorial:
- Use inheritance to quickly and easily share code from parent to child.
- Right click an event and choose "Inherit Event" to add unique code to that event.
- Use alarms to handle recurring events.
- Use instance_exists or the If Instance Exists action to check whether or not an instance exists before referencing it so your game doesn't crash.
Build your game further with GameMaker tutorials.
Happy GameMaking!