GameMaker Studio 2: Tile Collisions

preview_player
Показать описание
How to collide with a tilemap layer, pixel perfect. Less than 20 lines of code. Slopes and more advanced tile collisions are likely to be covered in a future video.

Рекомендации по теме
Комментарии
Автор

Hi, if you're having issues with "vibration" or "bouncing" etc putting this into a platformer it's because you're moving at floats (decimal numbers). Sub pixels and rounding is a pain. So my favourite solution is to simply never move to sub pixel positions and only ever be at whole integer coordinates.

One way to do this is to remove floats from your speeds before you move, then add them back in after you move. That way you retain the overall effect on your movement (0.25 speed moving you one pixel every 4 frames)

A script for this is here. Try to actually understand it before pasting it in or you won't have much luck.

SaraSpalding
Автор

I think I understand another reason some people might be having the jitters.

If you are using a gravity value that is a float, in my case gravity was set as 0.1
This will increase your vertical speed variable (vsp) by 0.1 each frame. That means it will take 10 frames before your vsp is equal to 1. In those 10 frames, your player's y position is increased by 0.1 on frame 1, increased by 0.2 on frame 2 for total of 0.3, increase by 0.3 frame 3 total = 0.6, increase by 0.4 frame 4 total = 1 pixel. On frame 4 your player moves down 1 pixel and vsp is still a float value.

Remember this bit of code...
if(tilemap_get_at_pixel(tilemap, bbox_left, bbox_side+vsp) != 0)

When the program checks to see if there is a tile to collide with bellow the player, if vsp is still a float, game maker will not check the pixel directly below the player to identify if there is a tile there to collide with. Instead it will see bbox_side+vsp as (for example) 32 + 0.1 = 32.1 and see no tile to collide with at that position. But the tile is at y position 33!!! Program goes on to move player down a pixel and then once vsp = 1, it will notice the tile directly below you and move you back up a pixel, then down, and up, and down again...

To fix this:
if((tilemap_get_at_pixel(tilemap, bbox_left, bbox_side+ceil(vsp)) != 0) || (tilemap_get_at_pixel(tilemap, bbox_right, bbox_side+ceil(vsp)) != 0 ))

The ceil () function (ceiling function) will raise a float value to the next highest integer.
Ex.
ceil(0.1) = 1;
ceil(0.8) = 1;
ceil(12.3) = 13;

Hope this helps somebody!

Majicman
Автор

I spent eight hours on this before realizing it was impossible to do with the way I had set things up. But despite that, I still learned a lot from this, and I may end up using it later down the line. Thank you for creating this tutorial.

cutthecreeper
Автор

For anyone having problems don't forget to put the collision code AFTER the movement code in the Step Event. You won't have that problem if you followed this tutorial exactly, but I already had movement code before this and put the collision stuff on top.
Seems like a small thing but I thought I'd share as it completely fixed all the problems I was having.

polaritybear
Автор

I noticed a weird 'bounce' effect happening on downward vertical collisions when vsp was around 16 or more.

After some fiddling I fixed this by changing (y mod 32) to (bbox_bottom mod 32 - (bbox_bottom-y))
Cleaning up the full line of code becomes simply: if (vsp > 0) y = y - (bbox_bottom mod 32) + 31.

Example with explanation:
Working with a 32x32 player object, origin in the centre, distance between y and bbox_bottom is 16. Let's say vertical speed is 16 or greater, we're at least 16 pixels away from the tile and colliding with it on the next frame...

When calculating the snap position, the old method of taking (y mod 32) snaps us 32 pixels too high, since if bbox_bottom is more than half the length of a tile away, then y itself is more than 1 whole tile away.

So I figured, why use y for the modulo calculation when we could use bbox_bottom itself? It's much closer to the target tile after all. Hence I changed it to (bbox_bottom mod 32) and subtracted the distance between y and bbox_bottom to compensate.

The fix seems to work with other sizes of tiles and bboxes as well, should make it safe now for vsp's all the way up to 32 (don't quote me on that, I still find it confusing)

I presume similar things could happen in the other directions, but this was the only one giving me trouble (y'know, with gravity and all) so I haven't tried modifying the rest.
Anyone else noticed issues like this / implemented a similar fix for fast moving objects?

tomcheshire
Автор

Nice Shaun, this is one of the features that makes game maker stand out.

amazingsparckman
Автор

At first I was worried because my character is actually around 2 tiles tall, but I had the genius idea of adding a third check on horizontal collision for the midpoint between the top and bottom corners and it actually worked. Game making makes me feel very smart, thank you for this tutorial.

virgiebabie
Автор

Fantastic stuff Shaun, thanks for taking the time to make a video on this subject!

I was dreading learning how to do tile-based collisions, and after watching several multi-part videos on the subject, I was dreading it even more because they made it seem like it was this complicated ordeal.

Then I stumbled on this video, and it's not a difficult subject at all! I would argue it's even easier than the "conventional" method with objects.

I was able to reproduce this in about 10 minutes in GameMaker, it's really that easy. Thanks again!

JeremyGardnerVideo
Автор

Shaun just wanted to say watching ur platformer tutorials as I am new in coding. 100% love it. Learning a lot and just wanted to say thank you...some of the stuff is hard to understand but I am new and know it will come over time but just wanted to say thanks and pokey poke looks amazing!

Cozmotrin
Автор

can we PLEASE get an updated version of these tutorials?? GMS2 has literally changed just a bit too much for some of this code to actually do what it's supposed to do.

cloudedarctrooper
Автор

Thanks for this! I've always wanted to do tile-based collision due to the overhead associated with filling the game with tons of collision objects. Works great and easy to implement, saved for reuse!

gdmachne
Автор

Truly amazing stuff, keep at it love this man.

Fredrick
Автор

I know this is an old video but I hope this helps - if youre player does the thing where it glitches as soon as it touches a collision tile, go in youre code and make sure you have x = x - (x mod 32) instead of x -= (x mod 32), they seem like the same thing but apparently doing x -= in this case makes the game execute it abnormally. (PS Replace x -= with x = x - for every instance of it, and for y too)

garrettmehl
Автор

one question: would you recommend using this system throughout rpg's?

AqareCover
Автор

thanks a lot! i had issues fixing this but i managed to fix it in the end! i recommend this video for sure!

Twp-pikmin
Автор

Thanks for this tutorial, I was starting a second project next to working side by side with your Platformer tutorial and it is quite handy to have more options when it comes to how to do collisions^^

roundishwhale
Автор

For everybody having problems with either jittering and/or no correct collision detection
By a lot of trial an error, I got it to work with this:
if ((bbox_bottom % 32) != 0) y = y - (bbox_bottom mod 32) + 31;

I do not really understand why shaun's code did not work with my game. All I can think about are these points?
a) player sprite size <= tile sprite size
b) hsp / vsp as integer or whole numbers

maxdennerle
Автор

I know this is like, extremely late since the video was posted, but how would one go about adding gravity?

miniignis
Автор

hey there its pretty funny to see how many people see that video and comment before time is over. ur doin a great job and im watching ur tutorials everyday, to learn GMS and they are really helpfull. i hope u keep up the good work with GMS2. greetings, Ryudo2406

Ryudo
Автор

FOR ANYONE WITH LEFT AND BOTTOM SIDE ISSUES, make sure the bbox_side and the x + hsp are in the correct slots in the tile map get at pixel functions! You cant just copy paste the x check and switch the x's for y's because the x is in the x dimension parameter so if you just swap the x for a y your x and y coord checks are inversed. That's why at 0, 0 it works fine but 200, 50 for example it does the opposite of what its supposed to because while x is 200 it thinks y is and 0's the y variable.

connorking