Hi! I'm trying to get a "path" of where a "beam" would bounce around a 2D room. I'm using RayCast2D
for this.
Here's the snippet of code I wrote for that:
func calc_beam_points(start_pos: Vector2, angle: float, reach: float):
var beam_points: Array
var ray_cast = RayCast2D.new()
ray_cast.set_enabled(true)
var beam = Vector2(cos(angle) * reach, sin(angle) * reach)
while reach > 0.1:
ray_cast.position = start_pos
var cast_target = beam + start_pos
ray_cast.set_cast_to(cast_target)
ray_cast.force_raycast_update()
var next_point
if ray_cast.is_colliding():
next_point = to_local(ray_cast.get_collision_point())
# update ray_cast for next bounce
reach -= (next_point - start_pos).length()
var coll_normal = ray_cast.get_collision_normal()
beam = beam.bounce(coll_normal).clamped(reach)
start_pos = next_point
else:
next_point = cast_target
reach = 0
beam_points.append(next_point)
return beam_points
The problem I have is that get_collision_point()
sometimes (but not always) returns a point inside the collider object. This means that every follow-up "bounce" ends up hitting the same object (i.e. the execution ends up in an infinite loop).
I tried solving this by adding the collider to the list of exceptions in RayCast2D
, but in that case, I can't have a collidable object that has multiple collision shapes, since the ray will "miss" other shapes after bouncing off the first one it hits (since the whole object was added as an exception).
The next idea I have is to set the bounce point a bit "before" the actual collision, but that feels a bit like a hack (and reduces ray accuracy with every bounce). So before doing that, I wanted to check - am I doing something wrong? Can this be solved in a nicer way?