The perfect top down collision system!

  • Object Based Collision System
  • Slide along ramps of any angle and any size!
  • 360 degree movement!
  • Slippery Corners
  • Move at virtually any speed
  • Movement and Collision 100% independent of controls!
  • Single Script implementation!

Example Project Includes

  • Example room with rotated, scaled rectangle collisions and custom shape collision blocks
  • 8 directional character
  • Basic  simple character motion example code
  • Advanced example with momentum & friction
  • Keyboard, D-Pad, and Analog Support
  • I mean... it's right up there.  Just play it.  It's pretty cool.

Are you working on a top down game?  Something like Binding of Isaac, Zelda, or Secret of Mana?  Do you want your character to slide along ramps and walls smoothly.  Do you want to use ANY movement speed; From 1, to 2.45, to 18, and even higher?  Do you want to use the same collision code for all characters (players, enemies, npcs, bosses)?

This is the system for you!

With a single script, you can move your character around your room with perfect world collision!  All you need to do is provide a direction to move and a speed to move at and you are done! 

The system is completely independent of controls!  If you are new to game maker or have done any research into basic collision detection, maybe this code looks familiar to you?

When you bind your world collision to your controls, you are very limited in what you can do.  What if you want to knock your player back from taking damage?  Now you have to write new collision code to handle moving without pressing any buttons!


How about this?

Call that in your step event  with your own direction, speed, and wall object parent, and your player will move and collide flawlessly!

Want to use tiles instead of objects?  Check out my devblog about converting the system to tiles!


Buy Now$3.99 USD or more

In order to download this script you must purchase it at or above the minimum price of $3.99 USD. You will get access to the following files:

TopDownMovementCollision2.yyz 317 kB
movement_and_collision.gml 2 kB
movement_and_collision_1_4.gml 1 kB

Development log


Log in with to leave a comment.

I'm struggling to implement this into an asteroid-like game that uses motion_add for movement based on image rotation/angle because the script's _mv_spd expects an integer but I add movement simultaneously to direction and speed. If I separate the values, then speed increases exponentially regardless of direction... but I only want +/- speed in the player object's direction of movement.

Any help would be greatly appreciated!

Ship Create


Ship Step Event

//Movement Script


//Add movement in direction

if (keyboard_check(vk_left) or keyboard_check(ord("A")))
sprite_index = spr_shipa;


if (keyboard_check(vk_right) or keyboard_check(ord("D")))
sprite_index = spr_shipd;


if (keyboard_check(vk_up) or keyboard_check(ord("W")))
sprite_index = spr_shipw;


if (keyboard_check(vk_up) or keyboard_check(ord("W")))
sprite_index = spr_shipw;


I don't see motion add in here, but essentially what you want to do is keep track of your horizontal speed and vertical speed separately.  And then use point_direction(0,0,hsp, vsp) to turn that into a direction, and point_distance(0,0,hsp,vsp) to turn it into a speed to pass to the script. I also recommend not using image_angle, as this will also rotate your collision mask which could cause problems.  Create a new variable to handle the display of a rotated sprite and draw the sprite in the draw event using draw_sprite_ext() with this new variable substituted for image_angle.  

I had a question regarding whether or not this was intended behavior? It seems as if the player collision mask overlaps the wall objects?

I wouldn't say it's "intended" behavior, but it is acceptable behavior.  The player would never see the mask, so they wouldn't know anything is wrong.  At most it would overlap by a pixel or two, and as long as it's not causing any shaking or jittering, it should be fine.

This essentially happens because we are using a larger app surface than our view, meaning that the difference between the coordinate positions of 4.0, 4.25, and 4.5 is actually visible.  So the player's y value is something like 4.25 which wouldn't fire off a "collision" (as place_meeting uses rounded values only) but we can still render the difference between 4.0 and 4.25 on screen.

Cool, appreciate the reply. I thought I was going crazy for a second, lol

Love the script but I have an issue now. I used to check "speed" for certain things (not set) but now none of that code works. Is there another way to check the player speed so I can fix this? Thanks

One way could be to do this:
pos = {x:x, y:y}
movement_and_collision(blah blah blah)
spd = point_distance(x,y,pos.x,pos.y)

Thanks! Everything working great :]

This is a tip for those who bought this awesome script. You can get more "slippery" effect by using a rounded collision mask and increasing _max_scan_angle.

does this include movement for going up and down sideways sets of stairs?

You can fake it with two ramps above and below each other like the angled path to the right in the demo.  Beyond that, no.

Hey pixelatedpope, Your script uses place_meeting ffunctions to check collisions or place_free+solid black box? I'd like to know that before buy. 


place_meeting.  It can also be converted to use tile collisions (there's a blog about it posted here)

Ohoho Nice! I can adapt it to a custom place_meeting function!

Thanks Pixelated!


I want to ask,
if your assets are on some license?
Or if i made game for sale, could i still use it
with no extra payment? 

Yup!  You can use them in any project: personal or commercial.  The only restriction is sort of the obvious one: don't buy the package and then turn around and re-sell it.  That's a real dick move :D

Is this easily compatible with your True State asset? Thanks!

Yup!  Totally compatible!


I don't suppose you have a tutorial, do you?  I am trying to figure out what parts of the code I need for my keyboard controlled top-down game.  My hope is to use the Basic code.  I understand some of what I need, but maybe not all of it, or where it should all go.  

I have placed movement_and_collision(dir,walkSpeed,oWall); in my oPlayer's Step event, and have copied the movement_and_collision Script into my own project.  Do I need the General Helpers or Vec2 scripts?  Is there other movement and/or collision code I need elsewhere.  What I have done doesn't seem to work.

I apologize for my ignorance.  I'm trying to figure this out, and there are very little comments within the code.  Any advice would be appreciated.  

Thanks so much!

(1 edit)

Yeah, sorry, a tutorial is planned but on the back-burner a bit.

Ultimately the only thing you NEED is to call the script.
You do the work to determine the direction you want the character to move in.
You do the work to determine the speed you want the character to move.

Pass both of those to the script and it will take care of the rest.

So the absolutely easiest implementation would be this:

var _hori = keyboard_check(vk_right) - keyboard_check(vk_left);
var _vert = keyboard_check(vk_down) - keyboard_check(vk_up);

var _dir = -1;
if(point_distance(0,0,_hori,_vert) > 0) {
    _dir = point_direction(0,0,_hori,_vert);

If you have further questions, feel free to hit me up on Discord.  DMs are open to anyone who has joined the GMS Discord Server:


This asset is great! It makes collisions feel much less clunky, I'll probably continue to use it for quickly jumping into top-down games for ages. 

One question though; how can I make the script work with BOTH tiles and objects at the same time? Tiles is great for just about everything, but I usually use objects for destructible obstacles.

I recommend moving to tiles for destructible objects, honestly.  It's very easy to add and remove tiles to and from your collision layer.

That being said, you could add a place_meeting near where the tile_meeting check is, and it must pass both of them to return no collision.


Thank you so much. Whenever I've tried to detect both objects and tiles before in one check it would go completely wrong. I was checking or instead of and, which usually resulted in players that can't move at all.

Adding and removing tiles would work in most cases, but I like the destructible objects to have their sprites collision masks, and be able to be freely positioned. With tiles I would need need to stick to the grid(and tile size), and every object that has a unique collision requires me to change my tile sprites, which I can see being tedious.

It still helps performance, since the amount of collision objects is going to be so small.

Hi PixelatedPope,

First, thanks for all you do for the GM community. Can you help me with something I don't quite understand with this method (which looks awesome btw)? In tile_meeting_precise you use place_meeting with precise collision checking selected for the obj_tile_wall collision type. First question: to use precise collision checking, both the obj_tile_wall and the calling instance have to have precise selected under the type of collision mask, right? That's what the manual says for place_meeting ( That would make the collision mask identical to the shape of the sprite, right? If that's right, how did you get the collision mask in the example game above to not include the sprite's hair? Are there two objects (the character and the green box) that move together with only one (the green box) checking for precise collisions? This is obviously important for our favorite genre of game (2.5d top-down) as you don't want the character's head running into wall above him which would undermine the fake 3d look. I don't see how this problem is solved just given the code above.

The player object has "collision mask" assigned to it.  This is set in the object panel just below where you assign the sprite.  

The object will use the assigned sprite's mask for all collision checks.  You can also do this yourself by setting the "mask_index" variable to any sprite.

In the draw event I then draw the mask index with draw_sprite(mask_index,0,x,y) at a 50% alpha and then draw the normal character sprite on top.  This way I know the mask is lined up and positioned to the character as I expect.

Thanks and I'll post this clarification in the yoyo forums so you don't have to! Just to make sure I've understood you, you are using a different sprite for the collision mask (the green square). But is it still true that the instance calling tile_meeting_precise also needs its collision mask type set to precise per frame (as place_meeting says it does)? Otherwise it won't work, right?

I think I get it now but honestly it's pretty crucial to the setup that we understand that any moving objects calling this function are likely to need a separate sprite for their collision mask and both the calling instance and the checker object need to have precise per frame turned on (not just the checker object). Maybe that was obvious to you but not to me because I've never had to do that before; rectangular collision masks always worked fine for me so I just haven't had to do something else. There might be quite a few others that get equally confused when they get everything set up, but haven't picked a different sprite for the collision mask, and find that their character sprite's head is triggering collisions; or, because they didn't turn on precise per frame in their character object, bounding boxes end getting used instead of precise checking. I don't know if you can edit the yoyoblog post to clarify that now but it might help others avoid some headaches. Awesome job though! I really like how this method combines the best of different approaches!

Hey, thanks for the feedback. I explain this stuff waaaaaaay back in my old top down movement and collision video, but you are right: an update is long overdue.  With the release of 2.3 I'm updating all of my assets and planning comprehensive "getting started with" youtube videos, and this will definitely be included. Sorry for the confusion, hopefully it will be easier to set up in the future!


I just bought this (9/15/2020), and was unable to run it properly on GMS 2.3.  It loads the room background and all the GUI, but no character or walls.  Is there something I am doing wrong, or is this a bug caused by 2.3?


That is VERY unusual.  I just imported the project into 2.3 and it worked great.  And you are the first to report an issue like this.  Try cleaning and re-building.  If that doesn't work, I'd be interested in seeing your project file.


Looks like it was a problem on my end.  My anti-virus was interrupting some GMS functionality.  I've spoken with yoyogames and have resolved the issues.  So now, this file runs GREAT!  thanks again.

(1 edit)

Hi! Would it be possible to re-write this script a bit for 4-directional movement?

Edit: I mean using running left or right sprite for diagonal movement.

Absolutely.  Just alter the switch statement that controls the sprite being used.  Super easy.

Hi, would this script support multiple movement speeds? Such as I'd like to walk slowly/crouch, normal speed, and run.


It does!  There's even a little secret in the demo project.  If you put your mouse cursor over the green square around the character's feet and scrollwheel up or down, it will change his move speed!

Hi! This script works with platformer game too? Thank you!

No, I wouldn't recommend using it for platformers.

Hi Pixel,this asset is wonderful.I do wonder if you ever plan to release this same assest but using tiles one day.Or do you believe disabling Walls outside views will provided the same level of performance, or at least close enough to tiles to not warrant making one.Or perhaps doing this will tiles is just much harder...haha.Anyways thanks for making this!

(1 edit)

Hi. i trying to use your scripts, it's work, but only if player move on 90 or 45 degree

if i trying to move like ~10-20 degrees, player start shaking so much.


Is this any way to fix it? I really hope you can help me.

This may be more related to your camera code than my code.
Likely you need to round your camera's position to match your sub pixel ratio.

Add this script to your project and use it instead of camera_set_view_pos().  I think it'll help.

can you please check this project?

script for camera does work. I need to free move on X-Y. 

I think it's shaking of player, not camera.

So, sorry, that script was not correct.  There should be a newer version that actually works.  I don't get any problems in your project with or without that script, however.  So there must be more going on.  Can you explain how to reproduce the jitteryness in more detail?

Just repeat like in this video

You must go in corner and move player(watch for joystick on video!!). Player start shaking if angle of move != 45 or 90.


Ah!  Okay!  I think I see the problem. aren't using the script.

You call it in your step event, yes, but you aren't USING it.  You never set movement_direction or move_speed.  And then you have a whole bunch of your own place_meeting calls down below and you set your x and y position manually.

You should almost never be setting your object's x and y position while using this script.  The clamp to keep it in the room is okay, but there should be no need to do additional place_meeting calls for world collision.

The asset is great, works like a charme. But one thing is just poking eyes - the lack of comments. If you write a code to someone else, especiallly if you sell  it, then just write  every damn line a comment. So a warning for those, who want to learn something from this code, it's gona be hard, especially for noobs. For that it's 4/5 from me. Despite that, very recomended this asset.

Good feedback.  I'll try to provide more comments in the next update.

hey hey! looks like an amazing "just do the damn collisions" script! especially when rapid prototyping. a question though: can you use this with game maker's own vspeed, hspeed and so on? or do i have to use my own separate variables?

You need to use your own separate variables.

The reason is that GM takes the values you've set in those existing speed variables (speed, direction, hspeed, vspeed, friction, gravity) and automatically updates your x and y position between the step event and the end step event.  So using those will mean you will move A: twice as fast and B: through walls.

OK! thanks for the quick reply, cheers!

Hi Pope! I'm confused, is this the same asset as the previous top down collision? or an updated version? I bought the original on the GM Marketplace and it doesn't say theres an updated version.

Good question!  It's an update (a big update), but I'm currently unable to update the package on the Yoyo marketplace at this time (some sort of 500 server error?).  Hit me up on Twitter or Discord and I'll get you a key for this itch version so you can check it out, and hopefully I'll get the update pushed out on Yoyo's marketplace soon.  

Does anyone have a video of this, my computer is down for the count atm and my phone won't run the script.   :(


Hello PixelatedPope:

Glad you are still doing well. I am thankful for the work and the tutorials you bring to all of us in the GMS2 community devs. WIll definitely purchase this one and support it.

Stay safe and keep well.

(1 edit)

To the author: Thank you for making this! I look forward to using it.

To everyone else:

If you are making a top-down game, you may ignore this comment, but if you're making a side-scrolling game, then before you decide to not support this asset here's something to consider; this script can actually have functionality outside of top-down games. 

For example if you're making a Metroidvania, and are including an ability that lets players stick to and scale certain types of walls, you could use this top-down collision script to extend that ability to also work on certain background tiles. That way, the background can become a platforming and/or puzzle element.

That is all I had to say. Happy developing~!


Spiderball, spiderball, look in the background and there's a wall!

The wall's magnetic, and you stick, so get ready to do a drop kick!