Basic Platformer Mechanics in GameMaker: Studio
I’m fond of platformers. It’s only natural that I spent the past year studying and refining platformer engines for GameMaker: Studio. Here’s what I actually use for my engine.

The following code is adapted from Zack Bell’s platformer code (from his article Understanding Collisions pt.2). Once you grasp the basics, you can edit the code to adapt to your specific needs. That’s what I’ve dove.
UPDATE: Please take a look at this other, optimized code. I’ve rewritten it and make some speed tests. It’s 2.8x more efficient than the code below. Enjoy!
Don’t use GameMaker’s internal variables.
For speeds (vertical and horizontal) I never use the internal variables (e.g. hspeed, vspeed, speed, direction, gravity and so on); there’s only so much control you can have over those variables and how they interact with your objects… sooner or later you’ll find yourself with no idea of what’s going on in your game.
I prefer to directly manipulate the X and Y coordinates of my objects, so I usually implement my own speed variables.
Platformer Initialization Script
The following script is executed once, in the create event by those objects that need to move. Everything that moves (e.g. in my game that would be the Player, the broken pieces of pots and crate boxes, bombs, collectible items…) must initialize some variables that will be used in lieu of GM internal ones.
This is a stripped down version of what I’m using since I’ve customized mine heavily (with sprite management stuff we don’t need for movement)
///scr_platformer_init() // This script is called in the create event of moving objects // Initialize the variables used for movement code xVel = 0 // X Velocity yVel = 0 // Y Velocity xVelSub = 0 // X Sub-pixel movement yVelSub = 0 // Y Sub-pixel movement // Previous X/Y coords to use as we see fit xprev = 0 // Previous X ausiliary var yprev = 0 // Previous Y ausiliary var
We might need to use our own variables for the previous X and Y positions as well. That’s why I define my own xprev and yprev as well.
Movement Code
This is the actual movement code that must be placed in the step event after you have modified the xVel and yVel as you see fit for you objects (like player input, jumps, falling mechanics and so on)
///scr_move()
xprev = x
yprev = y
// Handle sub-pixel movement
xVelSub += xVel
yVelSub += yVel
var xVelNew = round(xVelSub);
var yVelNew = round(yVelSub);
xVelSub -= xVelNew
yVelSub -= yVelNew
// Speed Directions
var xdir = sign(xVelNew)
var ydir = sign(yVelNew)
// Vertical Movement
repeat(abs(yVelNew))
{
if place_meeting(x, y + ydir, obj_solid)
{
yVel = 0
break
}
else
{
y += ydir
}
}
// Horizontal Movement
repeat(abs(xVelNew))
{
if place_meeting(x + xdir, y, obj_solid)
{
xVel = 0
break
}
else
{
x += xdir
}
}
As you can see this looks terribly similar to Zack Bell’s code. What I use now is quite customized in the collision check part. I’m not using a single place_meeting anymore. Instead I use multiple line_collision with different objects based on the direction I’m actually headed.
My code looks more like this one, indeed…
///scr_move()
xprev = x
yprev = y
// Handle sub-pixel movement
xVelSub += xVel
yVelSub += yVel
var xVelNew = round(xVelSub);
var yVelNew = round(yVelSub);
xVelSub -= xVelNew
yVelSub -= yVelNew
if ((xVelNew == 0) && (yVelNew == 0))
exit
// Speed Directions
var xdir = sign(xVelNew)
var ydir = sign(yVelNew)
// Vertical Movement
repeat(abs(yVelNew))
{
if ydir == 1
var coll = is_on_ground()
else
var coll = collision_line(bbox_left, bbox_top - 1, bbox_right, bbox_top - 1, obj_solid, false, true)
if coll
{
yVel = 0
break
}
else
{
y += ydir
}
}
// Horizontal Movement
repeat(abs(xVelNew))
{
if collision_rectangle(bbox_left + xdir, bbox_bottom, bbox_right + xdir, bbox_top, obj_solid, false, true) ||
collision_rectangle(bbox_left + xdir, bbox_bottom, bbox_right + xdir, bbox_top, obj_crate_solid, false, true)
{
xVel = 0
break
}
else
{
x += xdir
}
}
And the is_on_ground script looks like this one
///is_on_ground()
// Check For Solid Ground
var on_ground = collision_line(bbox_left, bbox_bottom + 1, bbox_right, bbox_bottom + 1, obj_solid, false, true)
if on_ground
return on_ground
// Check for Crate Object
var on_crate = collision_line(bbox_left, bbox_bottom + 1, bbox_right, bbox_bottom + 1, obj_crate_solid, false, true)
if on_crate
return on_crate
// Check For One Way Platform
var on_one_way_platforms = collision_line(bbox_left, bbox_bottom + 1, bbox_right, bbox_bottom + 1, obj_one_way_platform, false, true)
if on_one_way_platforms
return on_one_way_platforms
// Check for Moving Platforms
var on_moving_platform = collision_line(bbox_left, bbox_bottom + 1, bbox_right, bbox_bottom + 1, obj_platform_moving, false, true)
if on_moving_platform
return on_moving_platform
return false
You’ll notice this is called only if the object is actually moving down in the scr_move script.
Slopes & Moving Platforms
I will be talking about slopes and moving platforms in the next article. You can check Zack’s code in the meantime. The basic concept for slopes is there but beware that for moving platforms I’m using a totally different solution.
That’s all folks
Anyway this is the basic of my platformer engine. Every moving object may execute a custom variation of the previous scripts.
The logic behind it, is the same. Round the speeds while keeping track of the sub-pixel values, move 1px in the direction of the speed for as many times as the value of the speed until we collide with something.

About the xprev and yprev.
I might use the xprev and yprev as I see fit for my particular objects. Sometimes I need to know their positions before moving them at all (hence their values get refreshed before the repeat-loops). Sometimes I might need to store those values elsewhere along the execution of the movement code. Those are just values I keep around “just in case”.
I found it very interesting how the heart animation happens in your hud. Would you be able to teach me or give me a clue on how to get to this incredible result?