fix: train timings, minor transition issue to adult room, train audio

This commit is contained in:
tiger tiger tiger 2026-01-21 13:23:04 +01:00
parent 098eef6fe5
commit a0f6261c1e
6 changed files with 112 additions and 67 deletions

View File

@ -17,13 +17,32 @@ extends Node3D
@onready var subway : SubwayTrain = $Subway
@onready var subway_audio_main : AudioStreamPlayer3D = %SubwayTrainAudio
@onready var subway_audio_2 : AudioStreamPlayer3D = %SubwayTrainAudioIntense
var player_on_board : bool:
get: return %EntryDetect.overlaps_body(State.player)
var tween : Tween = null
signal departure(index : int)
## Player is about to arrive
signal train_approaching(track : Dolly)
## Player has fully arrived at station
signal train_arrived(track : Dolly)
## Player is departing in train
signal train_departing(track : Dolly)
## Player has fully left the station with train
signal train_left(track : Dolly)
func _ready() -> void:
reset()
## One arrival and departure
func cycle() -> void:
await arrive()
@ -33,34 +52,40 @@ func reset() -> void:
if tween: tween.kill()
subway.global_position = origination.global_position
func _seat_player_if_inside() -> bool:
if %EntryDetect.overlaps_body(State.player):
func _seat_player() -> void:
prints("Player departs inside Train", self.name)
State.player.reparent(subway)
return true
return false
func _unseat_player_if_inside() -> void:
if %EntryDetect.overlaps_body(State.player):
func _unseat_player() -> void:
prints("Player arrives on Train", self.name)
State.player.reparent(get_parent())
func arrive(endstation : bool = false) -> void:
%SubwayTrainAudio.play(0)
%SubwayTrainAudioIntense.play(0)
subway_audio_main.play()
subway_audio_2.play()
await get_tree().create_timer(pre_arrival_time).timeout
if player_on_board:
train_approaching.emit(self)
if tween: tween.kill()
tween = create_tween().set_trans(Tween.TRANS_CIRC).set_ease(Tween.EASE_OUT)
tween.parallel().tween_property(subway, "global_position", self.global_position, arrival_time)
await tween.finished
subway.door_open = true
_unseat_player_if_inside()
if player_on_board:
_unseat_player()
train_arrived.emit(self)
if endstation:
%SubwayTrainAudio.stop()
%SubwayTrainAudioIntense.stop()
subway_audio_main.stop()
subway_audio_2.stop()
@ -68,13 +93,19 @@ func leave() -> void:
await get_tree().create_timer(pre_leave_time).timeout
subway.door_open = false
await get_tree().create_timer(door_close_time).timeout
var seated := _seat_player_if_inside()
if player_on_board:
_seat_player()
train_departing.emit(self)
if tween: tween.kill()
tween = create_tween().set_trans(Tween.TRANS_QUART).set_ease(Tween.EASE_IN)
tween.parallel().tween_property(subway, "global_position", destination.global_position, leave_time)
# Player is on board and will be leaving
await tween.finished
await %SubwayTrainAudio.finished
# Player was on board and has left the station
if seated: departure.emit(index)
reset()
if player_on_board: train_left.emit(self)
reset() # Warp back / rewind train position

View File

@ -1,6 +1,7 @@
class_name Fahrplan extends Node3D
## easy graph: <station> : [Track1Train1 (next halt), Track1Train2], [Track2Train1(next halt), ...]
## CAVEAT: These must be direct children of the fahrplan!
@onready var fahrplan : Dictionary[Node3D, Array] = {
$station_hirschfeld: [[$station_university_mensa, $station_parity_square],[]],
$station_hirschfeld : [[$station_university_mensa, $station_parity_square],[]],
@ -13,10 +14,11 @@ class_name Fahrplan extends Node3D
$station_rosenthal : [null,null], # Endstation
}
## List of all registered station nodes, used to unparent them
@onready var stations : Array[Node3D] = fahrplan.keys()
@onready var tracks : Array[Dolly] = [%Track0Dolly, %Track1Dolly]
@export var random_wait : Vector2 = Vector2(1.0, 10.0)
@export var empty_train_random_delay : Vector2 = Vector2(5.0, 20.0)
func _set_signage_texts(group: StringName, message: String) -> void:
get_tree().call_group(group, "set_text", "")
@ -29,9 +31,10 @@ func _ready() -> void:
print(x.name)
await get_tree().process_frame
tracks[0].departure.connect(player_departed)
tracks[1].departure.connect(player_departed)
enter_station($station_hirschfeld)
tracks[0].train_left.connect(_player_train_left)
tracks[1].train_left.connect(_player_train_left)
_unparent_all_stations_except($station_hirschfeld)
enter_station(current_station)
var current_station : Node3D = null
@ -39,8 +42,8 @@ var stop := false
var destinations : Array[Node3D] = [null, null]
func train_traffic_loop(track: Dolly, cancel: Array) -> void:
## Begins the scheduled traffic (looping through the list of destinations) on a given track
func _begin_traffic_loop(track: Dolly, cancel: Array) -> void:
if fahrplan[current_station][track.index] == null: # empty array (just no routes) would be falsy
track.arrive(true)
_set_signage_texts(track.signage_group, "Endstation")
@ -60,7 +63,9 @@ func train_traffic_loop(track: Dolly, cancel: Array) -> void:
destinations[track.index] = next
_set_signage_texts(track.signage_group, next.name) # TODO: load nice string
await get_tree().create_timer(randf_range(random_wait.x, random_wait.y)).timeout
# Vary our schedule a little by making empty trains wait a random amount of time
if not track.player_on_board:
await get_tree().create_timer(randf_range(empty_train_random_delay.x, empty_train_random_delay.y)).timeout
if cancel.is_empty(): return # abort the loop
await track.cycle() # arrive and depart
@ -70,14 +75,24 @@ var cancellation_token : Array
func enter_station(station: Node):
prints("------------", "ENTER STATION", station, station.name, "------------")
if current_station: current_station.visible = false
remove_child(current_station)
current_station = station
current_station.visible = true
add_child(current_station)
cancellation_token = ["go"] # Allocate a new stopping token
train_traffic_loop(tracks[0], cancellation_token)
train_traffic_loop(tracks[1], cancellation_token)
_begin_traffic_loop(tracks[0], cancellation_token)
_begin_traffic_loop(tracks[1], cancellation_token)
func player_departed(track_index : int) -> void:
func _player_train_left(track: Dolly) -> void:
cancellation_token.clear()
enter_station(destinations[track_index])
enter_station(destinations[track.index])
func _unparent_all_stations_except(except : Node3D):
for station in stations:
if station == except:
current_station = station
continue
assert(station.get_parent() == self, "A station that isn't a child of Fahrplan is in the Fahrplan: %s" % station.name)
remove_child(station)
station.visible = true # Make visible by default, parenting handles visibility and collision

View File

@ -160,19 +160,22 @@ spot_angle = 15.0
[node name="SubwayTrainAudio" type="AudioStreamPlayer3D" parent="Subway"]
unique_name_in_owner = true
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -0.4578781, 0, -6.1605225)
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, -0.03272724, -0.06909847, -0.7569556)
stream = ExtResource("3_4h0n7")
unit_size = 100.0
max_polyphony = 2
panning_strength = 0.7
bus = &"sfx"
playback_type = 1
[node name="SubwayTrainAudioIntense" type="AudioStreamPlayer3D" parent="Subway"]
unique_name_in_owner = true
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0.6660023, 0, 0)
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 1.162013, -0.12873906, 11.825858)
stream = ExtResource("3_4h0n7")
attenuation_model = 1
unit_size = 15.0
max_polyphony = 2
panning_strength = 0.9
bus = &"sfx"
playback_type = 1

View File

@ -374,7 +374,7 @@ shape = SubResource("BoxShape3D_2ixm0")
[node name="Scenes" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.4831846, 0, 2.44453)
[node name="ScenePlayer" type="AnimationPlayer" parent="Scenes"]
[node name="SceneAnimationPlayer" type="AnimationPlayer" parent="Scenes"]
unique_name_in_owner = true
libraries = {
&"": SubResource("AnimationLibrary_br20t")

File diff suppressed because one or more lines are too long

View File

@ -81,6 +81,14 @@ func _ready() -> void:
progress = progress
if animation_player.has_animation("RESET"): animation_player.play("RESET")
if get_parent() is not CanvasLayer:
push_warning("-------------- ", "DEBUG MODE ", self, " --------------")
await Main.curtain.open()
await appear()
await play()
push_warning("-------------- ", "FINISHED ", self, " --------------")
func _rebuild():
print_debug("StoryPlayable.gd: %s._rebuild()" % self.name)
if is_node_ready():