[SOLVED] How do I check if a tile has a hitbox using the new Tilemap object?

Hi,

I have started making a little RPG inspired by the very first Ultima (and a little bit of Dragon Quest 1 too).

I am using the new Tilemap object but I can’t figure out how to make collisions work. The tutorial video on the GDevelop Youtube channel shows how to use the Tilemap with Platformer behavior but it doesn’t work for a top down game.

I tried using the top down corner slider obstacle behavior and the obstacle for pathfinding behavior but I didn’t manage to make it work.

The character movement in my game is very simple but it is exactly what I need :


(I don’t want to use the top down character behavior because it is not really what I want the movement to feel like)

So instead of using a behavior I thought I could use conditions to check if the tile the player is about to step on has a hitbox. If it has, the PlayerCharacter won’t move. If it has not a hitbox, the PlayerCharacter will move.

But I can’t find the condition I need.

Does anyone knows if it is even possible ?

PS : Sorry I’d had more screenshots but as a new user I am limited to only one.

I have found a very scuffed (and not long term viable) solution :

Instead of trying to check if the tile has a hitbox, I check the tile ID. I know tile ID 2 is a wall and tile ID 3 is water so I added a condition that PlayerCharacter can move if the tile he is about to go on is not a tile ID 2 or 3.

But obviously this means I have to add a condition for every tile on my Tilemap I do not want the Player to go on. It only works for now because my game is still very small but it is going to become unmanagable very quickly, so I’m still looking for a better solution.

I don’t know if the separate object action would work for you. If not, then you could use a range. Put the tiles with a collision first and then you could check if the ID is say less than 20. You could leave room for expansion.

Another option would be to stick objects a little away from each side and check if they’re in collision with the tile map. Ray cast would also probably work.

I wish they would add a way to get the tile by name. I thought about creating an array or structure with the tile names and then you could look up the name based on the ID. It would be a pain to setup but it would be better than using numbers alone.

These are all workarounds until they add new features. I would make suggestions and like or vote on other suggestions.

I tried this but it is really buggy, the character becomes all jittery.

Could be a solution but it is not ideal as I have no idea how many tiles the final game will have.

After a few hours of tinkering I came to the conclusion that the best solution would be to use Raycast against Tilemap but I have not been able to make it work yet. I don’t think I fully understand how raycasts work (it’s my first time using them).

The thing I find weird is that I managed to use Collisions against Tilemap for showing/hiding interiors but I can’t make it work with Raycasts.

EDIT : I found the solution ! I understood how to use raycasts ! I am so happy lol !

Here’s the working code if it can help someone one day :

At first it seemed logical to me to use the results stored in the variables but I was wrong. If I understand correctly, the raycast condition plays the actions if it detects the object it is tested against. And if you use a Tilemap, it will only detect the tiles with hitboxes.

Thank you @Keith_1357 for your help !

After testing the ray cast, IDK how well it will work because it only uses 1 point not the entire width or height. Maybe it needs multiple points.or something on a grid.

Unlike most conditions, inverting a raycast switches it to the farthest object. Instead of 2.ray cast per direction, you can set a variable like CanMove to true before the ray cast. And to false if the ray cast is triggered. Alternatively, you can put the ray cast in a NOT event and put the simulate button as the action.

I prefer the angle version of raycast. It could be made simpler by reading the key or the angle or maybe using points. IDK.

As my game uses a grid, it does not matter where the point of the raycast ends inside of the tile, I know the entirety of the tile can’t be walked on.

Now that I have something working I am afraid of touching it lmao

Is that a problem ?
I don’t understand why, but inverting the raycast works like if it was “If the raycast does not detect collision with Tilemap”.


In this example I’m showing the raycast which checks if the player can go to the right.
My raycast is 16px long. So it ends up right in the middle of the right tile.
If I understand correctly, the raycast is so small there is only 1 tile it can detect and that’s the wall.

So when I invert the raycast, it should still detect the wall tile and I should be unable to move ?

EDIT : I modified the event as you suggested to make the variable “CanPlayerMove” always true and it works like a charm. It is much simpler code and more “beautiful” and I guess it will prevent bugs down the line so thank you !

OK, yes, if the distance is short enough then it would detect the same location. For example, if you had a point past the nearest tile or object then it would choose the farthest object or tile. If there was only 1 tile or objext the x, y then it would either contain the point closest to the source of the ray cast or the farthest point on the other side.

This doodle might help.

Sorry but I don’t get it… (English is not my first language so thank you for being patient with me :tired_face:)

What I am currently understanding :

Capture d'écran 2024-08-28 A
My raycast is 16 pixels long. On this screenshot the raycast is not inverted. So it detects the tile as soon as it hits the hitbox (green mark).

Capture d'écran 2024-08-28 B
On this screenshot the raycast is inverted so it is checking for the farthest object. But because my raycast is so short, it detects the exact same tile.

In both case the hitbox of the tile is detected. So my player shouldn’t move in either case because I disable the variable CanMove when it detects the hitbox.

Except my player moved when I inverted the raycast. There is obviously something I am not getting :face_with_spiral_eyes:

1 Like

Just think of it as reversing the ray cast test direction. When inverted instead of starting at the start and going to the target, the ray cast is basically starting at the target x, y and moving toward the start. If the target x, y is in the center of an object or in this case a hitbox then it will detect the same hitbox and the same edge. It will return the same x, y. So, you should be fine.

1 Like

Since your character is moving by whole grid spaces I don’t see a reason to use raycasting. I would prefer to use a simple object to check the destination, and only when player tries to move in that direction:

pressed key Right           |   change position of checkTile
                            |   to player.X + 16, player.Y
  -> checkTile is NOT              |
     colliding with Tilemap        |   move player

In the collision check you would have to make sure to enable the “ignore objects that are touching but not overlapping” option, if the checker object is 16x16. Alternatively you could make it smaller than the tile size and put it in the center of the tile you are checking.

1 Like

Oh Ok I get it now ! Thank you for taking the time to explain it to me ! :smiley:

You’re totally right I don’t know why I haven’t thought of this, it is such a simple and elegent solution… I like to make my life more difficult than it needs to be lol

And now I’m wondering maybe using 4 raycasts is not really ideal optimization-wise ?

1 Like

It is not ideal, although that doesn’t really matter if you are only doing it for one player. You would need hundreds of objects doing this every tic to start seeing an impact on performance.

You could easily adopt my example into pre-detecting the possible moves, just move the checkTile around to the four directions after the player moves and store the result in a variable as you did before. This does make sense if you have some use for that information, such as highlighting the squares that the player can move to.

But if you aren’t doing anything like that then it would sufficient to just check the destination when the player tries to move. One advantage of doing it this way is that you don’t have to worry about changes to the environment… so for example, if a tile was destroyed to allow passage, but you had already calculated possible moves, you would then have to recalculate in order to reflect the new opening.