scenes
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
[gd_scene format=3 uid="uid://bjsiquu3pu2yi"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b8105tebdqgu7" path="res://scripts/hub.gd" id="1_l10or"]
|
||||
|
||||
[node name="Hub" type="Control" unique_id=1025413344]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_l10or")
|
||||
|
||||
[node name="CenterContainer" type="CenterContainer" parent="." unique_id=1963957334]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer" unique_id=1923587537]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Dock" type="Label" parent="CenterContainer/VBoxContainer" unique_id=196076069]
|
||||
layout_mode = 2
|
||||
text = "Dock"
|
||||
|
||||
[node name="StartMissionButton" type="Button" parent="CenterContainer/VBoxContainer" unique_id=1251733940]
|
||||
layout_mode = 2
|
||||
text = "Start Mission"
|
||||
|
||||
[connection signal="pressed" from="CenterContainer/VBoxContainer/StartMissionButton" to="." method="_on_start_mission_button_pressed"]
|
||||
@@ -1,5 +1,6 @@
|
||||
[gd_scene format=3 uid="uid://jven27ktracb"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ck3d6hhcoia15" path="res://scripts/mission.gd" id="1_272bh"]
|
||||
[ext_resource type="PackedScene" uid="uid://c6n3dg530t8oc" path="res://ocean.tscn" id="1_lquwl"]
|
||||
[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"]
|
||||
@@ -38,7 +39,8 @@ material = SubResource("StandardMaterial3D_j2yfa")
|
||||
radius = 0.3
|
||||
height = 0.6
|
||||
|
||||
[node name="Main" type="Node3D" unique_id=1242452333]
|
||||
[node name="Main" type="Node3D" unique_id=1242452333 groups=["mission"]]
|
||||
script = ExtResource("1_272bh")
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=431656791]
|
||||
environment = SubResource("Environment_1")
|
||||
|
||||
+2
-3
@@ -9,12 +9,11 @@
|
||||
material_override = ExtResource("1_j38dg")
|
||||
script = ExtResource("2_nb2vx")
|
||||
sea_height = 1.0
|
||||
sea_choppy = 8.0
|
||||
metadata/follow_step = 1.0
|
||||
|
||||
[node name="StaticBody3D" type="StaticBody3D" parent="." unique_id=1520290282 groups=["water"]]
|
||||
[node name="Surface" type="StaticBody3D" parent="." unique_id=1520290282 groups=["water"]]
|
||||
collision_layer = 32
|
||||
collision_mask = 0
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D" unique_id=629201170]
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Surface" unique_id=629201170]
|
||||
shape = SubResource("WorldBoundaryShape3D_r1f0u")
|
||||
|
||||
+7
-1
@@ -11,12 +11,13 @@ config_version=5
|
||||
[application]
|
||||
|
||||
config/name="boatgame"
|
||||
run/main_scene="res://main.tscn"
|
||||
run/main_scene="uid://bjsiquu3pu2yi"
|
||||
config/features=PackedStringArray("4.7", "Forward Plus")
|
||||
|
||||
[autoload]
|
||||
|
||||
Game="*uid://dtkqmj8h5mg8y"
|
||||
GameState="*uid://xpfddtyfru40"
|
||||
|
||||
[display]
|
||||
|
||||
@@ -70,6 +71,11 @@ debug_possess_next={
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194334,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
debug_end_mission={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194335,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
class_name AIController
|
||||
extends Node
|
||||
|
||||
@export var standoff_distance := 30.0 # throttle down inside this
|
||||
@export var fire_range := 120.0 # open fire inside this
|
||||
@export var full_rudder_angle_deg := 20.0 # bearing error at which rudder saturates
|
||||
|
||||
var _boat: Boat
|
||||
var _target: Boat # node reference — shift-safe; never store a position
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_boat = get_parent() as Boat
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if _boat == null:
|
||||
return
|
||||
if _player_has_boat():
|
||||
return # player possessed us — write nothing, resume when they leave
|
||||
|
||||
if not is_instance_valid(_target):
|
||||
_target = _pick_target()
|
||||
if _target == null:
|
||||
_boat.desired_throttle = 0.0
|
||||
_boat.steer_input = 0.0
|
||||
_boat.aim_point = null # stow turrets, per the aim contract
|
||||
_boat.fire_intents[0] = false
|
||||
return
|
||||
|
||||
# All geometry computed fresh this tick — origin-shift safe.
|
||||
var to_target: Vector3 = _target.global_position - _boat.global_position
|
||||
to_target.y = 0.0
|
||||
var distance := to_target.length()
|
||||
|
||||
var forward := -_boat.global_basis.z
|
||||
forward.y = 0.0
|
||||
|
||||
var bearing_error := forward.signed_angle_to(to_target, Vector3.UP)
|
||||
_boat.steer_input = clampf(
|
||||
bearing_error / deg_to_rad(full_rudder_angle_deg), -1.0, 1.0)
|
||||
|
||||
_boat.desired_throttle = 1.0 if distance > standoff_distance else 0.2
|
||||
|
||||
_boat.aim_point = _target.global_position
|
||||
_boat.fire_intents[0] = distance < fire_range
|
||||
|
||||
|
||||
func _player_has_boat() -> bool:
|
||||
var pc := get_tree().get_first_node_in_group(&"player_controllers") as PlayerController
|
||||
return pc != null and pc.current_controlled == _boat
|
||||
|
||||
|
||||
func _pick_target() -> Boat:
|
||||
var best: Boat = null
|
||||
var best_d := INF
|
||||
for node in get_tree().get_nodes_in_group(&"boats"):
|
||||
var other := node as Boat
|
||||
if other == null or other == _boat:
|
||||
continue
|
||||
var d := _boat.global_position.distance_squared_to(other.global_position)
|
||||
if d < best_d:
|
||||
best_d = d
|
||||
best = other
|
||||
return best
|
||||
@@ -0,0 +1 @@
|
||||
uid://hvfw24jpikc0
|
||||
+12
-2
@@ -4,10 +4,12 @@ extends Node
|
||||
const BOAT_SCENE := preload("res://boat.tscn")
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("restart"):
|
||||
if event.is_action_pressed(&"restart"):
|
||||
get_tree().reload_current_scene()
|
||||
if event.is_action_pressed(&"debug_spawn_boat"):
|
||||
if event.is_action_pressed(&"debug_spawn_boat") and _is_in_mission():
|
||||
_debug_spawn_boat()
|
||||
if event.is_action_pressed(&"debug_end_mission") and _is_in_mission():
|
||||
GameState.return_to_hub({"outcome": "aborted"})
|
||||
|
||||
func _debug_spawn_boat() -> void:
|
||||
var focus := get_tree().get_first_node_in_group(&"boats") as Node3D
|
||||
@@ -17,4 +19,12 @@ func _debug_spawn_boat() -> void:
|
||||
boat.position = focus.global_position + focus.global_basis.x * 10.0 + Vector3.UP * 2.0
|
||||
else:
|
||||
boat.position = Vector3(0, 3, 0)
|
||||
|
||||
var ai := AIController.new()
|
||||
ai.name = "AIController"
|
||||
boat.add_child(ai)
|
||||
get_tree().current_scene.add_child(boat, true)
|
||||
|
||||
func _is_in_mission() -> bool:
|
||||
var scene := get_tree().current_scene
|
||||
return scene != null and scene.is_in_group(&"mission")
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# scripts/game_state.gd — autoloaded as "GameState"
|
||||
extends Node
|
||||
|
||||
const HUB_SCENE := "res://hub.tscn"
|
||||
|
||||
# Written by the hub before starting a mission, read by the mission in _ready().
|
||||
# Later this becomes a MissionDef reference; a Dictionary is the v1 stand-in.
|
||||
var mission_params: Dictionary = {}
|
||||
|
||||
# Written by the mission before returning, read by the hub.
|
||||
var last_mission_result: Dictionary = {}
|
||||
|
||||
|
||||
func start_mission(scene_path: String, params: Dictionary = {}) -> void:
|
||||
mission_params = params
|
||||
last_mission_result = {}
|
||||
get_tree().change_scene_to_file(scene_path)
|
||||
|
||||
func return_to_hub(result: Dictionary = {}) -> void:
|
||||
last_mission_result = result
|
||||
mission_params = {}
|
||||
get_tree().change_scene_to_file(HUB_SCENE)
|
||||
@@ -0,0 +1 @@
|
||||
uid://xpfddtyfru40
|
||||
@@ -0,0 +1,9 @@
|
||||
extends Control
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not GameState.last_mission_result.is_empty():
|
||||
print("Mission result: ", GameState.last_mission_result)
|
||||
|
||||
func _on_start_mission_button_pressed() -> void:
|
||||
GameState.start_mission("res://main.tscn", {"difficulty": 1})
|
||||
@@ -0,0 +1 @@
|
||||
uid://b8105tebdqgu7
|
||||
@@ -0,0 +1,11 @@
|
||||
extends Node3D
|
||||
|
||||
@onready var _ocean: Ocean = $Ocean
|
||||
|
||||
func _ready() -> void:
|
||||
var params: Dictionary = GameState.mission_params
|
||||
_ocean.sea_height = params.get("sea_height", _ocean.sea_height)
|
||||
_ocean.sea_choppy = params.get("sea_choppy", _ocean.sea_choppy)
|
||||
_ocean.sea_freq = params.get("sea_freq", _ocean.sea_freq)
|
||||
_ocean.sea_speed = params.get("sea_speed", _ocean.sea_speed)
|
||||
print("Mission started with params: ", params)
|
||||
@@ -0,0 +1 @@
|
||||
uid://ck3d6hhcoia15
|
||||
@@ -43,6 +43,7 @@ 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
|
||||
add_to_group(&"player_controllers")
|
||||
_possess()
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
|
||||
Reference in New Issue
Block a user