#229 - a volley got louder for every ship in it. Every hull owns its gun and asks for its own shot sound, so eight ships firing on the same cooldown started eight voices playing the SAME sample in the same frame. Those amplitudes add, so a full fleet was the loudest thing in the game by a wide margin. play() now takes a per-sound coalescing window. A volley is one event to the ear, so it gets one voice. 70ms, which the test checks is inside the fastest gun's 500ms cooldown - it collapses "six guns at once", never "six shots in a row". PICKUP and ASTEROID_BREAK get one too: ore arrives in bursts when a rock breaks and that is one pickup to the ear. Deaths and the boss scream are left alone deliberately - several things dying together IS several events. test_sfx's pool-saturation case was driven by shots, which can no longer saturate anything by design. It is driven by deaths now, which is what the pool actually has to absorb, and it gained a case asserting a volley takes one voice - measured against the real pool rather than the gate. #234 - gas was not reliably in reach of the opening. Gas giants are gated behind two independent noise fields, the SPACE biome AND the planet roll, so whether any sat near the spawn was luck. Measured, this seed lost: ZERO gas planets within four chunks, the nearest five away past five rocky ones. Gas is an early need - the burner, ammunition - so the opening cannot depend on the noise being kind. SPAWN_GAS_GIANT_CHUNK at (2, -2), authored like OCTOPUS_BIOME_CENTER rather than found by searching outward: a fixed chunk is reproducible from anywhere without walking the map, which is what the rest of WorldGen is built on. The override is applied AFTER every rng draw, for the same reason the dev planting is - forcing one chunk must not shift what any other chunk rolls. Confirmed by probe: the five other planets within four chunks are identical before and after, and the distant gas giants at (-5,-4) and (0,-5) are still where they were. Both verified in reverse: without the window, "8 ships firing together started 8 shot sounds"; without the chunk, "no gas planet within 4 chunks of the spawn". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
This commit is contained in:
parent
f2309ea1c2
commit
885f977768
5 changed files with 312 additions and 4 deletions
|
|
@ -193,23 +193,39 @@ func _process(delta: float) -> bool:
|
|||
if _pool() != null and _sounding() > 0:
|
||||
return _fail("something was already sounding before anything happened")
|
||||
|
||||
# --- B. a shot, and then far more than there are voices --
|
||||
# --- B. more at once than there are voices ---------------
|
||||
Sfx.play(self, Sfx.SHOT)
|
||||
if _sounding() != 1:
|
||||
return _fail("firing played %d sounds, expected 1" % _sounding())
|
||||
if _pool().get_parent() != root:
|
||||
return _fail("the sound pool hangs off the scene - a death would take it with it")
|
||||
# Driven by a DEATH, not a shot. #229 coalesces shots - a volley
|
||||
# is one event to the ear and now gets one voice - so shots can
|
||||
# no longer saturate anything. Deaths carry no window, because
|
||||
# several things dying together really is several events, and
|
||||
# they are what the pool has to absorb now.
|
||||
for i in range(Sfx.VOICES * 3):
|
||||
Sfx.play(self, Sfx.SHOT)
|
||||
Sfx.play(self, Sfx.SHIP_DEATH)
|
||||
var busy: int = _sounding()
|
||||
if busy != Sfx.VOICES:
|
||||
return _fail("%d voices sounding after %d shots, the pool holds %d" \
|
||||
return _fail("%d voices sounding after %d deaths, the pool holds %d" \
|
||||
% [busy, Sfx.VOICES * 3, Sfx.VOICES])
|
||||
if _pool().get_child_count() != Sfx.VOICES:
|
||||
return _fail("the pool grew to %d voices" % _pool().get_child_count())
|
||||
print("%d shots into a %d-voice pool: %d sounding, none leaked" \
|
||||
print("%d deaths into a %d-voice pool: %d sounding, none leaked" \
|
||||
% [Sfx.VOICES * 3, Sfx.VOICES, busy])
|
||||
|
||||
# --- G. and a volley does not stack (#229) ----------------
|
||||
for voice in _pool().get_children():
|
||||
(voice as AudioStreamPlayer).stop()
|
||||
Sfx._last_started_msec.clear()
|
||||
for i in range(Sfx.VOICES * 3):
|
||||
Sfx.play(self, Sfx.SHOT)
|
||||
if _sounding() != 1:
|
||||
return _fail("%d simultaneous shots took %d voices - that is the volley getting louder per ship" \
|
||||
% [Sfx.VOICES * 3, _sounding()])
|
||||
print("%d simultaneous shots still take 1 voice" % (Sfx.VOICES * 3))
|
||||
|
||||
# --- F. and a dialog does not silence it -----------------
|
||||
for voice in _pool().get_children():
|
||||
(voice as AudioStreamPlayer).stop()
|
||||
|
|
|
|||
Loading…
Reference in a new issue