fix: explosion cuts off randomly

This commit is contained in:
minjaesong
2024-02-17 00:30:04 +09:00
parent ffd470f2b4
commit 9caf9ab2fa
12 changed files with 110 additions and 41 deletions

Binary file not shown.

View File

@@ -340,10 +340,11 @@ Sound from <https://freesound.org/people/DrinkingWindGames>
℗ 2019 Richwise ℗ 2019 Richwise
Sound from <https://freesound.org/people/richwise> Sound from <https://freesound.org/people/richwise>
- effects/explosion/bang_small.ogg - effects/explosion/fuse.ogg
- effects/explosion/fuse_continue.ogg
℗ 2009 Superex1110 ℗ 2012, 2015 j1987 and ScouseMouseJB
Sound from <https://freesound.org/people/Superex1110/> Sound from <https://freesound.org/people/j1987> and <https://freesound.org/people/ScouseMouseJB>

View File

@@ -453,9 +453,9 @@ class AudioMixer : Disposable {
} }
fun startAmb(song: MusicContainer) { fun startAmb(song: MusicContainer) {
val ambientTrack = if (!ambientTrack1.streamPlaying) val ambientTrack = if (!ambientTrack1.streamPlaying.get())
ambientTrack1 ambientTrack1
else if (!ambientTrack2.streamPlaying) else if (!ambientTrack2.streamPlaying.get())
ambientTrack2 ambientTrack2
else if (ambientTrack1.playStartedTime < ambientTrack2.playStartedTime) else if (ambientTrack1.playStartedTime < ambientTrack2.playStartedTime)
ambientTrack1 ambientTrack1

View File

@@ -181,8 +181,15 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
// fetch deviceBufferSize amount of sample from the disk // fetch deviceBufferSize amount of sample from the disk
if (track.trackType != TrackType.MASTER && track.trackType != TrackType.BUS && track.streamPlaying) { if (track.playRequested.get()) {
if (streamBuf == null && track.currentTrack != null) allocateStreamBuf(track) track.play()
}
if (track.trackType != TrackType.MASTER && track.trackType != TrackType.BUS && track.streamPlaying.get()) {
if (streamBuf == null && track.currentTrack != null) {
allocateStreamBuf(track)
}
streamBuf!!.fetchBytes() streamBuf!!.fetchBytes()
} }
@@ -208,7 +215,7 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
} }
// source channel: skip processing if there's no active input // source channel: skip processing if there's no active input
// else if (track.getSidechains().any { it != null && !it.isBus && !it.isMaster && !it.streamPlaying } && !track.streamPlaying) { // else if (track.getSidechains().any { it != null && !it.isBus && !it.isMaster && !it.streamPlaying } && !track.streamPlaying) {
else if (!track.streamPlaying || streamBuf == null || streamBuf!!.validSamplesInBuf < App.audioBufferSize) { else if (!track.streamPlaying.get() || streamBuf == null || streamBuf!!.validSamplesInBuf < App.audioBufferSize) {
samplesL1 = emptyBuf samplesL1 = emptyBuf
samplesR1 = emptyBuf samplesR1 = emptyBuf

View File

@@ -41,13 +41,13 @@ data class MusicContainer(
is Wav.Music -> { is Wav.Music -> {
val rate = gdxMusic.extortField<Wav.WavInputStream>("input")!!.sampleRate val rate = gdxMusic.extortField<Wav.WavInputStream>("input")!!.sampleRate
App.printdbg(this, "music $name is WAV; rate = $rate") // App.printdbg(this, "music $name is WAV; rate = $rate")
rate rate
} }
is Ogg.Music -> { is Ogg.Music -> {
val rate = gdxMusic.extortField<OggInputStream>("input")!!.sampleRate val rate = gdxMusic.extortField<OggInputStream>("input")!!.sampleRate
App.printdbg(this, "music $name is OGG; rate = $rate") // App.printdbg(this, "music $name is OGG; rate = $rate")
rate rate
} }
is Mp3.Music -> { is Mp3.Music -> {
@@ -62,11 +62,11 @@ data class MusicContainer(
// val rate = header.sampleRate // val rate = header.sampleRate
// gdxMusic.reset() // gdxMusic.reset()
App.printdbg(this, "music $name is MP3; rate = $rate") // App.printdbg(this, "music $name is MP3; rate = $rate")
rate rate
} }
else -> { else -> {
App.printdbg(this, "music $name is ${gdxMusic::class.qualifiedName}; rate = default") // App.printdbg(this, "music $name is ${gdxMusic::class.qualifiedName}; rate = default")
TerrarumAudioMixerTrack.SAMPLING_RATE TerrarumAudioMixerTrack.SAMPLING_RATE
} }
} }

View File

@@ -5,11 +5,14 @@ import com.badlogic.gdx.backends.lwjgl3.audio.OpenALLwjgl3Audio
import com.badlogic.gdx.utils.Disposable import com.badlogic.gdx.utils.Disposable
import com.badlogic.gdx.utils.Queue import com.badlogic.gdx.utils.Queue
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.audio.dsp.TerrarumAudioFilter import net.torvald.terrarum.audio.dsp.TerrarumAudioFilter
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.getHashStr import net.torvald.terrarum.getHashStr
import net.torvald.terrarum.hashStrMap import net.torvald.terrarum.hashStrMap
import net.torvald.terrarum.printStackTrace
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.math.log10 import kotlin.math.log10
import kotlin.math.pow import kotlin.math.pow
@@ -60,7 +63,7 @@ class TerrarumAudioMixerTrack(
var trackingTarget: Actor? = null var trackingTarget: Actor? = null
internal var streamPlaying = false internal val streamPlaying = AtomicBoolean(false)
var playStartedTime = 0L; internal set var playStartedTime = 0L; internal set
@@ -70,7 +73,7 @@ class TerrarumAudioMixerTrack(
other.nextTrack = this.nextTrack other.nextTrack = this.nextTrack
other.volume = this.volume other.volume = this.volume
other.trackingTarget = this.trackingTarget other.trackingTarget = this.trackingTarget
other.streamPlaying = this.streamPlaying other.streamPlaying.set(this.streamPlaying.get())
other.playStartedTime = this.playStartedTime other.playStartedTime = this.playStartedTime
filters.indices.forEach { i -> filters.indices.forEach { i ->
other.filters[i].copyParamsFrom(this.filters[i]) other.filters[i].copyParamsFrom(this.filters[i])
@@ -133,15 +136,18 @@ class TerrarumAudioMixerTrack(
nextTrack = nextNext nextTrack = nextNext
} }
val playRequested = AtomicBoolean(false)
fun play() { fun play() {
playStartedTime = System.nanoTime() playStartedTime = System.nanoTime()
streamPlaying = true streamPlaying.set(true)
playRequested.set(false)
// currentTrack?.gdxMusic?.play() // currentTrack?.gdxMusic?.play()
} }
val isPlaying: Boolean val isPlaying: Boolean
get() = streamPlaying//currentTrack?.gdxMusic?.isPlaying get() = streamPlaying.get()//currentTrack?.gdxMusic?.isPlaying
override fun dispose() { override fun dispose() {
/*if (isMaster) { // uncomment to multithread /*if (isMaster) { // uncomment to multithread
@@ -158,7 +164,7 @@ class TerrarumAudioMixerTrack(
fun stop() { fun stop() {
currentTrack?.reset() currentTrack?.reset()
streamPlaying = false streamPlaying.set(false)
// playStartedTime = 0L // playStartedTime = 0L
if (trackingTarget != null && currentTrack != null) { if (trackingTarget != null && currentTrack != null) {

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.gameactors
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.INGAME import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.audio.MusicContainer
@@ -12,6 +13,9 @@ import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.savegame.toBigEndian import net.torvald.terrarum.savegame.toBigEndian
import net.torvald.terrarum.utils.PasswordBase32 import net.torvald.terrarum.utils.PasswordBase32
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
typealias ActorID = Int typealias ActorID = Int
@@ -72,6 +76,8 @@ abstract class Actor : Comparable<Actor>, Runnable {
@Transient open val canBeDespawned = true @Transient open val canBeDespawned = true
@Volatile internal var despawned = false @Volatile internal var despawned = false
@Transient open val stopMusicOnDespawn = true
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other == null) return false if (other == null) return false
@@ -105,8 +111,12 @@ abstract class Actor : Comparable<Actor>, Runnable {
musicTracks1.forEach { name -> musicTracks1.forEach { name ->
val it = App.audioMixer.dynamicTracks[name.substring(2).toInt() - 1] val it = App.audioMixer.dynamicTracks[name.substring(2).toInt() - 1]
println("stop track $name") printdbg(this, "stop track $name")
it.stop()
if (stopMusicOnDespawn) {
it.stop()
}
it.filters[0] = NullFilter it.filters[0] = NullFilter
it.filters[1] = NullFilter it.filters[1] = NullFilter
it.processor.streamBuf?.pitch = 1f it.processor.streamBuf?.pitch = 1f
@@ -149,6 +159,7 @@ abstract class Actor : Comparable<Actor>, Runnable {
if (track != null) { if (track != null) {
musicTracks[music] = track musicTracks[music] = track
musicTracks1.add(track.name) musicTracks1.add(track.name)
track.stop()
} }
} }
@@ -161,14 +172,20 @@ abstract class Actor : Comparable<Actor>, Runnable {
* To loop the audio, set `music.gdxMusic.isLooping` to `true` * To loop the audio, set `music.gdxMusic.isLooping` to `true`
*/ */
open fun startAudio(music: MusicContainer, volume: TrackVolume = 1.0, doSomethingWithTrack: (TerrarumAudioMixerTrack) -> Unit = {}) { open fun startAudio(music: MusicContainer, volume: TrackVolume = 1.0, doSomethingWithTrack: (TerrarumAudioMixerTrack) -> Unit = {}) {
getTrackByAudio(music)?.let { getTrackByAudio(music).let {
it.stop() if (it == null) {
it.trackingTarget = this printdbg(this, "cannot startAudio $music")
it.currentTrack = music }
it.maxVolumeFun = { volume } else {
it.volume = volume printdbg(this, "startAudio $music")
doSomethingWithTrack(it) it.trackingTarget = this
it.play() it.currentTrack = music
it.maxVolumeFun = { volume }
it.volume = volume
doSomethingWithTrack(it)
// it.play()
it.playRequested.set(true)
}
} }
} }
@@ -177,9 +194,15 @@ abstract class Actor : Comparable<Actor>, Runnable {
}*/ }*/
open fun stopAudio(music: MusicContainer, doSomethingWithTrack: (TerrarumAudioMixerTrack) -> Unit = {}) { open fun stopAudio(music: MusicContainer, doSomethingWithTrack: (TerrarumAudioMixerTrack) -> Unit = {}) {
musicTracks[music]?.let { musicTracks[music].let {
doSomethingWithTrack(it) if (it == null) {
it.stop() // printdbg(this, "cannot stopAudio $music")
}
else {
// printdbg(this, "stopAudio $music")
doSomethingWithTrack(it)
it.stop()
}
} }
} }

View File

@@ -54,14 +54,14 @@ object ExplosionManager {
Thread { Thread {
while (true) { while (true) {
try { try {
val job = runners.first { !it.executed } runners.toList().firstOrNull { !it.executed }?.let { job ->
val executor = Executors.newSingleThreadExecutor() val executor = Executors.newSingleThreadExecutor()
executor.submit(job.runner).get(500L, TimeUnit.MILLISECONDS) executor.submit(job.runner).get(500L, TimeUnit.MILLISECONDS)
executor.shutdownNow() executor.shutdownNow()
job.executed = true job.executed = true
}
} }
catch (_: TimeoutException) { } catch (_: TimeoutException) { }
catch (_: NoSuchElementException) { }
Thread.sleep(50L) Thread.sleep(50L)
} }

View File

@@ -38,10 +38,36 @@ open class ActorPrimedBomb(
) { ) {
this.flagDespawn() this.flagDespawn()
} }
@Transient private val fuseSound = MusicContainer(
"fuse", ModMgr.getFile("basegame", "audio/effects/explosion/fuse.ogg")
) {
this.flagDespawn()
}
@Transient private val fuseSoundCont = MusicContainer(
"fuse_continue", ModMgr.getFile("basegame", "audio/effects/explosion/fuse_continue.ogg")
) {
this.flagDespawn()
}
private var fuseSoundStatus = 0 // this value must be stored into the savegame
@Transient private var fuseSoundFired = false
override val stopMusicOnDespawn: Boolean
get() = this.isVisible
override fun updateImpl(delta: Float) { override fun updateImpl(delta: Float) {
super.updateImpl(delta) super.updateImpl(delta)
if (!fuseSoundFired && fuse > 0f) {
fuseSoundFired = true
if (fuseSoundStatus == 0) {
startAudio(fuseSound, 2.0)
fuseSoundStatus = 1
}
else
startAudio(fuseSoundCont, 2.0)
}
fuse -= delta fuse -= delta
if (fuse <= 0f && !explosionCalled) { if (fuse <= 0f && !explosionCalled) {
@@ -57,6 +83,7 @@ open class ActorPrimedBomb(
) { ) {
physProp.usePhysics = false physProp.usePhysics = false
this.isVisible = false // or play explosion anim this.isVisible = false // or play explosion anim
stopAudio(fuseSound)
startAudio(boomSound, 10.0) startAudio(boomSound, 10.0)
} }
} }
@@ -65,6 +92,8 @@ open class ActorPrimedBomb(
override fun dispose() { override fun dispose() {
super.dispose() super.dispose()
boomSound.dispose() boomSound.dispose()
fuseSound.dispose()
fuseSoundCont.dispose()
} }
} }

View File

@@ -805,7 +805,7 @@ class BasicDebugInfoWindow : UICanvas() {
drawFaderHandle(batch, sliderX.toFloat(), faderY + 18f + meterHeight - faderKnobDbFs * meterHeight) drawFaderHandle(batch, sliderX.toFloat(), faderY + 18f + meterHeight - faderKnobDbFs * meterHeight)
// currently streaming // currently streaming
if (track.streamPlaying) { if (track.streamPlaying.get()) {
batch.color = ICON_GREEN batch.color = ICON_GREEN
App.fontSmallNumbers.draw(batch, "\u00C0", x + 17f, faderY + 1f) App.fontSmallNumbers.draw(batch, "\u00C0", x + 17f, faderY + 1f)
} }