Add collision detection to Line2D in Godot 4

Godot Version

Godot version 4.2.1

Question

I’m trying to add collision detection to a dynamically drawn Line2D that connects two sprite nodes. I know that I need to add a Collision Shape to my line scene, but haven’t been able to get it set up correctly yet. Here’s what I’m working from:

main.tscn (Node2D)
main.gd
extends Node2D

var spritescene = preload(“res://scenes/sprite_node.tscn”)
var linescene1 = preload(“res://scenes/line_2d.tscn”)

func _ready():
var leftNode = spritescene.instantiate()
leftNode.global_position = Vector2(100,300)
add_child(leftNode)
print(leftNode.id)
var rightNode = spritescene.instantiate()
rightNode.global_position = Vector2(1000,300)
add_child(rightNode)
print(rightNode.id)
var link1 = linescene1.instantiate()
link1.endpointID0 = leftNode.id
link1.endpointID1 = rightNode.id
add_child(link1)

sprite_node.tscn (Sprite2D with a button child, using the generic Godot texture, Z Index set to 100)
sprite_node.gd

extends Sprite2D

var id = get_instance_id()
@onready var main = get_node(“/root/main”)

var dragging = false
var of = Vector2(0, 0)
var selected = false
var base_scale = .5
var active_scale = 1

var node_name

var mouse_entered = 0

func _process(delta):
if dragging:
position = get_global_mouse_position() - of

func _on_sprite_button_button_down():
print(“button pressed”)
dragging = true
of = get_global_mouse_position() - global_position

func _on_sprite_button_button_up():
dragging = false

line_2d.tscn (Line2D)
Line2D.gd
extends Line2D

var endpointID0
var endpointID1
@onready var endpoint0 : Node = instance_from_id(endpointID0)
@onready var endpoint1 : Node = instance_from_id(endpointID1)

func _process(delta):
set_point_position(0, endpoint0.global_position)
set_point_position(1, endpoint1.global_position)

(button_down and button_up signals connected from the button to the spriteNode script)

I have tried adding a static body 2d and collision shape 2d (segment) in a variety of configurations in the line_2d.tscn but so far no luck. Any help would be appreciated.

Got it working, kind of. Would appreciate any help with improving my code/approach.
Anyways, found a post about a Godot 3 recipe for this:

https://kidscancode.org/godot_recipes/3.x/2d/line_collision/index.html

Still couldn’t get it to work with a SegmentShape2D, but the second approach, using a RectangleShape2D does work (did have to modify things slightly due to some differences between 3 and 4).

I created a Line2D scene (v3line2d) with a StaticBody2D child.

extends Line2D

var endpointID0
var endpointID1
var collision

@onready var endpoint0 : Node = instance_from_id(endpointID0)
@onready var endpoint1 : Node = instance_from_id(endpointID1)

func _ready():
print(points.size())
print(endpoint0.global_position)
print(endpoint1.global_position)
print(get_point_position(0))
print(get_point_position(0))
set_point_position(0, endpoint0.global_position)
set_point_position(1, endpoint1.global_position)
for i in points.size() - 1:
var new_shape = CollisionShape2D.new()
$StaticBody2D.add_child(new_shape)
var rect = RectangleShape2D.new()
new_shape.position = (points[i] + points[i + 1]) / 2
new_shape.rotation = points[i].direction_to(points[i + 1]).angle()
var length = points[i].distance_to(points[i + 1])
rect.size = Vector2(length, 10)
new_shape.shape = rect
print(new_shape)
collision = new_shape

func _process(delta):
set_point_position(0, endpoint0.global_position)
set_point_position(1, endpoint1.global_position)
collision.position = (endpoint0.global_position + endpoint1.global_position) / 2
collision.rotation = endpoint0.global_position.direction_to(endpoint1.global_position).angle()
var length = endpoint0.global_position.distance_to(endpoint1.global_position)
collision.shape.size = Vector2(length, 10)

func _on_static_body_2d_mouse_entered():
print(“you say hello!”)

func _on_static_body_2d_mouse_exited():
print(“I say goodbye”)

Then I modified my main scene (adding a third node so that I could test a variety of line objects at the same time). The new line got put in as the upper right side of the triangle and it gives me the functionality I need.