# Reflection Line2D

I found a video on YouTube with a sercol and a beam, and everything seems to be fine, but the beam doubles and flickers after spawning from the mirror, tell me what could be the problem, screenshot and the code is attached.

extends Node2D

onready var ray = $RayCast2D onready var lain =$Node2D/Line2D

var vec = Vector2()
var max_bounces = 5

func _process(delta):
lain.clear_points()

vec.y-=1

ray.global_position = lain.global_position
ray.cast_to = vec.normalized()*1000
ray.force_update_transform()

var prev = null
var bounces = 0

while true:
if not ray.is_colliding():
var pt = ray.global_position + ray.cast_to
break

var coll = ray.get_collider()
var pt = ray.get_collision_point()

if not coll.is_in_group("Mirrors"):
break

var normal = ray.get_collision_normal()

if normal == Vector2.ZERO:
break

if prev !=null:
prev.collision_layer = 3
prev = coll
prev.collision_layer = 0

ray.global_position = pt
ray.cast_to = ray.cast_to.bounce(normal)
ray.force_raycast_update()

bounces+=1
if bounces >= max_bounces:
break

if prev !=null:
prev.collision_layer = 3


You should be calling ray.force_raycast_update() when you changed ray.cast_to, and you should be calling ray.force_update_transform() when you changed ray.global_position. Since you changing them together, call these together too. Here:

    ray.global_position = lain.global_position
ray.cast_to = vec.normalized()*1000
ray.force_update_transform()
ray.force_raycast_update()


And here:

        ray.global_position = pt
ray.cast_to = ray.cast_to.bounce(normal)
ray.force_update_transform()
ray.force_raycast_update()


And with that the flickering should be gone.

There are other improvements we can do to the code. Notably it mixes local and global coordinates. The reason being that cast_to is local to ray. Which means instead of this:

var pt = ray.global_position + ray.cast_to


You should do this:

var pt = ray.to_global(ray.cast_to)


And since we have the normal in global coordinates. This is not correct:

ray.cast_to = ray.cast_to.bounce(normal)


Instead, we are going to convert ray.cast_to to global, then bounce it, and back to local:

ray.cast_to = ray.to_local(ray.to_global(ray.cast_to).bounce(normal))


With that, you should be able to move or rotate your Node2D and the laser should go with it.

By the way, instead of switching collision layers and mask, you can add an exception to the ray with:

ray.add_exception(coll)


And remove it with:

ray.remove_exception(prev)


Ah, and if you want to clear the exception, you call clear_exceptions:

ray.clear_exceptions()


I also want to point out that every frame you decrement vec.y:

vec.y-=1


If you keep decrementing vec.y it will eventually go out of representable integers.

You probably want to just give a value once. Don't forget you are normalizing and then scaling by 1000 anyway:

ray.cast_to = vec.normalized()*1000


And yes, that is local of the ray. Which is why moving or rotating it should also move the ray.