player controller logic
This commit is contained in:
@@ -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.
|
||||||
@@ -12,7 +12,7 @@ roughness = 0.9
|
|||||||
[sub_resource type="BoxShape3D" id="BoxShape_crate"]
|
[sub_resource type="BoxShape3D" id="BoxShape_crate"]
|
||||||
size = Vector3(1, 1, 5)
|
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
|
collision_layer = 2
|
||||||
mass = 5.0
|
mass = 5.0
|
||||||
script = ExtResource("1_7h74f")
|
script = ExtResource("1_7h74f")
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
[gd_scene format=3 uid="uid://jven27ktracb"]
|
[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://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="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="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://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"]
|
[sub_resource type="ProceduralSkyMaterial" id="SkyMaterial_1"]
|
||||||
sky_horizon_color = Color(0.66, 0.67, 0.68, 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]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="Seabed" unique_id=111957760]
|
||||||
shape = SubResource("BoxShape_seabed")
|
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)
|
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)
|
transform = Transform3D(1, 0, 0, 0, 0.9396926, 0.34202012, 0, -0.34202012, 0.9396926, 0, 0, 0)
|
||||||
script = ExtResource("4_1bvp3")
|
script = ExtResource("4_1bvp3")
|
||||||
target = NodePath("../PlayerBoat")
|
|
||||||
cam = NodePath("PlayerCamera")
|
cam = NodePath("PlayerCamera")
|
||||||
|
|
||||||
[node name="PlayerCamera" type="Camera3D" parent="CameraRig" unique_id=553919400]
|
[node name="PlayerCamera" type="Camera3D" parent="CameraRig" unique_id=553919400]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 8)
|
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")]
|
[node name="Hud" parent="." unique_id=167273188 node_paths=PackedStringArray("world") instance=ExtResource("4_272bh")]
|
||||||
boat = NodePath("../PlayerBoat")
|
|
||||||
world = NodePath("../WorldManager")
|
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")
|
script = ExtResource("6_7mycd")
|
||||||
focus = NodePath("../PlayerBoat")
|
|
||||||
ocean = NodePath("../Ocean")
|
ocean = NodePath("../Ocean")
|
||||||
shift_threshold = 50.0
|
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")
|
||||||
|
|||||||
+3
-12
@@ -1,27 +1,19 @@
|
|||||||
class_name Boat
|
class_name Boat
|
||||||
extends FloatingBody
|
extends FloatingBody
|
||||||
|
|
||||||
## All force values are per-kilogram (they get multiplied by mass), so the
|
## All values multiplied by mass, handling the same regardless of it
|
||||||
## boat handles the same if you change its mass later.
|
|
||||||
@export var engine_power := 12.0 # forward thrust, m/s² at full throttle
|
@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 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 throttle_response := 1.5 # how fast the engine spools up/down
|
||||||
@export var rudder_strength := 2.5 # turning torque at speed
|
@export var rudder_strength := 2.5 # turning torque at speed
|
||||||
@export var keel_grip := 3.0 # resistance to sliding sideways
|
@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
|
var throttle := 0.0
|
||||||
|
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
super(delta)
|
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)
|
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)
|
apply_central_force(forward * throttle * power * mass * submerged_ratio)
|
||||||
|
|
||||||
# --- rudder: only bites when water flows past it ---
|
# --- 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 forward_speed := linear_velocity.dot(forward)
|
||||||
var rudder_bite := clampf(forward_speed / 3.0, -1.0, 1.0)
|
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)
|
apply_torque(Vector3.UP * steer_input * rudder_strength * rudder_bite * mass * submerged_ratio)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
class_name CameraRig
|
||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
@export var target: Node3D
|
|
||||||
@export var sensitivity := 0.005
|
@export var sensitivity := 0.005
|
||||||
@export var follow_speed := 5.0
|
@export var follow_speed := 5.0
|
||||||
@export var cam: Camera3D
|
@export var cam: Camera3D
|
||||||
|
|
||||||
|
var target: Node3D # Controlled by PlayerController
|
||||||
|
|
||||||
var _dragging := false
|
var _dragging := false
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -4,11 +4,12 @@ extends CanvasLayer
|
|||||||
## The HUD's only inputs. Everything inside hud.tscn gets its references
|
## The HUD's only inputs. Everything inside hud.tscn gets its references
|
||||||
## from here -- nothing inside the scene reaches out on its own.
|
## 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):
|
set(value):
|
||||||
boat = value
|
boat = value
|
||||||
if is_node_ready():
|
if is_node_ready():
|
||||||
_distribute()
|
_distribute()
|
||||||
|
|
||||||
@export var world: WorldManager:
|
@export var world: WorldManager:
|
||||||
set(value):
|
set(value):
|
||||||
world = value
|
world = value
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://bxk0exu40a25x
|
||||||
@@ -14,11 +14,13 @@ func _process(_delta: float) -> void:
|
|||||||
var speed := boat.linear_velocity.dot(forward.normalized())
|
var speed := boat.linear_velocity.dot(forward.normalized())
|
||||||
var pos := world.true_position(boat)
|
var pos := world.true_position(boat)
|
||||||
|
|
||||||
text = "Throttle: %+.0f %%
|
text = "Desired Throttle: %+.0f %%
|
||||||
|
Actual Throttle: %+.0f %%
|
||||||
Speed: %.1f m/s
|
Speed: %.1f m/s
|
||||||
Submerged: %.0f %%
|
Submerged: %.0f %%
|
||||||
Position: (%.0f, %.0f)
|
Position: (%.0f, %.0f)
|
||||||
" % [
|
" % [
|
||||||
|
boat.desired_throttle * 100.0,
|
||||||
boat.throttle * 100.0,
|
boat.throttle * 100.0,
|
||||||
speed,
|
speed,
|
||||||
boat.submerged_ratio * 100.0,
|
boat.submerged_ratio * 100.0,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ extends Node
|
|||||||
## recenters scenery in the follow_focus group, and shifts the origin
|
## recenters scenery in the follow_focus group, and shifts the origin
|
||||||
## (teleporting the shift_with_origin group) before float precision degrades.
|
## (teleporting the shift_with_origin group) before float precision degrades.
|
||||||
|
|
||||||
@export var focus: Node3D # the boat
|
|
||||||
@export var ocean: Ocean
|
@export var ocean: Ocean
|
||||||
## Distance from origin that triggers an origin shift.
|
## Distance from origin that triggers an origin shift.
|
||||||
@export var shift_threshold := 2048.0
|
@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).
|
## True world position of the current local origin (grows over a long voyage).
|
||||||
var origin_offset := Vector3.ZERO
|
var origin_offset := Vector3.ZERO
|
||||||
|
|
||||||
|
var focus: Node3D # Controlled by PlayerController
|
||||||
|
|
||||||
|
|
||||||
func true_position(node: Node3D) -> Vector3:
|
func true_position(node: Node3D) -> Vector3:
|
||||||
return node.global_position + origin_offset
|
return node.global_position + origin_offset
|
||||||
|
|||||||
Reference in New Issue
Block a user