Skip to main content

Tile Maps and Collision Layers

·707 words·4 mins

First tile map. Working with Industrial Tileset by Atomic Realm. https://atomicrealm.itch.io/industrial-tileset/

And tutorial Using Tilesets

Phew. That is painstaking work. I could see it getting easier over time but right now it’s pretty tricky. Maybe I chose a tileset which is a little hard to use—it’s hard for me to tell which tile I’m using since I haven’t done this before. I imagine someone with experience knows exactly where to find each tile in the tile sheet.

Well, for now it turns out all of that is unnecessary. I can just paint with black boxes or something.

Okay, here’s our tile map test level.

Yellow is meant to be an area where prisms and mirrors cannot be placed. That ugly grey texture is meant to be smoke or mist and it should block lasers but not objects.

The smoke is working. Walls also block lasers the way I want so good news for those two.

Main problem right now is that rectangular prism in the top left. It’s embedded in the wall. For some reason I’m able to drag objects into the walls and half the time the engine seems okay with it.

Maybe the tiles aren’t treated as solids but just surfaces? Maybe the block’s boundary rectangle is lining up perfectly with the wall boundaries so no collision is detected. I could test that theory by turning off snapping. Or rotating the block.

Okay, yeah, if the block is rotated the collisions are detected properly. Huh.

Same thing happens with the right angle prism.

Once the diagonal comes into play, though, the collision is detected.

It’s not quite that simple, though. Why doesn’t this trigger a collision?

Wow, I think it’s intersecting with the corners only. I lightened pixels at the corners of the tile so I could see the edges and look how it lines up:

Crazy.

Hmm, not that simple either. Here’s a counterexample:

And another:

When the prisms are rotated it’s consistent. But when they’re not it’s unpredictable. I can’t find a pattern.

Might be because my collision detection code is using PhysicsBody2D.move_and_collide() with a zero vector for the motion. Poking around now, I’m seeing PhysicsDirectSpaceState2D.intersect_shape() which might be closer to what I actually want. Neither PhysicsBody2D nor CollisionObject2D have methods for testing a shape collision without moving it.

Spent quite a bit of time scratching my head over this. intersect_shape() above wasn’t actually helpful because the API is pretty hard to work with. I ended up going back to the PhysicsBody2D interface.

Not before looking at Godot’s source code a little to try to understand how to use it better.

There were two options that worked.

drag_ghost.test_move(drag_ghost.global_transform, Vector2.ZERO, null, 0.08, true)

or

var collision: KinematicCollision2D = drag_ghost.move_and_collide(Vector2.ZERO, true, 0.08, true)
return !!collision

For a while, I was passing Vector2(1,0) as the movement vector thinking that maybe the zero vector was part of the problem. Not the case. With that argument I was able to approach obstacles from the right side without detecting a collision but approaching from other directions detected collisions correctly. It was so weird. But when I switched that value to Vector2(1,0).rotated(randf() * 2 * PI) I got random results. The drag ghost would flicker between normal and red because collisions were being detected on and off.

The clincher was actually the last argument which sets recovery_as_collision to true.

If I understand correctly, the physics engine normally doesn’t report a collision if the colliding object gets pushed out of the way by the collision. I’m not sure exactly how that works with a static body colliding with a region on a tile map but when that value is false I get unpredictable results and when it’s true everything looks lovely.

Man, I was getting a little frazzled there. Glad to have it resolved. I was a little worried I’d have to abandon using tile maps or something but.

Spoiler alert but here’s the most basic version of the prism-beats-smoke mechanic in action.

I’ll need to flesh out that level so that it’s not so obvious.

Also, there’s a problem detecting collisions with rays originating from inside the smoke. That should get shut down right away instead of waiting until it crosses from one tile to the next. For example: