#Help making a predictive 'laser' for the bounce of a ball in 2D

40 messages · Page 1 of 1 (latest)

south forge
#

Hi guys! New to Godot.

I have a CharacterBody2D that moves as usual with WASD and faces the mouse. When I press spacebar, it throws out a boomerang that goes in a preset direction (using a throw_start and throw_end node to set the direction) that's always the same.

I am trying (and currently failing) to make a system to raycast out in the same direction as the ball, drawing out a line as preset distance (reusing the above throw_start and throw_end nodes). if it collides with something, then I want it to instead stop drawing the first line where the collision would happen (which should be where the boomerang would hit the wall too) and then it will calculate the bounce trajectory (which, again, should be the same as the boomerangs) and then draw a second line out so that you can preview the bounce.

Right now the first part works, I can draw the raycast out the length between the throw_start and the throw_end. However it changing the length when colliding doesn't work (it's no longer the same exact straight line) and the bounce is completely different. Any help is appreciated.

Any help is appreciated.

The Raycasting code
`
extends Node2D

class_name Laser_Cast

@onready var first_raycast = $"First Raycast"
@onready var first_line_2d = $"First Line2D"
@onready var second_raycast = $"Second Raycast"
@onready var second_line_2d = $"Second Line2D"
@onready var throw_start = $"../Throw Start"
@onready var throw_end = $"../Throw End"

@export var first_raycast_length = 100.0

func _ready():
first_raycast.position = throw_start.position
first_raycast.target_position = throw_end.position

func _process(_delta):
handle_first_laser()
handle_second_laser()

func handle_first_laser():
var is_colliding = first_raycast.is_colliding()

if (is_colliding):
    first_line_2d.points = [first_raycast.position, to_local(first_raycast.get_collision_point())]
else:
    first_line_2d.points = [first_raycast.position, first_raycast.target_position]

func handle_second_laser():
var is_colliding = first_raycast.is_colliding()
if not is_colliding:
second_line_2d.points = []
return

var collision_point = first_raycast.get_collision_point()
var collision_normal = first_raycast.get_collision_normal()
var bounce_direction = collision_normal.bounce(collision_normal)

var line_start = to_local(collision_point)
var line_end = to_local(collision_point + bounce_direction * 200)

second_line_2d.points = [line_start, line_end]

`

worldly forum
#

lots of things to consider here:

  • a raycasts target_position is relative to the rays origin, so it should probably read first_raycast.target_position = throw_end.position - throw_start.position
  • raycasts results are stored once per physics frame, if you change its position or target in code and don't wait for the next physics tick it will not update its result ( but you can use force_raycast_update() )
  • if your throw_start or throw_end position changes after this node was created you have to update the raycasts positions
  • using intersect_ray() is cleaner in these cases. it doesn't require a node etc
    https://docs.godotengine.org/en/stable/tutorials/physics/ray-casting.html
south forge
#

@worldly forum Hey! Thanks for the response. your first point about the throw_end.position - throw_start.position does indeed fix the issue of the line being off.

However, now the bounce appears to be being calculated incorrectly, but I can't see what I'm doing wrong. The first line is accurate to the ball's trajectory, but the bounce for the collision doesn't work

`
func handle_second_laser():
var is_colliding = first_raycast.is_colliding()
if not is_colliding:
second_line_2d.points = []
return

var collision_point = first_raycast.get_collision_point()
var collision_normal = first_raycast.get_collision_normal()
var bounce_direction = collision_normal.bounce(collision_normal)

var line_start = to_local(first_raycast.get_collision_point()) - throw_start.position
var line_end = to_local(bounce_direction)

second_line_2d.points = [line_start, line_end]

`

worldly forum
#

var bounce_direction = collision_normal.bounce(collision_normal)

#

you want to bounce the incoming vector off the normal

#

not the normal off the normal 😉

south forge
#

Sorry for sounding dumb, but the incoming vector in this situation would be which one? sadcat

south forge
worldly forum
#

your throw vector, throw_end - throw_start

south forge
#

So its the direction of the original line "bouncing" using the normal of the collision?

worldly forum
#

there are some great "vectors for game dev for beginners" videos on youtube. doesnt have to be godot specific, but thats the one thing you really need to at least understand the basics of. if you find someone who can explain it well its super easy actually

south forge
#

@worldly forum

``

#

Woops sorry

#

`
var collision_point = first_raycast.get_collision_point()
var collision_normal = first_raycast.get_collision_normal()
var original_line_direction = (throw_end.position - throw_start.position).normalized()
var bounce_direction = original_line_direction.bounce(collision_normal)

var line_start = to_local(first_raycast.get_collision_point()) - throw_start.position
var line_end = bounce_direction * 100

second_line_2d.points = [line_start, line_end]

`

This is not working either, the angle that the 2nd line is on is not changing at all as the raycast's angles

worldly forum
#

you should print the collision_point and collision_normal to see if these values even change

south forge
#

The normal is in fact not changing, but the point is changing

worldly forum
#

i think you need to change this line
var line_end = bounce_direction * 100
to this
var line_end = line_start + bounce_direction * 100
at least, possibly other issues here to

#

a direction isnt a point, if you want to make it a point you need to make it start from somewhere ( add a point to it )

#

in very not technical words 😄

worldly forum
#

in all these pictures i dont see any collision object

south forge
south forge
worldly forum
worldly forum
#

btw, if you add a minus
var bounce_direction = original_line_direction.bounce(-collision_normal) like this

#

it should reflect

#

dont ask me why tho 😄

south forge
#

The debug shapes thing is very helpful

south forge
worldly forum
#

whats helpful to track stuff down is to print virtually every value, like the throw positions etc then move and check if they are all where you expect them to be

#

approximately

south forge
#

I think I'm going to have to go just go back to the beginning with writing this out and get it going again - is it possible to specifically colour raycasts with the debug stuff?

south forge
worldly forum
worldly forum
south forge
#

Yeah I'm going to go and do that, stick with what I know is working and then have that chiselled in stone and then start fresh elsewhere