diff --git a/src/equipment/balls/physics_ball/game_ball.gd b/src/equipment/balls/physics_ball/game_ball.gd index 63f15dd..3b1f4b7 100644 --- a/src/equipment/balls/physics_ball/game_ball.gd +++ b/src/equipment/balls/physics_ball/game_ball.gd @@ -38,6 +38,8 @@ const MAGNUS_EPSILON := 1e-3 ## Scaling factor for additional force-based damage @export var damage_force_scale := 0.01 +var current_gravity: Vector3 + var _last_contact_normal: Vector3 = Vector3.UP var _position_on_last_wake: Vector3 var _awake := false @@ -80,6 +82,7 @@ func _magnus_force() -> Vector3: func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: + current_gravity = state.total_gravity if not _awake: # Triggered on first frame after waking _awake = true diff --git a/src/equipment/balls/physics_ball/physics_ball.tscn b/src/equipment/balls/physics_ball/physics_ball.tscn index 0899c67..772a5b4 100644 --- a/src/equipment/balls/physics_ball/physics_ball.tscn +++ b/src/equipment/balls/physics_ball/physics_ball.tscn @@ -49,6 +49,7 @@ const WIDTH := 4 @export var draw_reoriented_basis := true @export var draw_magnus_effect := true +@export var draw_gravity_basis := true @onready var physics_ball: GameBall = $\"..\" @@ -73,6 +74,19 @@ func _draw() -> void: if draw_magnus_effect: var end := camera.unproject_position(physics_ball.global_position + physics_ball._magnus_force() * MAGNUS_SCALE) draw_line(start, end, COLOR_MAGNUS, WIDTH) + + if draw_gravity_basis: + var orbital: Node3D = camera.get_parent_node_3d().get_parent_node_3d().get_parent_node_3d() + var up := -physics_ball.current_gravity.normalized() + var right := up.cross(orbital.global_basis.z).normalized() + var forward := right.cross(up).normalized() + + var end_x := camera.unproject_position(physics_ball.global_position + right) + var end_y := camera.unproject_position(physics_ball.global_position + up) + var end_z := camera.unproject_position(physics_ball.global_position + forward) + draw_line(start, end_x, COLOR_X, WIDTH) + draw_line(start, end_y, COLOR_Y, WIDTH) + draw_line(start, end_z, COLOR_Z, WIDTH) " [sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_gc38m"] @@ -150,6 +164,7 @@ grow_horizontal = 2 grow_vertical = 2 script = SubResource("GDScript_p4v7o") draw_reoriented_basis = false +draw_magnus_effect = false [node name="SFX" type="Node3D" parent="."] unique_name_in_owner = true diff --git a/src/ui/camera/orbital_camera/orbital_camera.gd b/src/ui/camera/orbital_camera/orbital_camera.gd index c5758f7..5819c8a 100644 --- a/src/ui/camera/orbital_camera/orbital_camera.gd +++ b/src/ui/camera/orbital_camera/orbital_camera.gd @@ -1,28 +1,49 @@ class_name OrbitalCamera extends Node3D const POSITION_ACCELERATION := 4.0 +const BASIS_ACCELERATION := 4.0 +const TARGETER_ACCELERATION := 7.0 @export var target: Node3D @export var offset := Vector3(0, 1, 0) @export var angular_speed := 0.007 +var target_basis := Basis.IDENTITY + +@onready var pivot: Node3D = %Pivot @onready var camera: Camera3D = %Camera +@onready var targeter: Node3D = %Targeter static var scene := preload("res://src/ui/camera/orbital_camera/orbital_camera.tscn") func _physics_process(delta: float) -> void: + var up := Vector3.UP + # If target is a game ball, realign to gravity + if target is GameBall: + up = -(target as GameBall).current_gravity.normalized() + var right := up.cross(global_basis.z).normalized() + var forward := right.cross(up).normalized() + target_basis = Basis(right, up, forward) + + # Slerp to basis + global_basis = global_basis.slerp(target_basis, delta * BASIS_ACCELERATION) + # Update position global_position = global_position.lerp( target.global_position + offset, delta * POSITION_ACCELERATION ) # Update rotation - camera.look_at(target.global_position) + #camera.look_at(target.global_position, up) + targeter.look_at(target.global_position, up) + camera.global_basis = camera.global_basis.slerp( + targeter.global_basis.orthonormalized(), delta * TARGETER_ACCELERATION + ) # Update phase angle - rotation.y += angular_speed + pivot.rotation.y += angular_speed static func create(_target: Node3D) -> OrbitalCamera: diff --git a/src/ui/camera/orbital_camera/orbital_camera.tscn b/src/ui/camera/orbital_camera/orbital_camera.tscn index 95d784c..78f1b94 100644 --- a/src/ui/camera/orbital_camera/orbital_camera.tscn +++ b/src/ui/camera/orbital_camera/orbital_camera.tscn @@ -5,12 +5,20 @@ [node name="OrbitalCamera" type="Node3D"] script = ExtResource("1_nvlic") -[node name="Pitch" type="SpringArm3D" parent="."] +[node name="Pivot" type="Node3D" parent="."] +unique_name_in_owner = true + +[node name="Pitch" type="SpringArm3D" parent="Pivot"] transform = Transform3D(1, 0, 0, 0, 0.913545, 0.406737, 0, -0.406737, 0.913545, 0, 0, 0) spring_length = 3.2 -[node name="Camera" type="Camera3D" parent="Pitch"] -unique_name_in_owner = true +[node name="CameraOffset" type="Node3D" parent="Pivot/Pitch"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3) + +[node name="Targeter" type="Node3D" parent="Pivot/Pitch/CameraOffset"] +unique_name_in_owner = true + +[node name="Camera" type="Camera3D" parent="Pivot/Pitch/CameraOffset"] +unique_name_in_owner = true current = true far = 8192.0