Compare commits

...

5 Commits

Author SHA1 Message Date
b3af967745 MP3 player mutes ambient noise while playing
All checks were successful
linting & formatting / build (push) Successful in 21s
2025-06-27 18:03:09 -06:00
f840738288 MP3 UI scrolling 2025-06-27 17:46:08 -06:00
22163f6f32 Renamed MP3 tracks 2025-06-27 16:37:38 -06:00
41814c2c4a Workaround for clipping rectangle rotation issue by simply hiding things that shouldn't be shown 2025-06-27 16:18:03 -06:00
05edbf5d27 Music playback continues quietly while paused 2025-06-27 14:37:51 -06:00
10 changed files with 248 additions and 27 deletions

View File

@ -1,6 +1,7 @@
[gd_resource type="AudioBusLayout" format=3 uid="uid://caten2l7w1h6w"]
[resource]
bus/0/volume_db = -0.130497
bus/1/name = &"Music"
bus/1/solo = false
bus/1/mute = false
@ -13,3 +14,9 @@ bus/2/mute = false
bus/2/bypass_fx = false
bus/2/volume_db = 0.0
bus/2/send = &"Master"
bus/3/name = &"Ambient"
bus/3/solo = false
bus/3/mute = false
bus/3/bypass_fx = false
bus/3/volume_db = 0.0
bus/3/send = &"SFX"

View File

@ -74,7 +74,7 @@ unique_name_in_owner = true
stream = ExtResource("5_ejh2c")
volume_db = -80.0
autoplay = true
bus = &"Music"
bus = &"Ambient"
script = ExtResource("5_jiowi")
[node name="AmbientSFX" type="Node3D" parent="."]
@ -83,6 +83,7 @@ script = ExtResource("5_jiowi")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -21, 1, -38)
stream = SubResource("AudioStreamRandomizer_d8fas")
unit_size = 2.0
bus = &"Ambient"
interval_mean = 120.0
interval_st_dev = 30.0
@ -90,6 +91,7 @@ interval_st_dev = 30.0
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 1, -54)
stream = SubResource("AudioStreamRandomizer_d8fas")
unit_size = 2.0
bus = &"Ambient"
interval_mean = 120.0
interval_st_dev = 30.0
@ -97,6 +99,7 @@ interval_st_dev = 30.0
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -27, 1, -54)
stream = SubResource("AudioStreamRandomizer_d8fas")
unit_size = 2.0
bus = &"Ambient"
interval_mean = 120.0
interval_st_dev = 30.0
@ -104,6 +107,7 @@ interval_st_dev = 30.0
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, -77)
stream = SubResource("AudioStreamRandomizer_d8fas")
unit_size = 2.0
bus = &"Ambient"
interval_mean = 120.0
interval_st_dev = 30.0
@ -111,6 +115,7 @@ interval_st_dev = 30.0
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 2, -38)
stream = SubResource("AudioStreamRandomizer_d8fas")
unit_size = 2.0
bus = &"Ambient"
interval_mean = 120.0
interval_st_dev = 30.0

View File

@ -228,7 +228,6 @@ text = ""
[node name="RetroSelectorList" parent="." instance=ExtResource("3_n8ehr")]
unique_name_in_owner = true
offset_bottom = 11.0
[node name="TransitionPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true

View File

@ -1,9 +1,12 @@
extends Tool
## Pump up the jamz!
const RUMBLE_INTENSITY = 0.006
const BIG_RUMBLE = 0.006
const SMALL_RUMBLE = 0.0009
const RUMBLE_DROPOFF = 0.8
const AMBIENT_BUS_IDX = 3
@onready var mp3_controller: MP3Controller = %MP3Controller
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
@onready var rumbler: Rumbler3D = %Rumbler
@ -20,12 +23,12 @@ func unlocked() -> bool:
func fire() -> void:
if not firing:
firing = true
rumbler.intensity = RUMBLE_INTENSITY
rumbler.intensity = BIG_RUMBLE
mp3_controller.select()
func switch_mode() -> void:
rumbler.intensity = RUMBLE_INTENSITY
rumbler.intensity = SMALL_RUMBLE
mp3_controller.cancel()
@ -46,12 +49,15 @@ func _on_mp3_collected(_track: MP3Track) -> void:
func pause_playback() -> void:
audio_stream_player.stream_paused = true
AudioServer.set_bus_mute(AMBIENT_BUS_IDX, false)
func resume_playback() -> void:
audio_stream_player.stream_paused = false
AudioServer.set_bus_mute(AMBIENT_BUS_IDX, true)
func select_track(idx: int) -> void:
audio_stream_player.stream = World.instance.manager.mp3_collection[idx].track
audio_stream_player.play()
AudioServer.set_bus_mute(AMBIENT_BUS_IDX, true)

View File

@ -74,7 +74,7 @@ render_target_update_mode = 4
[node name="ScreenTransform" type="Marker2D" parent="HUDTool/Rumbler/Position/HUDElement/DeviceScreenMask/SubViewportContainer/SubViewport"]
texture_filter = 1
position = Vector2(17.939, -1)
position = Vector2(17.939, -2)
rotation = 0.139626
skew = 0.0331613
@ -85,6 +85,7 @@ offset_bottom = 76.0
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
unique_name_in_owner = true
process_mode = 3
bus = &"Music"
[connection signal="pause" from="HUDTool/Rumbler/Position/HUDElement/DeviceScreenMask/SubViewportContainer/SubViewport/ScreenTransform/MP3Controller" to="." method="pause_playback"]

View File

@ -1,16 +1,17 @@
@tool
class_name RetroSelectorList extends Control
const DEFAULT_HEIGHT := 76.0
const DEFAULT_HEIGHT := 79.0
const LINE_HEIGHT_PX := 11
const LINE_HEIGHT_OFFSET := 1
const SELECTION_SMOOTHING := 8.0
const MAX_LINES := 7
const BLINK_INTERVAL := 0.2
@export var options: Array[String] = []
@export var selection_idx := 0:
set(value):
selection_idx = wrapi(value, 0, options.size())
set = _set_selection_idx
@export var expanded := true:
set(value):
if value != expanded:
@ -22,16 +23,62 @@ const BLINK_INTERVAL := 0.2
@export var tween_scale := 0.24
@export var debug_rebuild := false:
set(value):
if value:
rebuild_list()
var _active_tween: Tween
var _scroll_line := 0
@onready var screen_bounds_container: Control = %ScreenBoundsContainer
@onready var scrolling_container: Control = %ScrollingContainer
@onready var title_list: VBoxContainer = %TitleList
@onready var selection_mask: ColorRect = %SelectionMask
@onready var scroll_arrows: Control = %ScrollArrows
@onready var up_arrow: Label = %UpArrow
@onready var down_arrow: Label = %DownArrow
func _ready() -> void:
rebuild_list()
func _set_selection_idx(value: float) -> void:
selection_idx = wrapi(value, 0, options.size())
_update_scrolling()
func _update_scrolling() -> void:
# Custom scrolling logic
var max_line_idx := MAX_LINES - 1
var rel_selection := selection_idx - _scroll_line
if rel_selection < 0:
_scroll_line = selection_idx
if rel_selection > max_line_idx:
_scroll_line = selection_idx - max_line_idx
if up_arrow:
up_arrow.visible = _scroll_line > 0
if down_arrow:
down_arrow.visible = options.size() - _scroll_line > MAX_LINES
## This is a workaround for an issue with the clipping boundary
func _hide_unselected() -> void:
for i: int in title_list.get_child_count():
if i != selection_idx:
(title_list.get_child(i) as CanvasItem).modulate = Color.TRANSPARENT
func _show_all() -> void:
for n: Node in title_list.get_children():
if n is CanvasItem:
(n as CanvasItem).modulate = Color.WHITE
func rebuild_list() -> void:
# Remove any existing items
for c: Node in title_list.get_children():
@ -44,6 +91,7 @@ func rebuild_list() -> void:
title_list.add_child(item_label)
selection_idx = (selection_idx % options.size()) if options else 0
_update_scrolling()
func _new_tween() -> Tween:
@ -69,6 +117,8 @@ func expand() -> Tween:
. set_ease(Tween.EASE_OUT)
)
_active_tween = tween
_show_all()
scroll_arrows.show()
selection_mask.show()
return tween
@ -89,11 +139,15 @@ func select_and_contract() -> Tween:
func contract() -> Tween:
var tween := _new_tween()
var container_position := -(
(selection_idx - _scroll_line) * LINE_HEIGHT_PX + LINE_HEIGHT_OFFSET
)
tween.tween_callback(scroll_arrows.hide)
tween.set_parallel(true)
(
tween
. tween_property(
screen_bounds_container, "position:y", -selection_mask.position.y, tween_scale * 1.1
screen_bounds_container, "position:y", container_position, tween_scale * 1.1
)
. set_trans(Tween.TRANS_CUBIC)
. set_ease(Tween.EASE_OUT)
@ -104,6 +158,7 @@ func contract() -> Tween:
. set_trans(Tween.TRANS_CUBIC)
. set_ease(Tween.EASE_OUT)
)
tween.chain().tween_callback(_hide_unselected)
return tween
@ -112,3 +167,8 @@ func _process(delta: float) -> void:
selection_mask.position.y = lerpf(
selection_mask.position.y, target_position, 1 - exp(-SELECTION_SMOOTHING * delta)
)
var target_scroll := -_scroll_line * LINE_HEIGHT_PX
scrolling_container.position.y = lerpf(
scrolling_container.position.y, target_scroll, 1 - exp(-SELECTION_SMOOTHING * delta)
)

View File

@ -1,8 +1,70 @@
[gd_scene load_steps=5 format=3 uid="uid://t11xpl4mtgvf"]
[gd_scene load_steps=9 format=3 uid="uid://t11xpl4mtgvf"]
[ext_resource type="Script" uid="uid://qt6hnlakpqob" path="res://src/equipment/mp3_player/retro_selector_list.gd" id="1_kvinm"]
[ext_resource type="Theme" uid="uid://drq4sbm3i6uxt" path="res://src/equipment/mp3_player/player_ui_theme.tres" id="2_4rnpc"]
[ext_resource type="Shader" uid="uid://b6c7d34uvtssk" path="res://src/shaders/canvas_invert.gdshader" id="3_4rnpc"]
[ext_resource type="FontFile" uid="uid://bgy7odoob7xyl" path="res://assets/fonts/Silkscreen/Silkscreen-Bold.ttf" id="4_wabg6"]
[sub_resource type="Animation" id="Animation_f6w0q"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("UpArrow:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(58, 0)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("DownArrow:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(58, 63)]
}
[sub_resource type="Animation" id="Animation_wabg6"]
resource_name = "float"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("UpArrow:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.4, 0.6, 0.9, 1),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 0,
"values": [Vector2(58, 1), Vector2(58, 0), Vector2(58, 0), Vector2(58, 2), Vector2(58, 2), Vector2(58, 1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("DownArrow:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.1, 0.3, 0.6, 0.8, 1),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 0,
"values": [Vector2(58, 64), Vector2(58, 64), Vector2(58, 66), Vector2(58, 66), Vector2(58, 64), Vector2(58, 64)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_1k8u3"]
_data = {
&"RESET": SubResource("Animation_f6w0q"),
&"float": SubResource("Animation_wabg6")
}
[sub_resource type="ShaderMaterial" id="ShaderMaterial_4rnpc"]
shader = ExtResource("3_4rnpc")
@ -16,16 +78,18 @@ clip_contents = true
layout_mode = 3
anchors_preset = 0
offset_right = 70.0
offset_bottom = 76.0
offset_bottom = 79.0
theme = ExtResource("2_4rnpc")
script = ExtResource("1_kvinm")
options = Array[String](["one", "two", "three", "four", "five", "six", "seven", "and me too!", "uwoah!"])
selection_idx = 1
[node name="ScreenBoundsContainer" type="Control" parent="."]
unique_name_in_owner = true
custom_minimum_size = Vector2(70, 76)
custom_minimum_size = Vector2(70, 79)
anchors_preset = 0
offset_right = 70.0
offset_bottom = 76.0
offset_bottom = 79.0
[node name="Background" type="ColorRect" parent="ScreenBoundsContainer"]
layout_mode = 1
@ -36,7 +100,62 @@ grow_horizontal = 2
grow_vertical = 2
color = Color(0.619608, 0.678431, 0.705882, 1)
[node name="TitleList" type="VBoxContainer" parent="ScreenBoundsContainer"]
[node name="MarginContainer" type="MarginContainer" parent="ScreenBoundsContainer"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 1
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 1
[node name="ScrollArrows" type="Control" parent="ScreenBoundsContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
[node name="UpArrow" type="Label" parent="ScreenBoundsContainer/MarginContainer/ScrollArrows"]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -8.0
offset_bottom = 11.0
grow_horizontal = 0
scale = Vector2(1, -1)
pivot_offset = Vector2(0, 5.5)
theme_override_fonts/font = ExtResource("4_wabg6")
text = "v"
[node name="DownArrow" type="Label" parent="ScreenBoundsContainer/MarginContainer/ScrollArrows"]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -8.0
offset_top = -14.0
offset_bottom = -3.0
grow_horizontal = 0
grow_vertical = 0
pivot_offset = Vector2(0, 5.5)
theme_override_fonts/font = ExtResource("4_wabg6")
text = "v"
[node name="AnimationPlayer" type="AnimationPlayer" parent="ScreenBoundsContainer/MarginContainer/ScrollArrows"]
libraries = {
&"": SubResource("AnimationLibrary_1k8u3")
}
autoplay = "float"
[node name="ScrollingContainer" type="Control" parent="ScreenBoundsContainer"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
@ -44,13 +163,21 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="TitleList" type="VBoxContainer" parent="ScreenBoundsContainer/ScrollingContainer"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 88.0
grow_horizontal = 2
theme_override_constants/separation = 0
[node name="SelectionMask" type="ColorRect" parent="ScreenBoundsContainer"]
[node name="SelectionMask" type="ColorRect" parent="ScreenBoundsContainer/ScrollingContainer"]
unique_name_in_owner = true
material = SubResource("ShaderMaterial_4rnpc")
custom_minimum_size = Vector2(70, 11)
layout_mode = 0
offset_top = 1.00001
offset_top = 11.9999
offset_right = 70.0
offset_bottom = 12.0
offset_bottom = 22.9999

View File

@ -1,6 +1,8 @@
class_name World extends Node
## Access and flow control for the game world.
const MUSIC_BUS_IDX := 1
@export var pause_enabled := true
@export var save_state: SaveState
@ -8,6 +10,8 @@ class_name World extends Node
@export var manager: WorldManager
@export var spook_manager: SpookManager
@export var pause_music_effect: AudioEffect
@export_category("Game Scenes")
@export var initial_level: PackedScene
@ -27,7 +31,8 @@ var debug_unlock_next_milestone: bool:
if value:
var milestone := manager.next_milestone()
manager.grunk_vault = manager.next_milestone_amount()
manager.milestone_reached.emit(milestone)
if milestone:
manager.milestone_reached.emit(milestone)
var current_level_scene: PackedScene
var current_level: Level
@ -54,6 +59,9 @@ func _unhandled_input(event: InputEvent) -> void:
func pause() -> void:
# Quiet the music
AudioServer.add_bus_effect(MUSIC_BUS_IDX, pause_music_effect, 0)
get_tree().paused = true
var pause_menu: Control = pause_scene.instantiate()
ui_root.add_child(pause_menu)
@ -63,6 +71,10 @@ func pause() -> void:
func unpause() -> void:
get_tree().paused = false
# Un-quiet the music
# NOTE: if any other bus effects are added while paused, this could become inconsistent
AudioServer.remove_bus_effect(MUSIC_BUS_IDX, 0)
func load_level(level: PackedScene) -> void:
for c: Node in level_root.get_children():

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=3 uid="uid://884jqafhtrv0"]
[gd_scene load_steps=9 format=3 uid="uid://884jqafhtrv0"]
[ext_resource type="Script" uid="uid://cgqmhtemibxc5" path="res://src/world/world.gd" id="1_1k4gi"]
[ext_resource type="Resource" uid="uid://tgac5tnfx56r" path="res://src/world/world_manager.tres" id="2_5kmgb"]
@ -8,10 +8,14 @@
[ext_resource type="PackedScene" uid="uid://c0uitm5cg88h1" path="res://src/ui/menus/kill_screen/kill_screen.tscn" id="6_l0av5"]
[ext_resource type="PackedScene" uid="uid://brknr57xc2cp0" path="res://src/ui/elements/save_icon/save_icon.tscn" id="7_5kmgb"]
[sub_resource type="AudioEffectAmplify" id="AudioEffectAmplify_5kmgb"]
volume_db = -14.0
[node name="World" type="Node"]
script = ExtResource("1_1k4gi")
manager = ExtResource("2_5kmgb")
spook_manager = ExtResource("3_l0av5")
pause_music_effect = SubResource("AudioEffectAmplify_5kmgb")
initial_level = ExtResource("4_5kmgb")
pause_scene = ExtResource("2_6fy3g")
kill_screen_scene = ExtResource("6_l0av5")

View File

@ -28,7 +28,7 @@ metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_veuns"]
script = ExtResource("3_yiuq5")
title = "descending"
title = "catbird"
track = ExtResource("5_dwul7")
metadata/_custom_type_script = "uid://kwiy3dv1h7q7"
@ -65,7 +65,7 @@ metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_h2b4l"]
script = ExtResource("3_yiuq5")
title = "slower"
title = "get worse"
track = ExtResource("8_81w62")
metadata/_custom_type_script = "uid://kwiy3dv1h7q7"
@ -101,7 +101,7 @@ metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_enr7w"]
script = ExtResource("3_yiuq5")
title = "driving02"
title = "bonk"
track = ExtResource("9_gv3bq")
metadata/_custom_type_script = "uid://kwiy3dv1h7q7"
@ -137,7 +137,7 @@ metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_qb1w8"]
script = ExtResource("3_yiuq5")
title = "simple"
title = "gfolf"
track = ExtResource("7_dojbf")
metadata/_custom_type_script = "uid://kwiy3dv1h7q7"
@ -173,7 +173,7 @@ metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_drgdw"]
script = ExtResource("3_yiuq5")
title = "driving01"
title = "bonk jr"
track = ExtResource("6_2q28t")
metadata/_custom_type_script = "uid://kwiy3dv1h7q7"
@ -209,7 +209,7 @@ metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_mwqeg"]
script = ExtResource("3_yiuq5")
title = "gonk"
title = "dr hurt"
track = ExtResource("4_dwul7")
metadata/_custom_type_script = "uid://kwiy3dv1h7q7"
@ -245,7 +245,7 @@ metadata/_custom_type_script = "uid://ufxoxupdvyd5"
[sub_resource type="Resource" id="Resource_l175b"]
script = ExtResource("3_yiuq5")
title = "desert"
title = "coyote"
track = ExtResource("10_63s66")
metadata/_custom_type_script = "uid://kwiy3dv1h7q7"