Making a retro platformer with Game Maker and Super State Engine part 1‌

Disclaimer: This tutorial series is using my Super State Engine Framework which is sold on my itch io page. This Framework has tons of tools to help build platformer games specifically but can also be used for other kind of games. The State object in particular is very useful to manage animations and writing sequence of actions to make, for example, writing cutscenes easier.

Creating a new project

  • Create a new blank project in Game Maker.
  • Click Tools > Import Local Package
  • Select the latest SuperStateEngine package, click “Add All” then “Import”

You now have a new project with all files from Super State Engine. In some case you might not need the whole framework but for the purpose of this project, we’ll import it all as most of it will be necessary. Next we start setting things up.

  • Go in the “Rooms” folder and delete the default “Room1” file
  • In the “Room Order“, make sure the “launcher” room is at the very top
  • Open the “Game Options” panel (the little gear icon)
  • Go to “Main Options > General” and activate Collision Compatibility Mode

Create the hero

If you test the project now, you get a working level with the default “Jack” character. Now let’s change things up a bit.

  • Take the image file “spritesheet_megawoman_strip58.png” and drop it into your project
  • Open the created sprite and remove “_strip58” at the end of the name or rename it to your liking
  • Set the origin to “middle center”
  • Set the Fps to 12
  • Set the collision mask to these values
    • Left : 8
    • Right : 23
    • Top : 3
    • Bottom : 29

This should look like the image below. Since the file has “_strip58” at the end of it’s name, Game Maker automatically spliced the image into animation frames, which is a very handy trick!

Now that the sprite is ready, we will create a new “hero” object.

  • Create a new Object (either click the (+) at the top of the Asset Browser or do a Right-Click > Create > Object
  • Open the new created object
  • Change its name to “o_megawoman”
  • Set the sprite to be “spritesheet_megawoman”
  • Open the “Parent” panel and set the Parent to “o_hero”
  • Make this object “Persistent”

We now have a new “hero” object. We’ll add it to our game.

  • Open the Room “rm_level_launch”
  • Delete the object “o_jack” (the default hero object)
  • Drop your new “o_megawoman” object in the room

The new hero object “o_megawoman” is now correctly placed in the game but it does not have any set behavior so it can’t be controlled. We’ll get to that right away!

Coding Mega Woman’s behavior

That’s when we really get into Super State Engine’s features! We’ll start by setting up some animations in the Create event and then code the hero’s behavior in the Step event.

Setting up some animations

  • Open the “o_megawoman” object
  • Right-click the Create event and select “Inherit Event”
  • Under the “event_inherited();” call, write these lines:
create_anim("idle",0,5);
create_anim("slide",7);
create_anim("walk",8,13);
create_anim("jump",14);
create_anim("hurt",44);

create_anim() function explained

The create_anim function (which can be used with any child of the o_state_object) creates a new anim, gives it a name that is used to reference it and defines which frames of the set sprite it uses.

Let’s look at the “walk” animation we set up above:

create_anim("walk",8,13);

To use the walk animation, you would call it with either

play("walk"); or state_play("walk");

The animation will run from frame 8 to frame 13. You can go into the object’s sprite sheet to look those frames to get an idea of how it works.

If you only set one frame value, the animation will be static (single frame). If you set two frame values, it will run animation out of all the frames between and including those values.

There are more values you can pass to the create_anim function. The fourth value is “loop” and is expecting a Boolean. By default it is set to true, which makes the animation run in a loop indefinitely. If you set it to false, the animation will stop at the last frame.

The fifth passed value is the playing speed. By default it is set to 1. Increase this if you want the animation to play faster than the set framerate of the sprite, or decrease it to have it play slower. Play around with it to see how it works.

Mega Woman’s behavior

  • In the object “o_mega_woman”, right-click the Step Event and select “Inherit Event
  • Open the Step event and after the event_inherited() call, write this:
if(do_step)
{
    switch state
    {

    }
}

The “do_step” value is managed in every State object’s Begin Step event and is used for pausing / unpausing the game. We don’t have to worry about that for now.

State objects have a “state” value keeping track of which state they are in. This value accepts any number but is typically used with the enum STATES.

Let’s write our hero’s first state by adding the code below in the switch block. We’ll start with basic movement:

case STATES.NORMAL:
    hsp = (input.right - input.left) * spd;
    if(hsp != 0)
        hdir = sign(hsp);
    break;

Explanations

  • hsp = horizontal speed. We check left and right input with the input object and multiply it by the object’s speed
  • hdir = horizontal direction. If an input is given (hsp != 0), we set the hdir to either -1 (left) or 1 (right)
  • break. Marks the end of a case block in a switch statement.

Mega Woman can now go left and right when pressing the arrow keys and she turns to face the direction she’s going in.

Adding jumping

Add the part in bold below into your STATES.NORMAL block:

case STATES.NORMAL:
    hsp = (input.right - input.left) * spd;
    if(hsp != 0)
        hdir = sign(hsp);

    // CONTROLS JUMP
    if((blocked_down || coyote > 0) && input.A_pressed)
        vsp = -jump_spd;

    // INTERRUPT JUMP
    if(vsp < 0 && !input.A)
        vsp = 0;

    break;

Explanations

The first part checks if the hero is on the ground (blocked_down) or if the coyote value is above 0 (This basically implements coyote time, which means the hero can still jump a short time after he’s fallen off a cliff).

If either of those are true, pressing the A key will set the vsp (vertical speed) to the negative value of the jump_spd.

Values like spd, jump_spd and coyote time can be customized in the Variable Definitions panel of your object.

There are many values than can be customized in this panel. Look at the “Super State Engine Documentation.pdf” document for more details.

The second part interrupts the jump mid-air. If the vsp is negative (meaning the object is going up), releasing the A key will instantly set the vsp to 0, essentially stopping it from going higher and letting it fall back with gravity.

Linking this to our animations

So now our hero can move and jump but doesn’t play the animations we’ve set up previously. Let’s fix that by adding this code under the jumping parts:

// MANAGE ANIMATIONS
if(blocked_down)
{
    if(hsp == 0) play("idle");
    else         play("walk");
}
else
{
    play("jump");
}

Explanations

If the hero is standing on something (blocked_down), she will either play her “idle” animation or her “walk” animation depending on her horizontal speed. Otherwise she will use her “jump” animation.

Conclusion

Now Mega Woman can run and jump, look in the direction she’s going and play the appropriate animations for these actions. Her Step event should look like this:

event_inherited();

if(do_step)
{
    switch state
    {
        case STATES.NORMAL:
	    hsp = (input.right - input.left) * spd;
	    if(hsp != 0)
	    hdir = sign(hsp);
			
 	    // CONTROLS JUMP
	    if((blocked_down || coyote > 0) && input.A_pressed)
	        vsp = -jump_spd;
			
	    // INTERUPT JUMP
	    if(vsp < 0 && !input.A)
	        vsp = 0;
			
			
	    // MANAGE ANIMATIONS
	    if(blocked_down)
	    {
	        if(hsp == 0)	play("idle");
		else		play("walk");
	    }
	    else
	    {
		play("jump");
	    }
			
	    break;
    }
}

In part 2 of this series, we’ll add shooting bullets!

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *