Game Maker For Beginners: Part II
Main Topics: Inheritance, Object InteractionLevel: Total newb to Game Maker. Suitable for programming nubs, also.
Abstract: We're going to make a simple, one-level side-scrolling shoot 'em up using Game Maker and GML. In this second part, we're going to make some enemies and let you shoot at them!IntroductionIn the
last tutorial we made some sprites, and we made some objects. Now it's time to have them interact. And by interact, I mean explode.
Create PlayerShot and EnemyBasic ObjectsWe're going to make a shot object (for the player to fire) and a basic enemy object (which we'll call "oEnemyBasic"). To do this, we'll make two sprites and then attach them to new objects.
For the enemy, though, we're going to do something a little bit different: we're going to make it an animated sprite, with four frames. To do this, you can add some empty frames (Edit -> Add Empty), or simply copy-and-paste the first frame. I'm going to make mine a little rotatey thingy.

By default, sprite animations will loop indefinitely. You can preview the animation at various speeds in the Sprite Editor. However, you have to set the in-game speed of the sprite in the actual object (see below).
InheritanceOne of the nice features of Game Maker is
inheritance. This is actually a very important concept in object-oriented programming, so you should understand it. The idea is that objects can inherit traits from other objects.

In our shoot 'em up, we know we'll be blasting all kinds of enemies... some will fly right at us, some will follow a pattern, and some will simply sit there and shoot at us. But they all have at least two things in common: 1. we can blow the crap out of them, and 2. they can blow the crap out of us.
Without inheritance, we'd have to redefine the same shared variables over and over again, and if we wanted to make a change to all the enemies, we'd have to do it once for every enemy object we had. And if, for example, we wanted to test the player's collision against an enemy, we'd have to do that multiple times, too.
Instead, let's make an oEnemy object from which all our enemies will inherit. This object is called the
parent, and the objects that inherit from it are called its
children. oEnemy will house all the variables are shared by every enemy. If we want to do some kind of test against all enemies, we can write one test, against oEnemy, as opposed to one for each enemy type.
You will probably never use an instance of oEnemy in the game, only its children. It's just a "base" object that defines a type of object.
Let's start by giving oEnemy a single variable "hp = 1." So by default, all enemies will take one damage before exploding. That's all we need for now.

Now we'll open up our oEnemyBasic object. On the left-hand side, you can see a "Parent" drop-down menu. Set this to "oEnemy." oEnemyBasic is now the child of oEnemy. By default, it will also have the variable "hp = 1."
You can define a variable in a child object that is already defined in its parent. Whichever definition comes last will take precedent (see below).
If you drop an enemy into the room and run the game, you'll notice the animation is going really fast. To change the animation speed, you have to set the variable image_speed (preferably in the Create Event). The default is 1, which is 1 frame per step. For something more reasonable, try 0.4.
TAKE NOTE! If you add an event to a child object, it will overwrite the same event of the parent! To also run the parent's event, use the "control -> Call Inherited Event" action (

), which should proceed the child's code.
Let the Player ShootAlright, we have our enemy (which currently just sits there), so now our guy needs to be able to shoot. First, let's make the shot move. In oPlayerShot:
xVel = 8;
x += xVel;
That will add "xVel" (x velocity) to the shot's x position every step. And since we defined xVel as 8, it will move 8 pixels every step.
Now let's make it so that when you press the "X" key, your ship fires a bullet. Add this code to the Step Event of your oPlayerShip:
if (keyboard_check(ord('X')))
{
instance_create(x, y, oPlayerShot1);
}
Some new bits of syntax here
ord - to check for any of the letter (A-Z) or digit (0-9) keys, use the "ord" function. This evaluates to a number that represents the key. For special keys, like the arrow keys, there are "constant" (unchangeable) variables defined for them, like
vk_up,
vk_down, etc.
instance_create(xpos, ypos, object) - this is a very useful function! As the name implies, it creates an instance of the given object at the given position.
Be aware of the "origin" of your sprites, which you can change in the sprite editor. This is the point of reference for the objects, and corresponds to (x,y). By default, the origin is the upper-leftmost corner of the sprite, but it makes sense conceptually to set this to center for certain objects, like projectiles.
Let's test out our code...
holy crap!
It's like a machine gun. That's because Game Maker is checking if "X" is pressed EVERY STEP, and creating a shot if it is. There are a couple of ways to fix this:
1. Add a firing delayIn a lot of old shoot 'em ups, you can hold down the button to shoot at a steady rate, or you can tap the button to shoot faster. We can emulate that with this code:
firingDelay = 0;
firingDelayMax = 10;
if (keyboard_check(ord('X')))
{
if (firingDelay > 0)
{
firingDelay -= 1;
}
else
{
instance_create(x, y, oPlayerShot1);
firingDelay = firingDelayMax;
}
}
else
{
firingDelay = 0;
}
Try to make sense of it - we've added a firingDelay variable that ticks down while the key is pressed. And when you let go of the key, it sets the delay to 0 so that as soon as you tap the key again, you fire off a shot.
2. Only fire a shot when the key is first pressedThe easiest way to do this is to use Game Maker's Key Press event (

), which activates when the key is first pressed down.
Let's stick with the first solution, though! Test it out and make sure it looks right!
Make the Enemy Blow UpAlright, it's time for the money shot. KABLAM! First, let's make an explosion object. You know the drill - create a sprite, then create an object. As with any animated object, you'll probably want to set the image_speed to something less than 1.

One new event we'll want to use is the "Animation End" event, which is found in the "Other" group in the Event Selector. This event is called when the current animation ends. We want to destroy the explosion object after it's finished playing its animation (otherwise it will sit on the screen and loop).
To do this, we invoke the
instance_destroy() function. It takes no arguments.
Now that we've got a shot, that shoots, and an explosion, it's time for kablooie! To do make this happen, we're going to use a Collision event. Specifically, we're going to check when oShot collides with oEnemy (remember, we want to check against the base enemy object!).
Once this collision happens, we'll do two things: 1. we'll subtract 1 from the enemy's hp, and 2. we'll destroy the shot. The code looks like this:
other.hp -= 1;
instance_destroy();
other is a special variable which represents the other instance in the event. In this case, it represents oEnemy. There's also
self (oPlayerShot in this event), and
global (used for global variables who's scope crosses all objects and rooms). We'll talk about
global more later, since that's a useful one.
By using the "." notation we can set the variable of another instance. It's quite handy, as you can see.
Finally, oEnemyFlyer should do a check (in the Step event) for when its hp is less than 1. When this happens, it should create an explosion and then destroy itself:
if (hp < 1)
{
instance_create(other.x, other.y, oExplosion);
instance_destroy();
}
Create and then destroy - it's the circle of life! Lookin' good! Now can you make the enemies do damage to you when they touch you?
[Download the Source for this Tutorial]Next Up: We'll build the level, and make the screen scroll!
[link]