turntable to play disc

This commit is contained in:
minjaesong
2024-02-08 00:07:19 +09:00
parent ff15a3a8cf
commit 238dbfc3c4
15 changed files with 259 additions and 33 deletions

View File

@@ -62,5 +62,12 @@
"ingredients": [
[1, 20, "$WOOD"] /* 1 chest = 20 wood */
]
},
"item@basegame:30": { /* turntable */
"workbench": "basiccrafting",
"ingredients": [
[1, 4, "item@basegame:144", 14, "$WOOD", 10, "item@basegame:113"] /* 1 turntable = 4 quartz, 14 wood, 10 iron */
]
}
}

View File

@@ -28,6 +28,7 @@ id;classname;tags
27;net.torvald.terrarum.modulebasegame.gameitems.ItemFurnaceAndAnvil;FIXTURE,CRAFTING
28;net.torvald.terrarum.modulebasegame.gameitems.ItemJukebox;FIXTURE,MUSIC
29;net.torvald.terrarum.modulebasegame.gameitems.ItemCharcoal;COMBUSTIBLE
30;net.torvald.terrarum.modulebasegame.gameitems.ItemMusicalTurntable;FIXTURE,MUSIC
# ingots
26;net.torvald.terrarum.modulebasegame.gameitems.IngotSteel;INGOT
@@ -78,15 +79,15 @@ id;classname;tags
# data storage (discs; 256)
# 32768 is a reserved number for a blank disc
32769;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc01;MUSIC
32770;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc02;MUSIC
32771;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc03;MUSIC
32772;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc04;MUSIC
32773;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc05;MUSIC
32774;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc06;MUSIC
32775;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc07;MUSIC
32776;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc08;MUSIC
32777;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09;MUSIC
32769;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc01;MUSIC,PHONO
32770;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc02;MUSIC,PHONO
32771;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc03;MUSIC,PHONO
32772;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc04;MUSIC,PHONO
32773;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc05;MUSIC,PHONO
32774;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc06;MUSIC,PHONO
32775;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc07;MUSIC,PHONO
32776;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc08;MUSIC,PHONO
32777;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09;MUSIC,PHONO
# data storage (tapestries; 256)
#33023;net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry;FIXTURE
1 id classname tags
28 28 net.torvald.terrarum.modulebasegame.gameitems.ItemJukebox FIXTURE,MUSIC
29 29 net.torvald.terrarum.modulebasegame.gameitems.ItemCharcoal COMBUSTIBLE
30 # ingots 30 net.torvald.terrarum.modulebasegame.gameitems.ItemMusicalTurntable FIXTURE,MUSIC
31 # ingots
32 26 net.torvald.terrarum.modulebasegame.gameitems.IngotSteel INGOT
33 112 net.torvald.terrarum.modulebasegame.gameitems.IngotCopper INGOT
34 113 net.torvald.terrarum.modulebasegame.gameitems.IngotIron INGOT
79 32777 net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09 MUSIC MUSIC,PHONO
80 # data storage (tapestries 256)
81 #33023 net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry FIXTURE
82 # fluids on storage
83 # preferably autogenerated
84 # 10000h..100FFh : Fluid type 0 (water) x container type 0..255
85 # 10100h..101FFh : Fluid type 1 (lava) x container type 0..255
86 # 10200h..102FFh : Fluid type 2 (crude oil) x container type 0..255
87 # 10300h..103FFh : Fluid type 3 (petroleum) x container type 0..255
88 # 10400h..104FFh : Fluid type 4 (compressed air) x container type 0..255
89 # 10500h..105FFh : Fluid type 5 (steam) x container type 0..255
90 # ...
91 # 1FF00h..1FFFFh : Fluid type 255 (???) x container type 0..255
92
93

Binary file not shown.

View File

@@ -62,6 +62,7 @@
"ITEM_SMELTER_SMALL": "Small Smelter",
"ITEM_STORAGE_CHEST": "Storage Chest",
"ITEM_TIKI_TORCH": "Tiki Torch",
"ITEM_TURNTABLE": "Turntable",
"ITEM_TYPEWRITER": "Typewriter",
"ITEM_WIRE": "Wire",
"ITEM_WIRE_CUTTER": "Wire Cutter",

View File

@@ -62,6 +62,7 @@
"ITEM_SMELTER_SMALL": "소형 고로",
"ITEM_STORAGE_CHEST": "보관상자",
"ITEM_TIKI_TORCH": "티키 토치",
"ITEM_TURNTABLE": "전축",
"ITEM_TYPEWRITER": "타자기",
"ITEM_WIRE": "전선",
"ITEM_WIRE_CUTTER": "전선 절단기",

Binary file not shown.

View File

@@ -24,7 +24,7 @@ import kotlin.math.tanh
open class LoFi(
staticModule: String, staticPath: String,
irModule: String, irPath: String,
val crossfeed: Float, gain: Float = 1f / 256f
val crossfeed: Float, gain: Float = 1f / 256f, saturationLim: Float = 1f
): TerrarumAudioFilter(), DspCompressor {
override val downForce = arrayOf(1.0f, 1.0f)
@@ -72,8 +72,9 @@ open class LoFi(
* Default function is `tanh(x)`
*/
open fun saturate(v: Float): Float {
return tanh(v)
return K * tanh(v / K)
}
private val K = saturationLim.coerceIn(0f, 1f)
override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) {
convolver.drawDebugView(batch, x, y)

View File

@@ -7,9 +7,9 @@ import net.torvald.terrarum.ModMgr
*
* Created by minjaesong on 2024-01-24.
*/
class Phono(irModule: String, irPath: String, crossfeed: Float, gain: Float) : LoFi(
class Phono(irModule: String, irPath: String, crossfeed: Float, gain: Float, saturationLim: Float) : LoFi(
"basegame", "audio/effects/static/phono_pops.ogg",
irModule, irPath, crossfeed, gain
irModule, irPath, crossfeed, gain, saturationLim
)
/**
@@ -17,9 +17,9 @@ class Phono(irModule: String, irPath: String, crossfeed: Float, gain: Float) : L
*
* Created by minjaesong on 2024-01-24.
*/
class Tape(irModule: String, irPath: String, crossfeed: Float, gain: Float) : LoFi(
class Tape(irModule: String, irPath: String, crossfeed: Float, gain: Float, saturationLim: Float) : LoFi(
"basegame", "audio/effects/static/tape_hiss.ogg",
irModule, irPath, crossfeed, gain
irModule, irPath, crossfeed, gain, saturationLim
)
/**
@@ -29,7 +29,7 @@ class Tape(irModule: String, irPath: String, crossfeed: Float, gain: Float) : Lo
*
* Created by minjaesong on 2024-01-24.
*/
class Holo(irModule: String, irPath: String, crossfeed: Float, gain: Float) : LoFi(
class Holo(irModule: String, irPath: String, crossfeed: Float, gain: Float, saturationLim: Float) : LoFi(
"basegame", "audio/effects/static/film_pops_lowpass.ogg",
irModule, irPath, crossfeed, gain
irModule, irPath, crossfeed, gain, saturationLim
)

View File

@@ -379,6 +379,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
fun hasTag(s: String) = tags.contains(s)
fun hasAllTags(s: List<String>) = tags.containsAll(s)
fun hasAllTagOf(vararg s: String) = s.all { hasTag(it) }
companion object {

View File

@@ -18,6 +18,7 @@ import net.torvald.terrarum.audio.dsp.LoFi
import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.audio.dsp.Phono
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.Hitbox
import net.torvald.terrarum.gameactors.Lightbox
import net.torvald.terrarum.gameitems.ItemID
@@ -217,19 +218,11 @@ class FixtureJukebox : Electric, PlaysMusic {
}
private fun loadConvolver(it: TerrarumAudioMixerTrack?) {
it?.filters?.set(filterIndex, Phono(
"basegame",
"audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin",
0f, 5f / 16f
))
Companion.loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin")
}
private fun unloadConvolver(music: MusicContainer?) {
if (music != null) {
musicTracks[music]?.let {
it.filters[filterIndex] = NullFilter
}
}
Companion.unloadConvolver(this, filterIndex, music)
}
override fun reload() {
@@ -242,8 +235,25 @@ class FixtureJukebox : Electric, PlaysMusic {
override fun dispose() {
App.audioMixerReloadHooks.remove(this)
super.dispose()
// testMusic.gdxMusic.dispose()
// no need to dispose of backlamp and playmech: they share the same texture with the main sprite
}
companion object {
fun loadConvolver(filterIndex: Int, it: TerrarumAudioMixerTrack?, module: String, path: String, gain: Float = 5f / 16f, satLim: Float = 1f) {
it?.filters?.set(filterIndex, Phono(
module,
path,
0f, gain, satLim
))
}
fun unloadConvolver(actor: Actor, filterIndex: Int, music: MusicContainer?) {
if (music != null) {
actor.musicTracks[music]?.let {
it.filters[filterIndex] = NullFilter
}
}
}
}
}

View File

@@ -0,0 +1,181 @@
package net.torvald.terrarum.modulebasegame.gameactors
import com.badlogic.gdx.Gdx
import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.MusicContainer
import net.torvald.terrarum.modulebasegame.TerrarumMusicGovernor
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef
import net.torvald.terrarum.modulebasegame.gameitems.MusicDiscHelper
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
import net.torvald.terrarum.ui.MouseLatch
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
/**
* Created by minjaesong on 2024-02-07.
*/
class FixtureMusicalTurntable : Electric, PlaysMusic {
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
nameFun = { Lang["ITEM_TURNTABLE"] }
)
@Transient var musicNowPlaying: MusicContainer? = null; private set
@Transient private val filterIndex = 0
val musicIsPlaying: Boolean
get() = musicNowPlaying != null
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/turntable.tga")
density = 1400.0
setHitboxDimension(TILE_SIZE * 1, TILE_SIZE * 1, 0, 0)
makeNewSprite(TextureRegionPack(itemImage.texture, TILE_SIZE * 1, TILE_SIZE * 1)).let {
it.setRowsAndFrames(2,2)
it.currentRow = 1
}
actorValue[AVKey.BASEMASS] = 20.0
setWireSinkAt(0, 0, "appliance_power")
setWireConsumptionAt(0, 2, Vector2(80.0, 0.0))
App.audioMixerReloadHooks[this] = {
loadConvolver(musicTracks[musicNowPlaying])
}
despawnHook = {
stopGracefully()
}
}
internal var disc: ItemID? = null
@Transient private val clickLatch = MouseLatch(listOf(App.getConfigInt("config_mousesecondary")))
override val canBeDespawned: Boolean
get() = disc == null
override fun update(delta: Float) {
super.update(delta)
// right click
if (mouseUp) {
clickLatch.latch {
if (disc == null) {
if (INGAME.actorNowPlaying != null) {
val itemOnGrip =
INGAME.actorNowPlaying!!.inventory.itemEquipped.get(GameItem.EquipPosition.HAND_GRIP)
val itemProp = ItemCodex[itemOnGrip]
if (itemProp?.hasAllTagOf("MUSIC", "PHONO") == true) {
disc = itemOnGrip
INGAME.actorNowPlaying!!.removeItem(itemOnGrip!!)
playDisc()
}
}
}
else {
stopGracefully()
PickaxeCore.dropItem(
disc!!,
intTilewiseHitbox.canonicalX.toInt(),
intTilewiseHitbox.canonicalY.toInt()
)
disc = null
}
}
}
// supress the normal background music playback
if (musicIsPlaying && !flagDespawn) {
(INGAME.musicGovernor as TerrarumMusicGovernor).stopMusic(this, true)
}
}
fun playDisc() {
if (disc == null) return
App.printdbg(this, "Play disc!")
val musicFile = (ItemCodex[disc] as? ItemFileRef)?.getAsGdxFile()
if (musicFile != null) {
val (title, artist) = MusicDiscHelper.getMetadata(musicFile)
App.printdbg(this, "Title: $title, artist: $artist")
musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) {
unloadConvolver(musicNowPlaying)
musicNowPlaying?.gdxMusic?.tryDispose()
musicNowPlaying = null
App.printdbg(this, "Stop music $title - $artist")
// can't call stopDiscPlayback() because of the recursion
(INGAME.musicGovernor as TerrarumMusicGovernor).stopMusic(this, pauseLen = (INGAME.musicGovernor as TerrarumMusicGovernor).getRandomMusicInterval())
}
App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 2f) {
startAudio(musicNowPlaying!!) { loadConvolver(it) }
}
(sprite as SheetSpriteAnimation).currentRow = 0
}
}
/**
* Try to stop the disc being played, and reset the background music cue
*/
fun stopGracefully() {
stopDiscPlayback()
(INGAME.musicGovernor as TerrarumMusicGovernor).stopMusic(this, pauseLen = (INGAME.musicGovernor as TerrarumMusicGovernor).getRandomMusicInterval())
}
private fun stopDiscPlayback() {
musicNowPlaying?.let {
stopAudio(it)
unloadConvolver(it)
}
(sprite as SheetSpriteAnimation).currentRow = 1
}
private fun loadConvolver(it: TerrarumAudioMixerTrack?) {
FixtureJukebox.loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - small_speaker_Gallien Krueger GK 250ML B5 Left A 230 200 320.bin", 3.5f / 16f, 0.8f)
}
private fun unloadConvolver(music: MusicContainer?) {
FixtureJukebox.unloadConvolver(this, filterIndex, music)
}
override fun reload() {
super.reload()
// cannot resume playback, just stop the music
musicNowPlaying = null
}
override fun dispose() {
App.audioMixerReloadHooks.remove(this)
super.dispose()
// no need to dispose of backlamp and playmech: they share the same texture with the main sprite
}
}

View File

@@ -19,4 +19,21 @@ class ItemJukebox(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_JUKEBOX"
}
/**
* Created by minjaesong on 2024-02-07.
*/
class ItemMusicalTurntable(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureMusicalTurntable") {
override var baseMass = 20.0
override val isDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(7,3)
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_TURNTABLE"
}

View File

@@ -127,8 +127,8 @@ internal class UnsafePtr(pointer: Long, allocSize: Long) {
// appear (e.g. getting garbage values when it fucking shouldn't)
// using ifs instead of assertions: inactive assert statements still slows down the app
if (destroyed) { throw DanglingPointerException("The pointer is already destroyed ($this)") }
if (index !in 0 until size) { throw AddressOverflowException("Index: $index; alloc size: $size") }
// if (destroyed) { throw DanglingPointerException("The pointer is already destroyed ($this)") }
// if (index !in 0 until size) { throw AddressOverflowException("Index: $index; alloc size: $size") }
}
operator fun get(index: Long): Byte {

Binary file not shown.