Skip to content

Commit

Permalink
Added Sound and Music support
Browse files Browse the repository at this point in the history
  • Loading branch information
darkfrog26 committed Sep 5, 2023
1 parent 340d684 commit 490acf5
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 0 deletions.
2 changes: 2 additions & 0 deletions core/src/main/scala/org/sgine/UI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl3.{Lwjgl3Application, Lwjgl3ApplicationConfiguration}
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.g2d.BitmapFont
import org.sgine.audio.Audio
import org.sgine.task.TaskSupport
import reactify._

Expand Down Expand Up @@ -61,6 +62,7 @@ object UI extends gdx.Screen with TaskSupport { ui =>
inputProcessor.checkOver()
}
}
updates.attach(Audio.update)
new Lwjgl3Application(game, config)
}

Expand Down
36 changes: 36 additions & 0 deletions core/src/main/scala/org/sgine/audio/Audio.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.sgine.audio

import com.badlogic.gdx.Gdx
import org.sgine.update.UpdateSupport

object Audio extends UpdateSupport {
private var entries: List[AudioElement] = Nil

private def add(entry: AudioElement): Unit = synchronized {
entries = entry :: entries
}

private[audio] def remove(entry: AudioElement): Unit = synchronized {
entries = entries.filterNot(_ eq entry)
}

def sound(path: String): Sound = {
val gdxSound = Gdx.audio.newSound(Gdx.files.internal(path))
val sound = new Sound(gdxSound)
add(sound)
sound
}

def music(path: String): Music = {
val gdxMusic = Gdx.audio.newMusic(Gdx.files.internal(path))
val music = new Music(gdxMusic)
add(music)
music
}

override def update(delta: Double): Unit = {
super.update(delta)

entries.foreach(_.update(delta))
}
}
7 changes: 7 additions & 0 deletions core/src/main/scala/org/sgine/audio/AudioElement.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.sgine.audio

import org.sgine.update.UpdateSupport

trait AudioElement extends UpdateSupport {
def dispose(): Unit = Audio.remove(this)
}
53 changes: 53 additions & 0 deletions core/src/main/scala/org/sgine/audio/Music.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.sgine.audio

import com.badlogic.gdx.audio
import reactify.{Trigger, Val, Var}

class Music(gdx: com.badlogic.gdx.audio.Music) extends AudioElement {
private val _playing: Var[Boolean] = Var(false)
private val _position: Var[Double] = Var(0.0)

val position: Val[Double] = _position

def position_=(v: Double): Unit = gdx.setPosition(v.toFloat)

lazy val looping: Var[Boolean] = {
val v = Var(gdx.isLooping)
v.attach(gdx.setLooping)
v
}

lazy val volume: Var[Double] = {
val v = Var(gdx.getVolume.toDouble)
v.attach(d => gdx.setVolume(d.toFloat))
v
}

lazy val pan: Var[Double] = {
val v = Var(0.0)
v.attach(d => gdx.setPan(d.toFloat, volume().toFloat))
v
}

val finished: Trigger = Trigger()

def play(): Unit = gdx.play()

def pause(): Unit = gdx.pause()

def stop(): Unit = gdx.stop()

gdx.setOnCompletionListener((_: audio.Music) => finished.trigger())

override def update(delta: Double): Unit = {
super.update(delta)

_playing @= gdx.isPlaying
_position @= gdx.getPosition.toDouble
}

override def dispose(): Unit = {
gdx.dispose()
super.dispose()
}
}
26 changes: 26 additions & 0 deletions core/src/main/scala/org/sgine/audio/Sound.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.sgine.audio

class Sound(private[audio] val gdx: com.badlogic.gdx.audio.Sound) extends AudioElement {
def play(volume: Double = 1.0,
pitch: Double = 1.0,
pan: Double = 0.0,
loop: Boolean = false): SoundInstance = {
val id = if (loop) {
gdx.loop(volume.toFloat, pitch.toFloat, pan.toFloat)
} else {
gdx.play(volume.toFloat, pitch.toFloat, pan.toFloat)
}
new SoundInstance(this, id, volume, pitch, pan, loop)
}

def stop(): Unit = gdx.stop()

def pause(): Unit = gdx.pause()

def resume(): Unit = gdx.resume()

override def dispose(): Unit = {
gdx.dispose()
super.dispose()
}
}
42 changes: 42 additions & 0 deletions core/src/main/scala/org/sgine/audio/SoundInstance.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.sgine.audio

class SoundInstance(sound: Sound, id: Long, vlm: Double, ptch: Double, pn: Double, lp: Boolean) {
private var _volume = vlm
private var _pitch = ptch
private var _pan = pn
private var _loop = lp

def volume: Double = _volume

def volume_=(v: Double): Unit = {
_volume = v
sound.gdx.setVolume(id, v.toFloat)
}

def pitch: Double = _pitch

def pitch_=(p: Double): Unit = {
_pitch = p
sound.gdx.setPitch(id, p.toFloat)
}

def pan: Double = _pan

def pan_=(p: Double): Unit = {
_pan = p
sound.gdx.setPan(id, p.toFloat, volume.toFloat)
}

def loop: Boolean = _loop

def loop_=(l: Boolean): Unit = {
_loop = l
sound.gdx.setLooping(id, l)
}

def stop(): Unit = sound.gdx.stop(id)

def pause(): Unit = sound.gdx.pause(id)

def resume(): Unit = sound.gdx.resume(id)
}
36 changes: 36 additions & 0 deletions core/src/test/scala/examples/AudioExample.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package examples

import org.sgine.audio.Audio
import org.sgine.{Color, PointerCursor}
import org.sgine.component.{Component, Container, Image, Label, PointerSupport}
import perfolation.double2Implicits

object AudioExample extends Example {
private lazy val music = Audio.music("music.mp3")
private lazy val sfx = Audio.sound("sfx.mp3")

private lazy val logo = new Image("sgine.png") with PointerSupport {
center @= screen.center
middle @= screen.middle

pointer.cursor @= Some(PointerCursor.Hand)
pointer.isOver.attach {
case true => music.play()
case false => music.pause()
}
pointer.down.on {
sfx.play()
}
}

private lazy val musicStatus = new Label {
font @= Fonts.OpenSans.Regular.normal
center @= screen.center
top @= 50.0
text := s"Position: ${music.position().f()}"
}

override protected lazy val component: Container = Container(
logo, musicStatus
)
}

0 comments on commit 490acf5

Please sign in to comment.