From a40d0bfdd347ff7da561e290e435a2f9c5ae8680 Mon Sep 17 00:00:00 2001 From: bee Date: Tue, 7 Jul 2026 11:53:39 +0200 Subject: [PATCH] player controller logic --- README.md | 7 ++++ player_boat.tscn => boat.tscn | 2 +- main.tscn | 21 +++++++----- scripts/boat.gd | 15 ++------- scripts/camera_rig.gd | 4 ++- scripts/hud.gd | 3 +- scripts/player_controller.gd | 58 ++++++++++++++++++++++++++++++++ scripts/player_controller.gd.uid | 1 + scripts/stats_label.gd | 4 ++- scripts/world_manager.gd | 3 +- 10 files changed, 93 insertions(+), 25 deletions(-) create mode 100644 README.md rename player_boat.tscn => boat.tscn (90%) create mode 100644 scripts/player_controller.gd create mode 100644 scripts/player_controller.gd.uid diff --git a/README.md b/README.md new file mode 100644 index 0000000..014d4ad --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +TODO: + +Controller/possession refactor (input out of Boat). +WeaponDef resource + WeaponSlot + one dumb gun that prints instead of shooting. +Projectile base (with group self-registration) + real firing. +Loadout-driven mounting. +Second boat scene to prove the whole seam. diff --git a/player_boat.tscn b/boat.tscn similarity index 90% rename from player_boat.tscn rename to boat.tscn index b7bd5eb..45ee024 100644 --- a/player_boat.tscn +++ b/boat.tscn @@ -12,7 +12,7 @@ roughness = 0.9 [sub_resource type="BoxShape3D" id="BoxShape_crate"] size = Vector3(1, 1, 5) -[node name="PlayerBoat" type="RigidBody3D" unique_id=1387061778 groups=["shift_with_origin"]] +[node name="Boat" type="RigidBody3D" unique_id=1387061778 groups=["shift_with_origin"]] collision_layer = 2 mass = 5.0 script = ExtResource("1_7h74f") diff --git a/main.tscn b/main.tscn index 5d57923..e12978e 100644 --- a/main.tscn +++ b/main.tscn @@ -1,10 +1,11 @@ [gd_scene format=3 uid="uid://jven27ktracb"] [ext_resource type="PackedScene" uid="uid://c6n3dg530t8oc" path="res://ocean.tscn" id="1_lquwl"] -[ext_resource type="PackedScene" uid="uid://cieiwihia8t2w" path="res://player_boat.tscn" id="2_7mycd"] +[ext_resource type="PackedScene" uid="uid://cieiwihia8t2w" path="res://boat.tscn" id="2_7mycd"] [ext_resource type="Script" uid="uid://46jiwugeccqg" path="res://scripts/camera_rig.gd" id="4_1bvp3"] [ext_resource type="PackedScene" uid="uid://conoykdb1g38n" path="res://hud.tscn" id="4_272bh"] [ext_resource type="Script" uid="uid://dpohf1tg5e2gs" path="res://scripts/world_manager.gd" id="6_7mycd"] +[ext_resource type="Script" uid="uid://bxk0exu40a25x" path="res://scripts/player_controller.gd" id="6_272bh"] [sub_resource type="ProceduralSkyMaterial" id="SkyMaterial_1"] sky_horizon_color = Color(0.66, 0.67, 0.68, 1) @@ -48,24 +49,28 @@ surface_material_override/0 = SubResource("Material_seabed") [node name="CollisionShape3D" type="CollisionShape3D" parent="Seabed" unique_id=111957760] shape = SubResource("BoxShape_seabed") -[node name="PlayerBoat" parent="." unique_id=1387061778 instance=ExtResource("2_7mycd")] +[node name="Boat" parent="." unique_id=1387061778 instance=ExtResource("2_7mycd")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0) -[node name="CameraRig" type="Node3D" parent="." unique_id=2139913829 node_paths=PackedStringArray("target", "cam") groups=["shift_with_origin"]] +[node name="CameraRig" type="Node3D" parent="." unique_id=2139913829 node_paths=PackedStringArray("cam") groups=["shift_with_origin"]] transform = Transform3D(1, 0, 0, 0, 0.9396926, 0.34202012, 0, -0.34202012, 0.9396926, 0, 0, 0) script = ExtResource("4_1bvp3") -target = NodePath("../PlayerBoat") cam = NodePath("PlayerCamera") [node name="PlayerCamera" type="Camera3D" parent="CameraRig" unique_id=553919400] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 8) -[node name="Hud" parent="." unique_id=167273188 node_paths=PackedStringArray("boat", "world") instance=ExtResource("4_272bh")] -boat = NodePath("../PlayerBoat") +[node name="Hud" parent="." unique_id=167273188 node_paths=PackedStringArray("world") instance=ExtResource("4_272bh")] world = NodePath("../WorldManager") -[node name="WorldManager" type="Node" parent="." unique_id=1879897241 node_paths=PackedStringArray("focus", "ocean")] +[node name="WorldManager" type="Node" parent="." unique_id=1879897241 node_paths=PackedStringArray("ocean")] script = ExtResource("6_7mycd") -focus = NodePath("../PlayerBoat") ocean = NodePath("../Ocean") shift_threshold = 50.0 + +[node name="PlayerController" type="Node" parent="." unique_id=2011077099 node_paths=PackedStringArray("current_controlled", "world_manager", "camera_rig", "hud")] +script = ExtResource("6_272bh") +current_controlled = NodePath("../Boat") +world_manager = NodePath("../WorldManager") +camera_rig = NodePath("../CameraRig") +hud = NodePath("../Hud") diff --git a/scripts/boat.gd b/scripts/boat.gd index 277b7f6..2e9c86d 100644 --- a/scripts/boat.gd +++ b/scripts/boat.gd @@ -1,27 +1,19 @@ class_name Boat extends FloatingBody -## All force values are per-kilogram (they get multiplied by mass), so the -## boat handles the same if you change its mass later. +## All values multiplied by mass, handling the same regardless of it @export var engine_power := 12.0 # forward thrust, m/s² at full throttle @export var reverse_ratio := 0.4 # reverse is weaker, like a real prop @export var throttle_response := 1.5 # how fast the engine spools up/down @export var rudder_strength := 2.5 # turning torque at speed @export var keel_grip := 3.0 # resistance to sliding sideways -var desired_throttle := 0.0 +var desired_throttle := 0.0 # move_toward target for actual throttle +var steer_input := 0.0 var throttle := 0.0 - func _physics_process(delta: float) -> void: super(delta) - - if Input.is_action_pressed("throttle_increase"): - desired_throttle = move_toward(desired_throttle, 1, 0.005) - elif Input.is_action_pressed("throttle_decrease"): - desired_throttle = move_toward(desired_throttle, -1, 0.006) - elif Input.is_action_pressed("throttle_stop"): - desired_throttle = 0.0 throttle = move_toward(throttle, desired_throttle, throttle_response * delta) @@ -38,7 +30,6 @@ func _physics_process(delta: float) -> void: apply_central_force(forward * throttle * power * mass * submerged_ratio) # --- rudder: only bites when water flows past it --- - var steer_input := Input.get_axis("rudder_right", "rudder_left") var forward_speed := linear_velocity.dot(forward) var rudder_bite := clampf(forward_speed / 3.0, -1.0, 1.0) apply_torque(Vector3.UP * steer_input * rudder_strength * rudder_bite * mass * submerged_ratio) diff --git a/scripts/camera_rig.gd b/scripts/camera_rig.gd index bbadf17..4a396e4 100644 --- a/scripts/camera_rig.gd +++ b/scripts/camera_rig.gd @@ -1,10 +1,12 @@ +class_name CameraRig extends Node3D -@export var target: Node3D @export var sensitivity := 0.005 @export var follow_speed := 5.0 @export var cam: Camera3D +var target: Node3D # Controlled by PlayerController + var _dragging := false diff --git a/scripts/hud.gd b/scripts/hud.gd index ff53eae..d43541d 100644 --- a/scripts/hud.gd +++ b/scripts/hud.gd @@ -4,11 +4,12 @@ extends CanvasLayer ## The HUD's only inputs. Everything inside hud.tscn gets its references ## from here -- nothing inside the scene reaches out on its own. -@export var boat: Boat: +var boat: Boat: # Controlled by PlayerController TODO: Testing values, different label for different types set(value): boat = value if is_node_ready(): _distribute() + @export var world: WorldManager: set(value): world = value diff --git a/scripts/player_controller.gd b/scripts/player_controller.gd new file mode 100644 index 0000000..def67e0 --- /dev/null +++ b/scripts/player_controller.gd @@ -0,0 +1,58 @@ +class_name PlayerController +extends Node + +@export var current_controlled : Boat: + set(value): + current_controlled = value + if is_node_ready(): + if current_controlled != null: + desired_throttle = current_controlled.throttle + _possess() + +@export var world_manager : WorldManager: + set(value): + world_manager = value + if is_node_ready(): + _possess() + +@export var camera_rig : CameraRig: + set(value): + camera_rig = value + if is_node_ready(): + _possess() + +@export var hud : Hud: + set(value): + hud = value + if is_node_ready(): + _possess() + +@export var throttle_ramp := 0.5 + +var desired_throttle := 0.0 + +func _ready() -> void: + if current_controlled != null: # Only happens on intial loading if boat already moves + desired_throttle = current_controlled.throttle + _possess() + +func _process(delta: float) -> void: + if current_controlled == null: + return + + if Input.is_action_pressed("throttle_increase"): + desired_throttle = move_toward(desired_throttle, 1, throttle_ramp * delta) + elif Input.is_action_pressed("throttle_decrease"): + desired_throttle = move_toward(desired_throttle, -1, throttle_ramp * delta) + elif Input.is_action_pressed("throttle_stop"): + desired_throttle = 0.0 + + var steer_input := Input.get_axis("rudder_right", "rudder_left") + + current_controlled.desired_throttle = desired_throttle + current_controlled.steer_input = steer_input + +func _possess() -> void: + camera_rig.target = current_controlled + world_manager.focus = current_controlled + hud.boat = current_controlled diff --git a/scripts/player_controller.gd.uid b/scripts/player_controller.gd.uid new file mode 100644 index 0000000..1269833 --- /dev/null +++ b/scripts/player_controller.gd.uid @@ -0,0 +1 @@ +uid://bxk0exu40a25x diff --git a/scripts/stats_label.gd b/scripts/stats_label.gd index badb4e5..3571f1b 100644 --- a/scripts/stats_label.gd +++ b/scripts/stats_label.gd @@ -14,11 +14,13 @@ func _process(_delta: float) -> void: var speed := boat.linear_velocity.dot(forward.normalized()) var pos := world.true_position(boat) - text = "Throttle: %+.0f %% + text = "Desired Throttle: %+.0f %% +Actual Throttle: %+.0f %% Speed: %.1f m/s Submerged: %.0f %% Position: (%.0f, %.0f) " % [ + boat.desired_throttle * 100.0, boat.throttle * 100.0, speed, boat.submerged_ratio * 100.0, diff --git a/scripts/world_manager.gd b/scripts/world_manager.gd index 84e8009..8a0dbb5 100644 --- a/scripts/world_manager.gd +++ b/scripts/world_manager.gd @@ -5,7 +5,6 @@ extends Node ## recenters scenery in the follow_focus group, and shifts the origin ## (teleporting the shift_with_origin group) before float precision degrades. -@export var focus: Node3D # the boat @export var ocean: Ocean ## Distance from origin that triggers an origin shift. @export var shift_threshold := 2048.0 @@ -16,6 +15,8 @@ extends Node ## True world position of the current local origin (grows over a long voyage). var origin_offset := Vector3.ZERO +var focus: Node3D # Controlled by PlayerController + func true_position(node: Node3D) -> Vector3: return node.global_position + origin_offset