GMS 2 Check if an object is completely colliding with a tilemap

Tobey

Member
I am currently creating void (areas the player can fall into) collisions for my top down game. The void is defined with tiles and a specific tile layer and I want to check to see if the players entire collision mask is inside of the void tiles similar to the rectangle_in_rectangle() function.

This is the code I have right now:
GML:
///@arg tilemap

var _tilemap, _meeting;

_tilemap = argument0;

//check for collision on all four corners of the collision mask
_meeting = tilemap_get_at_pixel(_tilemap, bbox_right, bbox_top)
          or
          tilemap_get_at_pixel(_tilemap, bbox_right, bbox_bottom)
          or
          tilemap_get_at_pixel(_tilemap, bbox_left, bbox_top)
          or
          tilemap_get_at_pixel(_tilemap, bbox_left, bbox_bottom);

//Return wether or not there was a collision
return(_meeting);
 

TheouAegis

Member
You are close I think.

Ok not as simple as my first copout suggestion. I just didn't want to type this out. LOL

That code tells you if any corner is on any tile. I think you would want to use xor instead of regular or. Since you have an even number of corners to check, the result using xor would be 0 whenever all 4 corners are on a tile or all 4 corners are not on a tile. Then just checking any one of those corners again will tell you if it is a void or tile.

The method I would personally go with would be to actually convert each tile check into bits and add them all up.
Code:
var _meeting = !!tilemap_get_at_pixel(_tilemap, bbox_right, bbox_top)
          +
          !!tilemap_get_at_pixel(_tilemap, bbox_right, bbox_bottom) * 2
          +
          !!tilemap_get_at_pixel(_tilemap, bbox_left, bbox_top) * 4
          +
          !!tilemap_get_at_pixel(_tilemap, bbox_left, bbox_bottom) * 8;

return _meeting;
Or just do a series of if-else conditions. If even one corner is on a tile, return true or false, else check the next corner.
 
Last edited:

SoVes

Member
Just get the corners of the tile and use rectangle_in_rectangle. Simple as that
Edit: I think i misunderstood the question
 

TheouAegis

Member
Just get the corners of the tile and use rectangle_in_rectangle. Simple as that
And if the object is inside 2 void tiles? Or 4 void tiles? Defining the rectangle becomes a lot less simple. And by the time you find the coordinates of the rectangle, you would already know if the object is over void tiles.
 

Tobey

Member
You are close I think.

Ok not as simple as my first copout suggestion. I just didn't want to type this out. LOL

That code tells you if any corner is on any tile. I think you would want to use xor instead of regular or. Since you have an even number of corners to check, the result using xor would be 0 whenever all 4 corners are on a tile or all 4 corners are not on a tile. Then just checking any one of those corners again will tell you if it is a void or tile.

The method I would personally go with would be to actually convert each tile check into bits and add them all up.
Code:
_meeting = !!tilemap_get_at_pixel(_tilemap, bbox_right, bbox_top)
          +
          !!tilemap_get_at_pixel(_tilemap, bbox_right, bbox_bottom) * 2
          +
          !!tilemap_get_at_pixel(_tilemap, bbox_left, bbox_top) * 4
          +
          !!tilemap_get_at_pixel(_tilemap, bbox_left, bbox_bottom) * 8;

return _meeting;
Or just do a series of if-else conditions. If even one corner is on a tile, return true or false, else check the next corner.
It works perfectly, thank you!!! I don't really understand how it works though. What does "!!" do?
 

TheouAegis

Member
It works perfectly, thank you!!! I don't really understand how it works though. What does "!!" do?
! Negates a bool, or turns a real into a bool and negates the result. Two of them negates the negation. So !0 is 1 and !1 is 0, thus !!0 is 0 and !!1 is 1. And !2 is 0, so !!2 is 1.

I don't know how it compares to >0 checks, but it's just a quirky style I use in Game Maker. I think I do it to remind my brain my code will be treating a real as a bool. Gestalt theory, or something.
 
Last edited:

Tobey

Member
! Negates a bool, or turns a real into a bool and negates the result. Two of them negates the negation. So !0 is 1 and !1 is 0, thus !!0 is 0 and !!1 is 1. And !2 is 0, so !!2 is 1.

I don't know how it compares to >0 checks, but it's just a quirky style I use in Game Maker.
Ok thank you and sorry just one last question. It is returning 493 when the player is completely colliding with the tilemap and 12 when the player is only partially colliding with the tile map. Are these numbers consistent and then could I just do if(_meeting == 493){ do something }?
 

TheouAegis

Member
493?! That's not right at all. A 12 makes sense. The result should be 0 to 15 if you use the bit method. 15 would be all 4 corners are on a tile. Using the code I posted, a 12 should be... left side over tiles, right side over nothing.

You kept the _var tilemap, _meeting;line in, right?

I wonder if YYG broke OoP.


Post your script's current code. Make sure there are no typos. (I can't even come up with 493 on my calculator.)
 
Last edited:

Tobey

Member
493?! That's not right at all. A 12 makes sense. The result should be 0 to 15 if you use the bit method. 15 would be all 4 corners are on a tile. Using the code I posted, a 12 should be... left side over tiles, right side over nothing.

You kept the _var tilemap, _meeting;line in, right?

I wonder if YYG broke OoP.


Post your script's current code. Make sure there are no typos. (I can't even come up with 493 on my calculator.)
Sorry, I accidentally removed a "!!" when I was trying to figure out what those actually did. Now it is returning 15 when the players is inside the tilemap which I'm assuming is correct.

Thanks for the help. I really appreciate it.
 
Top