Skip to main content

Laser Beams Exiting a Body

·475 words·3 mins

Continuing with ray casting. It looks like RayCast2D allows me to exclude certain objects. So the first laser beam should exclude the emitter. And any recast laser beam should exclude the object that triggered the recast.

Still not sure how to deal with the collision at the exit location but one thing at a time.

Sweet. Both fixes worked. Excluded the emitter and when creating a child laser beam I excluded the colliding object. No more errors. No need for the debouncer.

That’s good because the debouncer would probably hurt the user experience and also led to some weird behaviour like this:

That means we’re onto the more difficult problem. I have a few ideas.

  1. Add more collision shapes around the outside of the block to mark its boundaries. Put them on a different collision layer and test the laser against those. The problem is I’ll be testing collisions with boundary shapes from all the blocks. Even if I use lines for those collision shapes, there will be situations where blocks are overlapping for a moment before the physics engine resolves the collision.
  2. Cast a ray backwards from far away until it collides with the block. Problem is there’s no way to check for a collision with a specific object. I could add them both to an empty physics layer and perform the check or I could recast rays that collide with other objects until I get the desired object.

I think option 2 is the better way.

Doesn’t necessarily have to be a function to detect the exit. The API could just detect a collision with a specific object.

I should try to do the collision mask method first. If that doesn’t work then do the recast method since that doesn’t leverage the engine as much and will be more prone to (my) errors.

Alright, recast method so far so good. Here’s a shot of it working as desired:

And here’s a shot of it breaking:

That bad behaviour happens because it’s doing a reverse cast and testing against all blocks instead of just testing against the block inside which it’s traversing.

Switching up the collision layer fixed it.

reverse_cast.set_collision_mask_value(1, false)
reverse_cast.set_collision_mask_value(2, true)
containing_block.set_collision_layer_value(2, true)

reverse_cast is the RayCast2D instance. containing_block is the Block instance on the left. So when I do the reverse ray cast I change the RayCast2D to ignore blocks on layer 1 and check blocks on layer 2. I add the block I want to check to layer 2.

Now this is not robust because any block that gets hit by the laser will be added to layer 2 and when another block gets between it and the emitter we have the same problem all over again.

I guess I need to remove the containing block from layer 2 after finding the intersection. I hope that operation is relatively fast…