Space Rocks
Space Rocks
SHOOTER
Gurpreet S. Matharoo
03 November 2022
Beginner
o Complete Game
o Popular
Create your own version of Asteroids in GameMaker.
For this game, let's use the "Space Rocks" template. This gives you all the images for
this tutorial.
Enter a "Project Name", and hit "Let's Go!".
The Asset Browser on the right contains all your assets. You'll now see four Sprites,
which are images you can use in your game.
There’s “spr_player”, the ship you’ll fly, “spr_bullet”, which you’ll fire from your ship,
and two rocks, which you’ll destroy.
Your ship, rocks, and even the bullets you fire are created as objects. We’ll put these in
the “Objects” group in the Asset Browser, which is currently empty.
Create a new Object
Rename it to obj_player
Right-click on the “Objects” group, and select “Create -> Object”. Change its name from
“Object1” to “obj_player”.
Every object needs a sprite – otherwise how would you see it?
Click where it says “No Sprite”, and from under the “Sprites” group, select spr_player.
We need some more objects now. Just like you created obj_player, create three more
objects:
Double-click on it. The “Room Editor” will open, where you’ll build your level.
Before doing anything, I want to resize the room to make it a 1000x1000 square.
If you don't see these options, go into your Asset Browser and click on Room1. They
should be visible while the room is selected.
Look at the left panel in the Room Editor: there are two layers created by default,
“Instances” and “Background”.
1. Instances: This is an instance layer. Your objects go here, just like cereal goes into
a bowl.
2. Background: This is a background layer. Change the background colour or apply
an image.
Click on the “Instances” layer to select it – this is where your objects will go:
From the Asset Browser, drag obj_player and place it in the room.
Your player ship is in the room now, as an “instance” – you can place multiple
“instances” of any object in the room!
Do this with the rocks – drag obj_rock into the room multiple times, until you have
around six instances:
The stage is set for the play. We just need to teach the actors their roles.
If you run the game right now (press F5 or the “Play” button at the top) your game will
open, but it’ll be as still as a frozen lake at night.
Your objects are there, your room is there, but nothing is programmed to move or do
anything.
You might be asked to choose between GML Code and GML Visual.
Choose GML Code if you've done programming before, or GML Visual if you're new.
This tutorial will cover both options, so you can choose whichever option you prefer.
Make your choice, and enable “Don’t ask again for this project.”
An object has many events. Each event has its own unique time when it runs.
For example, you brush your teeth in the morning. Then you breathe pretty much all
day, every second.
If you were a GameMaker object, you would brush your teeth in the "Create" event, and
breathe in the "Step" event.
That's because the "Create" event is the first event to run for an instance, and it only
runs once. The "Step" event then runs all the time in every single frame while the
instance exists.
We’re going to program this “Step” event to move the ship, as it's a continuous thing
that must happen, akin to breathing.
If you’re using GML Visual, search for the relevant actions in the Toolbox, and drag
them into the event area:
If you’re using GML Code, simply write your code into the event window.
if keyboard_check(vk_up)
{
motion_add(image_angle, 0.1);
}
If you're holding the up arrow key, this adds motion to the instance, so it moves in a
particular direction.
In GML Visual, the second action is “attached” to the first action. The second action will
only run if the first action’s condition is true.
To attach “Add Motion” to “If Key Down”, drop it on the right edge of the conditional
action, as shown above.
That direction is the “image_angle” of the instance, which is where the ship is facing.
The amount of motion we’re adding is 0.1. You can change this to make your ship faster
or slower.
The ship is alive! It moves to the right, as that’s the default angle of an instance.
if keyboard_check(vk_left)
image_angle += 4;
}
if keyboard_check(vk_right)
{
image_angle -= 4;
}
The logic here is simple:
To solve this, we’ll make the ship “wrap” around the room: if it leaves through the top, it
comes back through the bottom.
move_wrap(true, true, 0)
Make sure to add it outside of any conditions.
This tells the ship to wrap around the room when it’s outside. Both horizontal and
vertical wrapping are enabled, and the wrap margin is set to 0.
The wrap margin controls how far outside the room the instance has to go before it
wraps. We’re not using it for now, but it will come in handy later.
Aaand the ship movement is done! You can now move, turn and wrap around the room.
That’s one step off our checklist. To the rocks: we’re coming!
When the bullet is outside the room, we’ll destroy it. This prevents a memory leak that
would happen if all the bullets you shot continued to exist forever.
if mouse_check_button_pressed(mb_left)
}
This checks if the left mouse button is “pressed”. This is different from checking if it’s
“held down”, as this only checks if you’ve just hit the button.
If you hit the left mouse button, it creates an instance of obj_bullet. Apart from the
object to create, it takes three other parameters:
You can now shoot! Thing is… the bullets don’t move at all.
HOW TO MOVE AN INSTANCE
CONSTANTLY
For the bullet, we’ll set its speed once it’s created. After that, it will continue to move
forever until it’s outside the room.
This event is the first to run in an instance, and only runs once. That’s why it’s called
“Create” because it runs as soon as the instance is created.
speed = 10;
direction = obj_player.image_angle;
We’re telling the bullet to move at a speed of 10 – that’s 10 pixels every frame. Change
this to make your bullet go faster or slower.
So that’s how fast your bullet moves, but where does it move?
In the Events window, click on “Add Event”. Hover over “Other” and select “Outside
Room”.
This event runs as soon as the instance has exited the room area. Add this here:
instance_destroy();
I think this explains itself… Here, the instance is destroyed, so it no longer exists in the
room.
Of course, the object itself continues to exist in the Asset Browser, and new instances
can be created from it at any time.
Woohoo! We can now shoot.
Double-click on obj_rock. Add the Create event, and add this there:
speed = 1;
direction = random(360);
image_angle = random(360);
First we’re setting the speed to 1. This is very low compared to the bullet’s speed of 10,
which is expected.
Then we’re setting the direction to random(360). This can be any random number from
0 to 360 (a full circle).
That sets the direction where the rock moves, but doesn’t rotate the sprite – so we also
apply a random number to image_angle.
The rocks are now moving! But there are two problems:
1. If a rock goes outside the room, it will be lost and never come back
2. The rocks look very still and boring
ROCK WRAPPING
In the same obj_rock object, add the Step event, and add this there:
image_angle += 1;
We enable wrapping for the rock, with a margin of 100. This means a rock will only wrap
around once it’s more than 100 pixels outside the room.
If you had used a margin of 0, you'd see the rock jump from one point to another on-
screen, but now it does that off-screen.
Finally, we’re adding 1 to the image_angle, so the rock continues to rotate constantly. It
just looks more realistic.
Now rocks also wrap around the room, and they rotate, giving the game a more space-y
feeling.
When they collide, we want to destroy both the bullet and the rock.
By now, you’re probably aware that an instance can be destroyed
with instance_destroy() (or “Destroy Instance”). But that’s not all.
Let’s program the collision between a bullet and a rock. We’ll do it from the perspective
of the rock, as that's the object that will be affected the most.
Open obj_rock. Click on “Add Event”, go under “Collision”, and select obj_bullet.
This event will run when the rock collides with a bullet.
Add this here:
instance_destroy(other);
effect_create_above(ef_explosion, x, y, 1, c_white);
direction = random(360);
1. It destroys the “other” instance, which is the bullet. GameMaker gives you
the other variable in a collision event, so you can modify the instance you collided
with.
2. In GML Visual, use the drop-down arrow to assign this action to the “Other”
instance, so the bullet is destroyed.
3. It creates an explosion effect at the rock’s location. Its size is medium (1) and its
colour is white.
4. It sets the direction to a random value. When the rock eventually becomes a small
rock, or respawns, it will move in a new direction.
The event isn’t finished yet, but you can see our logic working. You can shoot at a rock
and change its direction. A particle effect is also created.
To control the number of rocks in the room, we’ll only respawn a rock if there are less
than 12 rocks in the room. This will be done using a “comparison condition”.
if sprite_index == spr_rock_big
sprite_index = spr_rock_small;
instance_copy(true);
1. The first block checks if the rock is big, by checking its sprite.
If it’s big, it’s changed into a small rock, and the instance is then copied so we get
two small rocks.
2. The second block starts with “else”, so it only runs if the preceding condition is false
– meaning the rock is small.
It then checks if there are less than 12 rocks in the room, and if that's true, it
changes the rock into a big rock.
1. It also sets the rock's x (horizontal) position to -100 so the rock goes outside
the room and can re-enter.
3. The final block only runs if the both preceding conditions are false, meaning the
rock is small and there are already 12 or more rocks in the room.
You can now destroy rocks, which respawn, resulting in infinite gameplay.
When your ship runs into a rock, it should explode immediately, and the game should
restart after two seconds.
To restart the game after two seconds of the player losing, we’ll use “Alarms”.
In this event, let’s program what happens when the player collides with a rock:
effect_create_above(ef_firework, x, y, 1, c_white);
instance_destroy();
obj_game.alarm[0] = 120;
Add the actions, and apply “Set Alarm Countdown” to “obj_game”
GameMaker also has alarms. You can tell an Alarm event to run after a number of
frames. After that number of frames have passed, that event will run.
In the code above, we’re telling obj_game to run its first alarm (Alarm 0) after 120
frames (two seconds). In that event, we’ll restart the room.
Because we’re destroying the player instance. You can’t run alarms in an instance that
doesn’t exist.
Open obj_game. Click on “Add Event”, and add the “Alarm 0” event.
room_restart();
This will simply restart the room, so you can play again.
This is almost done – but for obj_game to work, it has to be in our room. Right now it’s
not!
Open Room1 from the Asset Browser. Select the “Instances” layer, and from the Asset
Browser, drag obj_game into the room.
Since it doesn’t have a sprite, it’ll appear with a question mark. You can place it
anywhere – its location doesn’t matter, only that it exists.
In the game, you can now hit a rock and lose! Two seconds after that and you can play
again.
We’ll create our own variable to store the score. That variable will appear on-screen.
When a rock is destroyed, we’ll add 50 to that variable, increasing the player’s score.
Open obj_game, and add the Create event. Add this there:
points = 0;
Before we program how the score changes, let’s draw it to the HUD.
Add the “Draw GUI” event to the obj_game object. Add this there:
We’re drawing the points value at 10, 10 on the HUD. You’ll see it if you run the game:
It’s stuck at 0 though. Let’s make it increase when you destroy a rock.
Open obj_rock, and open its existing Collision event with obj_bullet.
Add this there, outside of any conditions:
obj_game.points += 50;
Run the game, and you will see your score go up as you shoot away at rocks!
Tip: Did you use GML Visual to make your game? Try it with GML Code now.
You will get a better understanding of GML having used both Code and Visual.
Happy GameMaking!