From 7c9403273f54bf7e57784f56ea4c8f99f6d40edb Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Tue, 19 Nov 2024 23:26:18 -0700 Subject: [PATCH] Fixed post-shot reorientation weirdness --- src/equipment/balls/physics_ball/game_ball.gd | 33 +++++++++++++++---- .../balls/physics_ball/physics_ball.tscn | 25 +++++++++++--- src/player/shot_setup/hitbox.gd | 1 - src/player/shot_setup/shot_setup.gd | 12 +++---- src/player/shot_setup/shot_setup.tscn | 15 ++------- 5 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/equipment/balls/physics_ball/game_ball.gd b/src/equipment/balls/physics_ball/game_ball.gd index a3ab2e4..9f8f685 100644 --- a/src/equipment/balls/physics_ball/game_ball.gd +++ b/src/equipment/balls/physics_ball/game_ball.gd @@ -25,7 +25,9 @@ const IRON_DAMPING := 9999.0 ## Base damage inflicted on impact with a player @export var base_damage := 15.0 -var last_contact_normal: Vector3 +var _last_contact_normal: Vector3 = Vector3.UP +var _position_on_last_wake: Vector3 +var _awake := false var _zones: Array[BallZone] = [] @onready var normal_physics: PhysicsMaterial = preload( @@ -50,15 +52,20 @@ func _total_terrain_angular_damping() -> float: func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: + if not _awake: + # Triggered on first frame after waking + _awake = true + _position_on_last_wake = global_position + _last_contact_normal = Vector3.UP + var damping := air_damping - if iron_ball: - damping = iron_damping - elif state.get_contact_count(): + if state.get_contact_count(): + _last_contact_normal = state.get_contact_local_normal(0) damping = _total_terrain_angular_damping() if damping <= TERRAIN_DAMPING_EPSILON: damping = rough_damping - last_contact_normal = state.get_contact_local_normal(0) - _debug_draw.queue_redraw() + if iron_ball: + damping = iron_damping angular_damp = damping @@ -71,3 +78,17 @@ func enter_zone(zone: BallZone) -> void: func exit_zone(zone: BallZone) -> void: _zones.erase(zone) + + +func get_reoriented_basis() -> Basis: + var up := _last_contact_normal.normalized() + var forward := (_position_on_last_wake - global_position).normalized() + var right := up.cross(forward).normalized() + forward = right.cross(up) # orthonormalize + return Basis(right, up, forward) + + +func _on_sleeping_state_changed() -> void: + if sleeping: + # Trigger to reassign on wake + _awake = false diff --git a/src/equipment/balls/physics_ball/physics_ball.tscn b/src/equipment/balls/physics_ball/physics_ball.tscn index ea64613..d3e537b 100644 --- a/src/equipment/balls/physics_ball/physics_ball.tscn +++ b/src/equipment/balls/physics_ball/physics_ball.tscn @@ -31,17 +31,30 @@ radius = 0.05 resource_name = "debug_draw" script/source = "extends Control -const COLOR := Color(0, 1, 0) +const COLOR_X := Color(1, 0, 0) +const COLOR_Y := Color(0, 1, 0) +const COLOR_Z := Color(0, 0, 1) const WIDTH := 4 @onready var physics_ball: GameBall = $\"..\" + +func _process(_delta: float) -> void: + if visible: + queue_redraw() + + func _draw() -> void: - if physics_ball.last_contact_normal != null: + if physics_ball._last_contact_normal != null: var camera := get_viewport().get_camera_3d() - var start := camera.unproject_position(physics_ball.global_transform.origin) - var end := camera.unproject_position(physics_ball.global_transform.origin + physics_ball.last_contact_normal) - draw_line(start, end, COLOR, WIDTH) + var start := camera.unproject_position(physics_ball.global_position) + var basis := physics_ball.get_reoriented_basis() + var end_x := camera.unproject_position(physics_ball.global_position + basis.x) + var end_y := camera.unproject_position(physics_ball.global_position + basis.y) + var end_z := camera.unproject_position(physics_ball.global_position + basis.z) + draw_line(start, end_x, COLOR_X, WIDTH) + draw_line(start, end_y, COLOR_Y, WIDTH) + draw_line(start, end_z, COLOR_Z, WIDTH) " [node name="PhysicsBall" type="RigidBody3D"] @@ -73,3 +86,5 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 script = SubResource("GDScript_p4v7o") + +[connection signal="sleeping_state_changed" from="." to="." method="_on_sleeping_state_changed"] diff --git a/src/player/shot_setup/hitbox.gd b/src/player/shot_setup/hitbox.gd index 0de869b..40fa049 100644 --- a/src/player/shot_setup/hitbox.gd +++ b/src/player/shot_setup/hitbox.gd @@ -6,7 +6,6 @@ signal ball_collision(ball: GameBall) @export var ignored_balls: Array[GameBall] = [] @onready var shot_setup: ShotSetup = $".." -@onready var physics_ball: GameBall = %PhysicsBall func _on_ball_entered(ball: GameBall) -> void: diff --git a/src/player/shot_setup/shot_setup.gd b/src/player/shot_setup/shot_setup.gd index b42682a..3e9cea3 100644 --- a/src/player/shot_setup/shot_setup.gd +++ b/src/player/shot_setup/shot_setup.gd @@ -293,14 +293,10 @@ func travel_to_ball() -> void: # Re-orient to the ball's last contact normal if there is one. # Normally this will just be Vector3.UP or something close to it. - var normal := game_ball.last_contact_normal - if normal == null: - normal = Vector3.UP - var up := Vector3.BACK - if not normal.cross(up): - up = Vector3.RIGHT - look_at(global_position + normal, up) - rotate_object_local(Vector3.RIGHT, -PI / 2) + direction.rotation.y = 0 + _target_rotation.y = 0 + global_basis = game_ball.get_reoriented_basis() + print_debug("REORIENTED BASIS: ", global_basis) game_ball.global_transform = ball_point.global_transform diff --git a/src/player/shot_setup/shot_setup.tscn b/src/player/shot_setup/shot_setup.tscn index ad0ad5d..7c76b69 100644 --- a/src/player/shot_setup/shot_setup.tscn +++ b/src/player/shot_setup/shot_setup.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=20 format=3 uid="uid://cy7t2tc4y3b4"] +[gd_scene load_steps=19 format=3 uid="uid://cy7t2tc4y3b4"] [ext_resource type="Script" path="res://src/player/shot_setup/shot_setup.gd" id="1_r6ei4"] -[ext_resource type="PackedScene" uid="uid://dfttci386ohip" path="res://src/equipment/balls/physics_ball/physics_ball.tscn" id="2_1i5j5"] [ext_resource type="PackedScene" uid="uid://c2k88ns0h5ie1" path="res://src/ui/3d/arrow/arrow.tscn" id="2_s70wl"] [ext_resource type="PackedScene" uid="uid://dcqxlbsrubapk" path="res://src/equipment/balls/plasma_ball/plasma_ball.tscn" id="3_8dte7"] [ext_resource type="PackedScene" uid="uid://1s3gywmoi20e" path="res://src/characters/player_characters/gfolf_girl/gfolf_girl.tscn" id="3_e4aur"] @@ -215,12 +214,6 @@ script = ExtResource("1_r6ei4") unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.08, 0) -[node name="PhysicsBall" parent="BallPoint" instance=ExtResource("2_1i5j5")] -unique_name_in_owner = true -process_mode = 4 -transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) -visible = false - [node name="PlasmaBall" parent="BallPoint" instance=ExtResource("3_8dte7")] unique_name_in_owner = true @@ -357,7 +350,7 @@ visible = false initial_speed = 50.0 time_step = 0.01 max_steps = 800 -excluded_bodies = [NodePath("../../BallPoint/PhysicsBall")] +excluded_bodies = [NodePath("../../BallPoint/PlasmaBall")] [node name="ProjectedTarget" parent="ArrowPivot/ShotProjection" instance=ExtResource("6_mynqj")] @@ -374,13 +367,11 @@ one_shot = true [node name="Hitbox" type="Area3D" parent="." node_paths=PackedStringArray("ignored_balls")] script = ExtResource("7_uh8kn") -ignored_balls = [NodePath("../BallPoint/PhysicsBall"), NodePath("../BallPoint/PlasmaBall")] +ignored_balls = [NodePath("../BallPoint/PlasmaBall")] [node name="CollisionShape3D" type="CollisionShape3D" parent="Hitbox"] shape = SubResource("SphereShape3D_xvvdi") -[connection signal="entered_water" from="BallPoint/PhysicsBall" to="." method="_on_ball_entered_water"] -[connection signal="sleeping_state_changed" from="BallPoint/PhysicsBall" to="." method="_on_ball_sleeping_state_changed"] [connection signal="entered_water" from="BallPoint/PlasmaBall" to="." method="_on_ball_entered_water"] [connection signal="sleeping_state_changed" from="BallPoint/PlasmaBall" to="." method="_on_ball_sleeping_state_changed"] [connection signal="timeout" from="BallReturnTimer" to="." method="_on_ball_return_timer_timeout"]