Refactor audio effect handling: remove cooldown logic and enhance sound playback functionality

This commit is contained in:
Kirill
2026-10-03 13:36:33 +03:00
parent 9e13c8bbe3
commit 6f6a1be3bd
8 changed files with 58 additions and 22 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ const EFFECTS: Dictionary = {
"select": preload("res://sound/effects/select.ogg"),
"star_birth": preload("res://sound/effects/star_birth.ogg"),
"structure_decay": preload("res://sound/effects/structure_decay.ogg"),
"swipe": preload("res://sound/effects/swipe.ogg"),
#"swipe": preload("res://sound/effects/swipe.ogg"),
"time_minus": preload("res://sound/effects/time_minus.ogg"),
"time_plus": preload("res://sound/effects/time_plus.ogg"),
"trend_action": preload("res://sound/effects/trend_action.ogg"),
+23 -1
View File
@@ -94,6 +94,7 @@ var g_active_items: Dictionary = {}
var pending_page: int = -1
var active_actions_dirty: bool = true
var active_actions_elapsed: float = 0.0
var interface_sounds_enabled: bool = false
var owniverse:Owniverse = Owniverse.new()
var owniverse_items: Dictionary[String, OwniverseItem] = {}
@@ -323,6 +324,11 @@ func _ready() -> void:
for pa in page_actions:
page_actions[pa].action_pressed.connect(_page_action_pressed)
page_actions[pa].page_id = pa
_enable_interface_sounds.call_deferred()
func _enable_interface_sounds() -> void:
interface_sounds_enabled = true
## Starts a fresh universe. Can be connected directly to a button's pressed signal.
@@ -398,10 +404,15 @@ func _process(delta: float) -> void:
func _change_speed(delta: int) -> void:
var previous_speed: int = owniverse.speed
owniverse.speed = owniverse.speed + delta
var speed: int = owniverse.speed
if speed > previous_speed:
effects_player.play_effect("time_plus")
elif speed < previous_speed:
effects_player.play_effect("time_minus")
var ind: int = 1
for icon in g_speed_icons:
if ind <= speed:
@@ -421,6 +432,17 @@ func _change_speed(delta: int) -> void:
func _on_topmenu_button_pressed(screen_name: String) -> void:
var current_screen: String = ""
for screen_id in screens:
if screens[screen_id].visible:
current_screen = screen_id
break
if current_screen == screen_name:
return
if interface_sounds_enabled:
effects_player.play_effect("window_close" if screen_name == "World" else "window_open")
for screen_id in screens:
#print(screen_name, " ←→ ", screen_id)
+4 -7
View File
@@ -25,17 +25,14 @@ func run() -> void:
check(not player.play_effect("select"), "Playing effect is not restarted")
check(player.stream == selected_stream and player.playing, "Rejected duplicate keeps current playback")
player.stop()
check(not player.play_effect("select"), "Named effect is rejected during its two-second cooldown")
check(player.play_effect("blast"), "Different effect starts without waiting for another name")
player.stop()
player._last_played_msec.select -= player.EFFECT_COOLDOWN_MSEC
check(player.play_effect("select"), "Named effect starts after its cooldown")
check(player.play_effect("select"), "Stopped effect can start again immediately")
check(player.play_effect("blast"), "Different effect starts immediately")
check(not player.play_effect("missing_effect"), "Unknown effect is rejected")
check(player.stream == player._effects.select, "Unknown effect does not interrupt playback")
check(player.stream == player._effects.blast, "Unknown effect does not interrupt playback")
player.set_enabled(false)
check(player.stream_paused, "Disabling effects pauses current playback")
check(not player.play_effect("blast") and player.stream == player._effects.select, "Disabled player rejects new effects")
check(not player.play_effect("select") and player.stream == player._effects.blast, "Disabled player rejects new effects")
player.set_enabled(true)
check(not player.stream_paused, "Enabling effects resumes current playback")
+13 -2
View File
@@ -176,8 +176,19 @@ func run() -> void:
world.state.amount.Met = 100
world.state.auto_resources.H = 100
world.evolute(E.of("0.1"))
check((E.eq(world.state.amount.RD, 101) and E.eq(world.state.amount.H, 0)), "Automatic formation uses its resource budget")
check(E.ge(world.state.binds.RD.HP, 1), "Automatic formation also creates planets")
check((E.eq(world.state.amount.RD, 1) and E.eq(world.state.amount.H, 100)), "Automatic formation cannot spend hydrogen retained from an earlier cycle")
check(E.eq(world.state.auto_resources.get("H", 0), 0), "Unused automatic hydrogen becomes an ordinary free resource")
dispose(world)
world = fixture()
world.catalog.entities.N.auto = 1
world.state.amount.RD = 1
world.state.amount.H = 100
world.state.amount.Met = 100
world.evolute(100)
check(E.gt(world.state.amount.RD, 1), "Automatic formation can spend newly produced hydrogen")
check(E.ge(world.state.amount.H, 100), "Automatic formation preserves hydrogen available before the cycle")
check(E.ge(world.state.binds.get("RD", {}).get("HP", 0), 1), "Automatic formation also creates planets")
dispose(world)
world = fixture()
+11
View File
@@ -21,6 +21,7 @@ func run() -> void:
root.add_child(scene)
await process_frame
await process_frame
check(stage.effects_player.stream == null, "Startup does not play a UI sound")
stage.stage_page_scroller.scroll_horizontal = stage.PAGE_WIDTH
await process_frame
stage.owniverse.state.amount.H = 1000
@@ -54,6 +55,16 @@ func run() -> void:
stage.owniverse.state.time.year = E.of("1234.5")
stage._refresh_universe_ui()
check(E.eq(stage.date_time.text, "1 234.5"), "Time displays tenths with thousands separator")
stage.effects_player.set_enabled(true)
stage.owniverse.speed = 1
stage._change_speed(1)
check(stage.effects_player.stream == stage.effects_player._effects.time_plus, "Increasing speed plays its effect")
stage._change_speed(-1)
check(stage.effects_player.stream == stage.effects_player._effects.time_minus, "Decreasing speed plays its effect")
stage._on_topmenu_button_pressed("MainMenu")
check(stage.effects_player.stream == stage.effects_player._effects.window_open, "Opening a window plays its effect")
stage._on_topmenu_button_pressed("World")
check(stage.effects_player.stream == stage.effects_player._effects.window_close, "Closing a window plays its effect")
for entity in stage.owniverse.catalog.entities.values(): entity.free()
stage.owniverse.free()
scene.free()
-7
View File
@@ -1,11 +1,8 @@
class_name OwniverseEffectsPlayer
extends AudioStreamPlayer
const EFFECT_COOLDOWN_MSEC := 2000
var enabled: bool = true
var _effects: Dictionary = OwniverseAudioLoader.get_effects()
var _last_played_msec: Dictionary = {}
func set_enabled(value: bool) -> void:
@@ -21,11 +18,7 @@ func play_effect(effect_id: String) -> bool:
return false
if playing and stream == _effects[effect_id]:
return false
var now: int = Time.get_ticks_msec()
if now - int(_last_played_msec.get(effect_id, -EFFECT_COOLDOWN_MSEC)) < EFFECT_COOLDOWN_MSEC:
return false
stream = _effects[effect_id]
play()
_last_played_msec[effect_id] = now
return true
+2 -2
View File
@@ -2,8 +2,8 @@ class_name OwniverseMusicPlayer
extends AudioStreamPlayer
const EXCLUDED_TRACK := "apocalypse_the_end"
const MIN_PAUSE_SECONDS := 120.0
const MAX_PAUSE_SECONDS := 300.0
const MIN_PAUSE_SECONDS := 2 * 60.0
const MAX_PAUSE_SECONDS := 5 * 60.0
var enabled: bool = true
var last_track: String = ""
+4 -2
View File
@@ -58,8 +58,10 @@ func produce_for_period(previous: Dictionary, target: Dictionary, quantities: Di
amount = world.ledger.credit(target, id, amount)
world.batches.append_batch(target, id, amount, from_year, to_year)
# Keep unused automatic resources across cycles; they are part of free amounts.
var budget: Dictionary = previous.get("auto_resources", {}).duplicate(true)
# Automation may spend only the automatic output produced during this cycle.
# Any unused part becomes an ordinary free resource on the next cycle instead
# of remaining eligible for later automatic production.
var budget: Dictionary = {}
for id in automatic:
budget[id] = E.add(budget.get(id, 0), automatic[id])
for id in budget: