GameMaker Studio 2 - Slope Tiles for a Platformer -

GameMaker Studio 2 – Slope Tiles for a Platformer

Shaun Spalding
Views: 57002
Like: 915
▶ 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:


  1. Does not work in version 2.2.1 287. Does not jump or collide with slope tiles.

  2. Is this compatible with the platformer tutorial you made for gms2?

  3. I using a view of 640×360 and I am resizing application surface to have smooth animations etc to 1920×1080, but when I do these collisions wont work, any solutions?

  4. I would be very interested in what you stated this tutorial does not cover certain types of slope. Please point to a video where that is covered in more detail. I love your work by the way You're awesome.

  5. I tried changing the size of the camera to 384 x 216 and the viewport to 1920 x 1080 (I changed them for both the init room and room0), but now the collisions are all messed up. How can I fix this?

  6. iIf I pay for the final version, do you give me permission to use it in my game?

  7. 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?

  8. Lol i saw like it was 50 minutes and i just bought the code instead lol
    i regret it, just corrupted all my game

  9. 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);?

  10. 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.

  11. _________________________________________

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

  12. 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.

  13. Does it matter what size the tile is? Or does it have to be a specific width and height?

  14. 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?

  15. "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

  16. 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.

  17. 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…

  18. 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

  19. 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

  20. 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?

  21. 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

  22. why is it slow when i restart? It's a 3 second wait.

  23. has anybody used this to make top down slopes i'm not sure how i can do it but it would help me alot!

  24. 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!

  25. 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);

  26. 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?

  27. 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?

  28. So if i had a tileset the wasnt just a row of tiles would i have to put in oinit's create_event

    tileset_height = sprite_get_height(scol)
    tiles_height = tileset_height/TILE_SIZE

    for (var i = 0; i<= tiles; i++) { tilemap_set(tilemapid,i,i,tiles_height) }


  29. Does anyone know why this code doesn't like it when you change the application surface?

  30. Or just do it once on your own then hardcode the numbers in an array and be done with it. Why do it every time?

  31. Hey Shaun! I am trying to use this example for the GMS 2.3 and it seems the slopes don't work at all. they just move the player instantly above the top boundary instead of moving along the ramp. I followed exactly how the tutorial does it and i even bought your example on your patreon site following that. I dunno why it would cause this and Im using 128 grid for this one since my tiles are 128 size along the grid (made the correct modifications for this). If you could help me find out what went wrong, please contact me in I will appreciate the help a lot, Thanks!

  32. The problem with this is that the players x position only moves once hsp = an integer so fractions dont actually affect the player it only stops the players movement for a few fames until hsp is an integer. How can i fix this shaun? This makes the players movement feel stuck when you add acceleration.

  33. Nice tutorial !
    It works fine with 32×32 tiles but I have a problem if I want to use 16×16 tiles with the player's 32×32 sprite. My player object bounces :/
    What change do I need to make to make this work ?

  34. 17:00 you can save global.heights on txt file then load on initial..

  35. i have tons of bugs using this code on v2.3.1

  36. Works fine with slope rising from left to right but not the opposite.
    Also i'm able to go through vertical walls and i'm getting gradually sent to the top of it.

  37. It bugs out if you use any shape but the one that comes with it.

  38. Took 2 years to notice, but at 29:11 you can see he changed bbox_side, p1, and p2 to temp variables. THAT IS WHY THEY ARE YELLOW FOR ONLY HALF OF THE VIDEO! All this time I just thought it was GML screwing up the color…

  39. trying to figure out how to mash this together using heartbeast tile collision

  40. On the vertical collision check, when i comment out the "if (vspd >= 0) y =y" and the else statement following that everything works. But when I enable it again the collisions start breaking and the player just falls through the map. I know that without it the player just starts bouncing, is there a way I can fix this? I think it's because my player's sprite is smaller than the tiles.

  41. Hey! At 19:20, the global.heights[i] assignment is performed inside the while loop. Isn't it more optimised to do it straight after the while loop? Then we only change a value in the array once! Besides, the only thing the while loop is doing is incrementing check until it reaches the value we want. So when the while loop is done, check will still be the value we want. ==> global.heights[i] outside of the while loop for performance gains! 😉

  42. Getting this error when I try to run the game at "42:39", any idea why?

    ERROR in

    action number 1

    of Create Event

    for object <undefined>:

    tilemap_get_at_pixel argument 1 incorrect type (undefined) expecting a Number (YYGI32)

    at gml_GlobalScript_InFloor (line 6) – var pos = tilemap_get_at_pixel(argument0, argument1, argument2)


    gml_GlobalScript_InFloor (line 6)

    Update: Got it working, see reply for answer.

  43. I bought this project base, but when I want to add new rooms and try the game it says "Error : Could not find any rooms in the project – could be caused by project file corruption (check for errors on project load)"
    It only works when the default room's name is "room0", even when I just rename this one, the error happens. If I add new rooms, as exemple room1, it is just not recognized and I get this message, I don't understand why.
    Is there a setting in the project that locked on purpose the possibility to add rooms?

  44. I faced such a problem. I don't understand how to solve: "Object: oInit Event: Create at line 3 : cannot use resource name "sCol" as it is not being exported


  45. Thank you Shaun, very helpful video! You mentioned ceiled slopes (metroid). Do you think it would be possible to achieve ceiled slopes with this system? Would you be able to hint, without the exact answer, where to begin or how to apply it in this project?

  46. Thanks for this magic tutorial, but I have a problem.

    I plan to put my textures on the tileset, but how do I make the tileset transparent?

    It's not like classic tiles

Leave a Reply

Your email address will not be published.