GameMaker Studio 2 – Slope Tiles for a Platformer

▶ Source code & project base:
▶ Support my work:

Build a pixel perfect platformer using tile collision which handles arbitrary slopes. All in GameMaker Studio 2. Time to move on from slow and messy object based collision!

My previous video on tiled collision:

Due to the use of tilemaps this method doesn’t apply to GameMaker Studio 1.x. You could still accomplish something like this in 1.x but you would have to build your own tile system likely using ds_grids, etc.

A lot of this was based on Mike Dailly’s method for generating a height table:


Xem thêm bài viết khác:

Article Categories:


  • I'm just using the code for moving using only integers, but I'm having a problem. It works fine until the gravity variable I have is a fraction; the integer movement code for the vspeed somehow doesn't account for the gravity with a fraction.
    my code:

    grav = 0.5

    //Check for ground
    if (place_meeting(x, y+1, obj_solid))
    if (keyboard_check_pressed(vk_space))
    vspd = -jspd;
    } else{
    if (vspd) < (termgrav)
    vspd += grav;

    //Integer movement
    vspd += vspdr
    vspdr = vspd -floor(abs(vspd)) * vspd
    vspd -= vspdr

    Also with the termgrav variable(terminal velocity for gravity), if its value is higher than grav, the player object just bounces up and down non stop. Any suggestions?

    Damian July 1, 2020 9:31 am Reply
  • I have a question. I've been trying to figure this out for a while now. I have my jump animation split into jump and fall. I also have the fall animation set to play when the player is not grounded and vsp > 0. However when i use your method for tile collision and slopes, the animation will play for fall when walking down slopes because the vsp changes in order to keep the player on the ground. If i removed the grounded check for the fall animation, when the player walks off a ledge, it will remain as the run animation and not change to the fall animation like how i want it to. Do you have any suggestions on how i can check if the player is falling off a ledge so the fall animation will play and not when walking down a slope?

    Jayson R July 1, 2020 9:31 am Reply
  • Want to add the effect of gravity when going up a slope? Here is my somewhat hacky code addition, which you should put just before the x += hsp; in the horizontal collision detection bit. Bear in mind that you need to manually provide the tile index numbers for the slopes you want to apply the effects of gravity to. You can change the effects for steeper slopes. You don't really need to change it for going down a slope as you appear to speed up anyway.

    In my example, tiles 2 and 3 in my tilemap are a one tile wide slope (45 degrees), whereas tiles 8 & 9 and 10 & 11 are paired steeper ones that are two tiles high (a mountainous 64 degrees).

    var floordist = InFloor(tilemap,x, bbox_bottom+vsp);
    if (floordist <= 0)
    if (p2 = 0 and !key_jump)
    var _id;
    var _x = tilemap_get_cell_x_at_pixel(tilemap,x,bbox_bottom+1);
    var _y = tilemap_get_cell_y_at_pixel(tilemap,x,bbox_bottom+1);
    var data = tilemap_get(tilemap,_x,_y);
    _id = tile_get_index(data);

    if (_id == 2 or _id == 3) hsp = hsp * SPD_GRAVITY;
    if (_id == 8 or _id == 9 or _id == 10 or _id == 11) hsp = hsp * (SPD_GRAVITY/1.5);

    LeaderOfTheStarrySky July 1, 2020 9:31 am Reply
  • Don't make the same mistake I did and set your first tile (after the blank) to be be anything other than the SOLID BLOCK!!!. The sloping tiles mostly worked, but the solid box collision didn't properly, and my character kept spazzing out when I walked into one from the side or jumped up and hit one underneath.

    I thought there was something wrong with my code and checked and rechecked it multiple times, or something wrong with the size of the tileset I had chosen (64 pixels). I spent half a day trying to sort it out, and only rewatching the video from the start and not skipping the bit about making your tileset sprite made me realise where I had gone wrong! Doh!

    LeaderOfTheStarrySky July 1, 2020 9:31 am Reply
  • has anybody used this to make top down slopes i'm not sure how i can do it but it would help me alot!

    DarkBehindFlat July 1, 2020 9:31 am Reply
  • why is it slow when i restart? It's a 3 second wait.

    DarkBehindFlat July 1, 2020 9:31 am Reply
  • Shaun IDK what you got in your pocket, but if you can make this code work with flipped slopes I'd love ya forever! lol

    Jake Hopper July 1, 2020 9:31 am Reply
  • I have this problem where near the end pixels of each slope tile, there is an invisible spot that i can land onto when falling down. It sets my vsp to 0, but doesn't register as solid ground as there's nothing there. What do I do to fix this issue?

    Houston Cancer July 1, 2020 9:31 am Reply
  • There is a problem with this system.

    It somehow messes up the viewports of the rooms after the init room.

    You'll always have a weird 4:3 like view even if you set the viewport of the following rooms to a 16:9 ratio.

    I have no idea what causes this (probably the draw surface application) and no solution.

    Can somebody please help?

    RyuBlade July 1, 2020 9:31 am Reply
  • how can I get the angle of a slope?

    BadComic July 1, 2020 9:31 am Reply
  • hey, Shaun recently got the tutorial off your Patreon. I realize that the code works for player obj sprite that is size 32 but breaks if larger. A solution for this is just having a tilemap as large as your player sprite. But there is a bug where the player sprite will "twitch" be placed above the tile map when on a flat surface if you could write back with a solution involving code it would be much appreciated

    Brian Jarema July 1, 2020 9:31 am Reply
  • bruh I'm trying to do a similar "in_ceiling" that returns positive numbers if you are too far into the ceiling instead, and my math brain is a slow moving pile of goo. Even with your example to use as a mirror it took me like 2 hours to come up with

    theceiling = global.tiles_ceiling_heights[(argument1 mod GRID) + (the_tile * GRID)];

    return theceiling – ( argument2 mod GRID ) ;

    and for empty tiles:

    return -( argument2 mod GRID ) – 1;

    and I snuck in another while loop for a "ceilings" height map in the draw of that init room

    var check_ceiling = GRID – 1 ;
    while (check_ceiling >= 0){

    global.tiles_ceiling_heights[i] = check_ceiling;

    var getpixel = surface_getpixel(application_surface, i, check_ceiling);

    if (getpixel == COLLISION_BLUE ){





    wish me luck on actually doing something with these values lol
    – no more modulo magic to snap my guy to the grid, back to pixel-pushy loops with in_floor() and in_ceiling() checks

    TheOnePabb July 1, 2020 9:31 am Reply
  • I honestly don't understand why gravity, walk speed, and jump speed are macros. Especially if you were to try to use this as a more universal collision code…

    Velen Zaiga July 1, 2020 9:31 am Reply
  • So I’m in a rough spot here. I followed your code exactly and checked for errors and fixed any mistakes I made, but no matter, my character seems to fly vertically upwards. Weirdly enough, when I decided to set my GRAVITY variable to 10 (I originally had it at 0.4) my character tends to float in the middle of the air. Then, I added draw-text functions so I could see what my character’s “vsp” was, and the vsp read “0”; this happens no matter if the gravity was 10 or 0.4. Would anyone care to suggest what might be the problem? Thanks.

    BSG’s Music July 1, 2020 9:31 am Reply
  • "tilemap element corrupted" people look here
    TLDR: set your tileset resource's "borders" to 0

    It seems that all asset functions related to sprites get messed up if that sprite is associated with a tileset, and that tileset has "borders" defined. I think it actually affects the sprite resource, like, chops it into subimages and whatnot

    So I had a tileset of 24×24 tiles with a (default?) border of 2px
    – first it would throw an error about my created tileset being corrupt. Eventually I found out that heights_to_get was incorrect and then dividing it by the grid size produced a non-integer which would mess up the new layer creation process
    – the sprite_get_width function only returned 20 when targeting the sprite resource behind the tileset (which would line up with that 2px border, times two, on a single 24px tile of my 192px sprite)
    – the asset_get_index and asset_get_type functions would suddenly start returning -1 when targeting the sprite resource behind the tileset
    – this, of course, messed up everything in this tutorial unless I manually entered the width as a magic number at the start
    – as soon as I found and set this border to 0 everything started working normally

    TheOnePabb July 1, 2020 9:31 am Reply
  • how do i make tile collision and slopes work if the player is 32×32 while the tiles are 16×16? furthermore how can i design it to be functional with obj wall collision?

    Sheep Lavender July 1, 2020 9:31 am Reply
  • Does it matter what size the tile is? Or does it have to be a specific width and height?

    Insight Games July 1, 2020 9:31 am Reply
  • Hi Shaun, thanks for making this tutorial. I am implementing your code into my own project. Everything is fine except the vsp += SPD_GRAVITY is making my player jump uncontrollably by itself. I've double checked my codes and all seems to be correct. I even downloaded your project file and copied my codes into your file but there seems to be no error in your file. I did same (copied the codes and settings from your project file into my own project) but the problem still persist. I'm not sure where to look at anymore. The jumping stops when I disable the Vertical Collision code but it causes the going up the stairs to be buggy (it can't take the first step up smoothly). Do you know what could be the issue or what am I overlooking that could cause this problem? Thanks.

    Monica Theseira July 1, 2020 9:31 am Reply
  • _________________________________________

    draw_tilemap() – tilemap element corrupted i get that error then testing the game. is it not creating the layer "Tiles" in oInit?

    AncientArts July 1, 2020 9:31 am Reply
  • This is really cool! Something to watch out for is, when I implemented this code into a different project, having Viewports enabled in the "init" room messed up how the slope collisions worked. I assume it has something to do with the surface_getpixel function and how the size of the application surface changes? I disabled Viewports in r_init and it fixed the issue.

    Atma505 July 1, 2020 9:31 am Reply
  • In the section at around 4:00 you have the hspdfraction = hsp – (floor(abs(hsp)) * sign(hspd)); why did you do that instead of hspfraction = hsp – floor(hsp);?

    Miss Gnomer July 1, 2020 9:31 am Reply
  • Lol i saw like it was 50 minutes and i just bought the code instead lol
    i regret it, just corrupted all my game

    Linkselott July 1, 2020 9:31 am Reply
  • Hi , this video is old I know, but if anyone can help I'll very glad. So I wrote and checked all codes but I can't find where I made the mistake, when move to right and up, player go for down, and when move to left and down, player to go for come up. Anyone have a idea how to fix it?

    Dandy July 1, 2020 9:31 am Reply

Leave a Comment

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