The versatile and easy to use top down collision system!

  • Easy to use
  • Move any direction at any speed
  • Control motion with Speed and Direction or X Speed and Y Speed
  • Flexible system supports object collisions, tile collisions, and more
  • Configure objects to slide around corners
  • Always whole number coordinates for objects
  • Never get stuck in a wall
  • Directional collision reporting

Example Project Includes

  • Object based collision example with rotated, scaled rectangle collisions and custom shape collision blocks
  • Tile based collision example with angled and custom shaped tiles
  • 8 directional character
  • 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!

After a bit of simple setup, you can move your character around your room with perfect world collision! Provide a direction to move in and a speed to move at and your object will move, collide, and slide!

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!

NO MORE!

How about this?

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

Need Help setting up tile based checking with your tile set?  A little confused by the given example? Understandable. Check out my devblog about converting the system to tiles!

DOCUMENTATION

https://docs.google.com/document/d/1tLEZSzRd9cQ9iiPq8shaF42j1K9Yo36LFG90sYuZeTo/...

Quick Start for Object Based Collision

  1. Import the use_tdmc script into your project
  2. Open the script and at the very top, locate where it references objWall (line 4) and change it to whatever you call your basic wall object asset
  3. Call use_tdmc() in your object’s create event and store the return value in a variable

  4. In the step event, call the desired movement function based on how you are managing your characters momentum
  5. To remove any jittering, draw your sprite with the given draw position

Basic License: You are free to use this in any project personal or commercial; no credit necessary.  Just don't be a dick and redistribute it or claim that it is your own.   The included character art was created by GameKrazzy


StatusReleased
CategoryAssets
Rating
Rated 5.0 out of 5 stars
(9 total ratings)
AuthorPixelated Pope
Made withGameMaker: Studio
Tagscollision, GameMaker, gms2, scripts, sourcecode, Top-Down

Purchase

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:

TDMC2.yyz 482 kB
use_tdmc.gml 5 kB

Development log

Comments

Log in with itch.io to leave a comment.

(+1)

Great project. Does what it claims to do, very well.

@Pixelated Pope are you on hand to help with some customization?

(+1)

I could be, but it really depends on what you want changed. The system is pretty "locked in" so something that might seem like a modification or an adjustment could mean a full re-write.  Feel free to hit me up on Discord to chat. My DMs are open to those who are members of the GM Discord server: https://discord.gg/gamemaker

Hello, thanks for this awesome script!  Ive found an infinte loop and replicated it in your demo.  Generally if the character clips into a wall the game will still run, however in corners this can freeze the game.  In RmBasicDemo, position the character to coordinates 122, 311. Moving the character now with a controller will freeze the game.  It doesnt seem to happen when using the keyboard. Not sure if this needs to be fixed as the character shouldn't be clipping anyway, but thought i'd let you know.  

This is happening for me as well

If I set a high speed in the corner, the game freezes

I'll take a look!

Okay, I don't see the same issue.  Define "high speed", which corner, basic or advanced, which controller method?

I have the same problem. Apparently with the latest updates, the script does not work as before, even with the compability mod

Everything seems to be working for me.  What exactly are you experiencing?

(2 edits)

I Use tile collision I sometimes get stuck and there is a chance that the game will freeze. https://images-ext-1.discordapp.net/external/UZFVf_tk6sHPgHBiysILtOfV_U55eM_uQWI...

https://i.imgur.com/dK3MrFp.png

Yeah, using "tile collision" is a VERY important piece of information when reporting an issue :D

(4 edits)

Sorry) I can send you the project itself. There is your code without edits. I don't know how to explain the problem to you. All I can see is that in the junction of tiles, the player sometimes gets stuck in a collision, and when doing so, there is a chance that the game will freeze.

Or maybe it would be more correct that you send your working version with a tile collision, and I will try to find the problem. Maybe I did something wrong. although I have tried several times.

Oh, yeah.  If you drop the player on a wall, it's likely not gonna move.  Seems to happen to me for both keyboard and controller... because the player is stuck in the wall you dropped them on.
This is something you can solve with a "get out of the wall" function easily enough, and not really something I plan on fixing as part of this package.

Just wondering if you tried my method of moving the character to 122, 311 in the rmBasicDemo room? I can send you a copy if youre getting different results. For me the issue is that the game freezes in corners and I cant push them out of the wall.  However if the character is completely in a wall, the game wont freeze and they can be pushed out.

Yeah, I tried that exactly location in the room and it just doesn't work at all with keyboard or controller because the player is embedded in the wall from the start.  If you wanna send me a link to your example, I'd take a look

(2 edits)

Here is an example file with the character slightly overlapping a corner. At the start of the game, use a gamepad and it will freeze.  Using a keyboard I can walk out of the corner.  If the character starts more inside of the solid, it wont freeze.  

Here is a video showing the freeze.  First part is keyboard movemet, second is gamepad.  I added a timer just to help with the visualization.

Thanks for taking a look

So, check out this tweet:
https://twitter.com/Pixelated_Pope/status/1516815617109635073?s=20&t=VWha6dl9I8t...

Just call that function in your step event before movement_and_collision (or after or both, honestly) and you'll never get stuck in a wall and freeze the game ever again

(1 edit)

Hi Pixelated Pope, 
really nice script.
I got just one problem with enemies.
When they touch obstacles, the game does freeze.

As direction variable for enemies I did use
move_dir = image_angle

Thanks in advance for any suggestion.

Yeah, don't use image angle.  You need a different variable for your sprite angle, and then you draw the sprite using draw_sprite_ext with that angle variable.
image_angle rotates your collision mask, which is usually a very bad idea

Hello! You have made a great script, man. The movement is very smooth, the code itself is quite minimal and performant. Very well done. I bought this and have been using it for a few days, great job!

I have one complaint/question though. When using your script to move my objects, I don't get any collisions events firing at all. Digging around your script I'm guessing it's because you move the object out of collisions before GMS registers anything?

If I'm doing something wrong, can you please give me a pointer?
And if it's a missing feature, would it be a lot of trouble to ask you to please add it?


Thank you for your time!

Yeah, no collision events will fire.  Collision events fire if you are inside an object between the step event and the end step event, and the purpose of this script is to not be inside an object by the end of the script.

Now the script returns true or false based on whether the object's movement has been halted by an object... that may not be useful to you depending on your situation, but there's almost always a way to do what you want without using collision events.

For the record: I never use collision events past the prototyping stage 99% of the time, and even then only in the most basic, simple of situations for objects that the player can walk through.

For help with your specific situation, it's probably best to head over to the discord server.  Much easier to get live help there to get you fixed up and moving forward sooner. https://discord.gg/gamemaker

this is amazing. i see this is for statick objects. can this be applied to moving objects? like a basic enemy that moves? as a inheritance from parent to child i mean thx for your answer. love your content btw keep it up 

Please update to 2.3+ version. I catch some bug...https://disk.yandex.ru/i/hIS0fg1_bBKJcw

Thank you! I will look into it.

So, I can't seem to reproduce this on my end.  All you did was convert it to 2.3 and it just doesn't work?  What platform are you running this on?

Yes. v2.3.4.583

Well, I rewrote like the whole demo.  Try the latest upload.

TDMC.yyz

Script: movement_and_collision at line 8 : unexpected symbol "?" in expression

Script: movement_and_collision at line 8 : got '?' expected ':'

I apologize for my stupidity...

I'm afraid to break something in the script

(+1)

Update to the latest version of GM
Line 8 uses the ?? operator or "nullish" operator.  It's the equivalent of:
if(_count != undefined)
  _count = _count
else
  _count = 1

Love this as a beginning step, especially since I'm not really a coder but want to make a quick and dirty prototype of a game idea I have. Collision is so silky smooth!

What I'd really like to do is add a zaxis for jumping though, like on top of walls, and having depth collision. Any plans to update this with that? Or do you know a quick copy and paste I could do? Like I said... not much of a coder. I THINK I might be able to figure it out, maybe just adding Z whereever you call to check X and Y? It's just going to take me a very long time.

So this is something I've been meaning to write an article about, but think about it like this.

When we say "place_meeting()" we are basically asking "is there a collision here or not."  And then we handle the result of that.  "There is something there?  I can't move."  "There isn't?  I can move."

So all you really want to do is add another variable to the check: z.  
So replace place_meeting() with place_meeting_z: a script of your own making, that accepts a z axis and makes all the necessary checks; including a z-axis.  The result is still the same: there is something there, or there isn't. True or False.

This is the difference between "collision checking" and "collision handling".  You simply want to change how your collision checking is done, which is the easier part to handle.  

I HAVE done this before, so if you run into trouble, I'd recommend asking about it in the help channels of the GM Discord.  You are welcome to ping me when you ask, but if I'm unavailable someone just as capable (or more so) should be able to help.
Here's an invite.
https://discord.gg/gamemaker

Deleted 144 days ago

Hmm...  It's certainly possible to modify it to do that, but it may not be easy.  If you want to discuss it further, Discord might be a better format for talking through your options.  If you aren't already a member, join the GM Discord server, then you can either ping me in an available help channel, or DM me.

https://discord.gg/gamemaker

Bought the script I'm really new to this but needed to get some quick guidance. As I added the script but not 100% sure if I have to change anything once I add it to the object.

Best place to get help with anything GM related is in the unofficial discord server: https://discord.gg/gamemaker

If I'm there and available, I'll be happy to assist you personally, if I'm not, there are tons of awesome people who can help you with getting this script up and running and just about anything else you need help with on your game dev journey!

god the collision feel so much better now

I want to ask, is your "any speed" solution resisted to flickering? Lets say if I use 2.27 speed will my character flicker on the screen?

If they do, let me know... because they shouldn't.  There is the possibility of some jittering when sliding across a wall at a speed like 1.25 but that also depends on a lot of factors.  But your character should never "flicker", and if it does it is very unlikely to be my script that is the cause.

This script is fantastic! Works perfectly for my project and after a little fine-tuning I have better movement than ever!

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

vardirection=direction;
varspeed=speed;

Ship Step Event

//Movement Script

movement_and_collision(vardirection,varspeed,obj_wall_base);

//Add movement in direction

if (keyboard_check(vk_left) or keyboard_check(ord("A")))
{
sprite_index = spr_shipa;
vardirection=image_angle+90;
varspeed+=1;

}

if (keyboard_check(vk_right) or keyboard_check(ord("D")))
{
sprite_index = spr_shipd;
vardirection=image_angle-90;
varspeed+=1;

}

if (keyboard_check(vk_up) or keyboard_check(ord("W")))
{
sprite_index = spr_shipw;
vardirection=image_angle;
varspeed+=1;

}

if (keyboard_check(vk_up) or keyboard_check(ord("W")))
{
sprite_index = spr_shipw;
vardirection=image_angle;
varspeed+=1;

}

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?

https://imgur.com/a/UqqAF7u

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. 

(+1)

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!

Hi

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? 

(+1)

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!

Hello,

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);
}
movement_and_collision(_dir,walkSpeed,oWall)

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: https://discord.gg/By6u9pC

Hi! 

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.

Oh!

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 (http://127.0.0.1:51291/index.htm#t=...rhsearch=place_meeting&rhhlterm=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!

Hi,

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?

Thanks.

(+1)

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.

(+2)

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.

Thanks.

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!

https://pixelatedpope.itch.io/tdmc/devlog/156556/converting-tdmc-to-use-tiles

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

Video:https://streamable.com/mdab2h

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.

https://www.dropbox.com/s/v3h86tf2oey6aiu/camera_set_view_pos_subpixel.gml?dl=0

can you please check this project?

https://drive.google.com/open?id=1mmftbs2B8tP3fi35SttBYkO5P-9WuRAr

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 https://streamable.com/mdab2h

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

(+3)

Ah!  Okay!  I think I see the problem.

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

(+1)

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.

(+1)

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.   :(

(+1)

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!