local_game_jam_jan_2025/player/rope.gd
Ethan Wellenreiter ed9643f386 Improving rope disconnecting technique
Now compares the angle of the old connection to the new one and based off
of the attachment being from clockwise movement or counterclockwise
movement, it disconnects

Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
2025-01-05 22:09:25 -05:00

129 lines
4.1 KiB
GDScript

extends Node2D
class_name Rope
@onready var rope_seg_scene : PackedScene = preload("res://assets/rope_segment.tscn")
@onready var player : Player = %Player
@export var DIST_MARGIN : float = 0.01
var rope_segments : Array[RopeSegment] = []
func add_rope_seg(conn_point : Vector2) -> void:
var rope_seg : RopeSegment = rope_seg_scene.instantiate()
add_child(rope_seg)
rope_seg.set_conn_point(conn_point)
rope_seg.update_sprite_heading(player.global_position)
rope_seg.update_ray_heading(player.global_position)
rope_segments.append(rope_seg)
func shift_add_rope_seg(conn_point : Vector2) -> void:
add_rope_seg(rope_segments[-1].conn_point)
rope_segments[-2].conn_point = conn_point
var t1 = rope_segments[-2]
rope_segments[-2] = rope_segments[-1]
rope_segments[-1] = t1
rope_segments[-2].update_sprite_heading(conn_point)
rope_segments[-2].update_ray_heading(player.global_position)
rope_segments[-1].update_sprite_heading(player.global_position)
rope_segments[-1].update_ray_heading(player.global_position)
func pop_rope_seg() -> void:
if (rope_segments.size() == 0):
print("ERROR: popping from empty rope")
else:
var rope_seg : RopeSegment = rope_segments[-1]
remove_child(rope_seg)
rope_segments.remove_at(rope_segments.size()-1)
rope_seg.safe_destroy()
func shift_pop_rope_seg() -> void:
#print("shift_pop_entered")
if (rope_segments.size() == 0):
print("ERROR: popping from empty rope")
else:
var t1 = rope_segments[-2]
rope_segments[-2] = rope_segments[-1]
rope_segments[-1] = t1
rope_segments[-2].conn_point = rope_segments[-1].conn_point
rope_segments[-2].update_sprite_heading(player.global_position)
rope_segments[-2].update_ray_heading(player.global_position)
pop_rope_seg()
func clear_rope() -> void:
while not rope_segments.is_empty():
pop_rope_seg()
func angle_valid_release_rope(a1:float, cw:bool) -> bool:
var result : bool
if cw:
result = a1 < 0
else:
result = a1 > 0
return result
func check_new_coll():
#print("enter")
var cur_rope = rope_segments[-1]
if cur_rope.rope_ray.is_colliding():
var col_point : Vector2 = cur_rope.rope_ray.get_collision_point()
var dist : float = player.global_position.distance_to(col_point)
#print(player.rope_length, " ", dist)
if player.rope_length - dist > DIST_MARGIN:
shift_add_rope_seg(col_point)
#rope_segments[-2].connection_angle = rope_segments[-2].conn_point.angle_to_point(player.global_position)
var tangent : Vector2 = col_point - player.global_position
tangent = Vector2(tangent.y, -tangent.x)
rope_segments[-2].clockwise = player.velocity.dot(tangent) > 0
#print(tangent, " ", player.velocity, " ", rope_segments[-2].clockwise)
#cur_rope.update_sprite_heading(col_point)
player.rope_length = dist
player.connection_point = col_point
else:
var counter : int = rope_segments.size() - 2
#var pop : bool = false
while counter >= 0:
#print("looping")
if rope_segments[counter].rope_ray.is_colliding(): # safety check
if rope_segments[counter].conn_point.distance_to(rope_segments[counter].rope_ray.get_collision_point()) < DIST_MARGIN and \
angle_valid_release_rope((rope_segments[counter].conn_point - player.global_position).angle_to(rope_segments[counter+1].conn_point - player.global_position), rope_segments[counter].clockwise): # if the collision of the other ray is longer (so it can see the earlier connection point)
player.connection_point = rope_segments[counter].conn_point
player.rope_length = player.global_position.distance_to(player.connection_point)
shift_pop_rope_seg()
counter -= 1
else:
break
else:
break
#print("exit")
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
#print(global_position)
if player.on_rope and rope_segments.size() >= 1:
#print("hi")
rope_segments[-1].update_sprite_heading(player.global_position)
for i in range(rope_segments.size()):
rope_segments[i].update_ray_heading(player.global_position)
#print("aim_dir ", aim_dir)
#look_at(aim_dir)
check_new_coll()
pass