Merge remote-tracking branch 'origin/main'

main
lihell 2 years ago
commit 5847c52400

@ -1,5 +1,7 @@
package com.last.commit;
import com.badlogic.gdx.math.MathUtils
class ColorState {
public var red = 0f
private set;

@ -52,10 +52,13 @@ class Game : Game() {
}
fun createState() {
val settings = GameSettings()
val soundEngine = SoundEngine(settings.sfxVolume, settings.musicVolume)
settings.soundEngin = soundEngine
state = GameState(
Inventory(),
GameSettings(),
SoundEngine(),
settings,
soundEngine,
TimeTravelAssetManager(),
null,
DialogStage(Skin(Gdx.files.internal("ui/uiskin.json")))

@ -36,7 +36,7 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga
updateCollider()
if (System.currentTimeMillis() - lastStep > 500) {
gameState.soundEngine.play(GameSoundEffect.STEPS_INDOOR, 0.5f)
gameState.soundEngine.play(GameSoundEffect.STEPS_INDOOR) //0.5F
lastStep = System.currentTimeMillis()
}
}

@ -4,24 +4,34 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.audio.Music
import com.badlogic.gdx.audio.Sound
public class SoundEngine {
public class SoundEngine(private val sfx: Float, private val music: Float) {
var volumeSfx = sfx
var volumeMusic = music
set(newValue) {
field = newValue
resume()
}
private val sounds: ThreadLocal<HashMap<String, Sound>> =
ThreadLocal.withInitial() { HashMap() }
private val musicTracks: ThreadLocal<HashMap<String, Music>> =
ThreadLocal.withInitial() { HashMap() }
lateinit var backgroundMusic: Music
var backgroundMusic: Music
init {
backgroundMusic = loadMusic("world_music.mp3")
}
fun play(gameSound: GameSound, volume: Float = 1f) {
fun play(gameSound: GameSound, ) {
if (gameSound is GameSoundEffect) {
val sound = loadEffect(gameSound.name)
sound.play(volume)
sound.play(volumeSfx)
} else if (gameSound is GameMusic) {
backgroundMusic = loadMusic(gameSound.name)
backgroundMusic.volume = volume
backgroundMusic.setLooping(true)
backgroundMusic.play()
resume()
}
}
@ -30,9 +40,11 @@ public class SoundEngine {
}
fun resume() {
backgroundMusic.play()
backgroundMusic.volume = volumeMusic
if (!backgroundMusic.isPlaying) {
backgroundMusic.play()
}
}
private fun loadEffect(name: String): Sound {
return loadSound("effects/$name")
}

@ -2,24 +2,52 @@ package com.last.commit.config
import com.badlogic.gdx.Input.Keys
import com.badlogic.gdx.math.MathUtils
import com.last.commit.GameState
import com.last.commit.audio.SoundEngine
import java.util.*
class GameSettings {
class GameSettings() {
lateinit var soundEngin : SoundEngine
private val actionKeys: EnumMap<ActionCommand, List<Int>> = EnumMap(ActionCommand::class.java)
private val actionKeysReversed: HashMap<Int, ActionCommand> = hashMapOf()
var musicEnabled: Boolean = true
set(newValue: Boolean) {
field = newValue
soundEngin?.volumeMusic = musicVolume
}
var sfxEnabled: Boolean = true
set(newValue: Boolean) {
field = newValue
soundEngin?.volumeSfx = sfxVolume
}
var musicVolume: Float = 0.5F
get() {
return if (musicEnabled) {
field
} else {
0F
}
}
set(newValue: Float) {
field = MathUtils.clamp(newValue, 1f, 0f)
field = newValue
soundEngin?.volumeMusic = musicVolume
}
var sfxVolume: Float = 0.5F
get() {
return if (sfxEnabled) {
field
} else {
0F
}
}
set(newValue: Float) {
field = MathUtils.clamp(newValue, 1f, 0f)
field = newValue
soundEngin?.volumeSfx = sfxVolume
}
@ -33,8 +61,6 @@ class GameSettings {
actionKeys[ActionCommand.INTERACT] = listOf(Keys.E)
actionKeys[ActionCommand.JUMP] = listOf(Keys.SPACE)
musicVolume = 0.5F
setReversed(actionKeys)
}

@ -63,7 +63,7 @@ class TimeMap(fileName: String, val state: GameState) {
System.out.println("Teleporting to targetMap $targetMap")
loadMap("tiled/$targetMap")
val mapDescription = mapState.description
state.dialogStage.setTexts("You teleported to $mapDescription")
state.dialogStage.setTexts(4000L, "You teleported to $mapDescription")
state.dialogStage.show()
}
}

@ -16,6 +16,7 @@ import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.viewport.Viewport
import com.badlogic.gdx.utils.viewport.StretchViewport
import com.badlogic.gdx.utils.viewport.FillViewport
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.last.commit.Game
import com.last.commit.Player
import com.last.commit.audio.GameMusic
@ -24,6 +25,7 @@ import com.last.commit.config.GameConfig
import com.last.commit.map.Interactable
import com.last.commit.map.TimeMap
import com.last.commit.stages.UIStage
import com.last.commit.stages.PromptStage
import kotlin.math.floor
/** First screen of the application. Displayed after the application is created. */
@ -48,8 +50,8 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
val highlightColor = Color(0f, 0f, 1f, 0.5f)
var pause = true
var uiStage: UIStage
val promptStage: PromptStage
init {
@ -63,18 +65,42 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
uiStage = UIStage("sprites/genericItems_spritesheet_colored", gameState)
shapeRenderer.setAutoShapeType(true)
gameState.soundEngine.play(GameMusic.WORLD_MUSIC, 0.25f)
promptStage = PromptStage(Skin(Gdx.files.internal("ui/uiskin.json")))
promptStage.addText("""
You are stranded in time.
The time traveling device you carry with you cannot be controlled anymore.
""".trimIndent())
promptStage.addText("""
You need to find the tools required to fix your time traveling device.
Look around the map to find them.
""".trimIndent())
promptStage.addText("""
You can use <W>, <A>, <S> and <D> to walk around the map.
""".trimIndent())
promptStage.addText("""
Doors can be opened and items picked up with <E>.
Some doors require keys to be opened.
""")
promptStage.addText("""
At some locations you can press <T> to travel to a random spot in time.
The top left indicates where you traveled to.
""".trimIndent())
promptStage.addText("""
Some items can only be collected in certain time locations.
A collectible item will be highlighted when hovering over it using the mouse
""".trimIndent())
promptStage.visible = true
viewport.camera = camera
viewport.apply()
}
override fun getInputProcessors(): Array<InputProcessor> {
return arrayOf(gameState.dialogStage)
return arrayOf(gameState.dialogStage, promptStage)
}
override fun handleKeyInput(action: ActionCommand) {
if (!pause) {
when (action) {
ActionCommand.INTERACT -> {
openDoor()
@ -95,22 +121,20 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
//Gdx.app.exit()
parent.changeScreen(Screens.MAIN_MENU)
}
}
}
override fun handleMouseInput(screenX: Int, screenY: Int, pointer: Int, button: Int) {
if (!pause) {
val mouseCoordinates: Vector2 = toWorldCoordinates(screenX.toFloat(), screenY.toFloat())
val playerDirection: Vector2 = player.getAbsoluteDirection()
map.interactWith(playerDirection.x, playerDirection.y, player.getCollider())
}
}
override fun show() {
// Prepare your screen here.
resume()
}
@ -124,15 +148,20 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
override fun render(delta: Float) {
if (gameState.inventory.checkVictoryCondition()) {
gameState.dialogStage.show()
gameState.dialogStage.act(delta)
gameState.dialogStage.setTexts("You won!")
gameState.dialogStage.draw()
} else if (!pause) {
promptStage.visible = true
promptStage.clearText()
promptStage.addText("You won!")
promptStage.act(delta)
promptStage.draw()
} else {
uiStage.act(delta)
gameState.dialogStage.act(delta)
handleInput(delta)
handleMapBorderCollision()
promptStage.act(delta)
if (!promptStage.visible) {
handleInput(delta)
handleMapBorderCollision()
}
val mousePosition: Vector2 = getMousePosition()
player.lookAt(mousePosition)
@ -149,6 +178,7 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
uiStage.draw()
gameState.dialogStage.draw()
promptStage.draw()
viewport.apply()
updateCamera()
}
@ -259,6 +289,7 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
override fun resize(width: Int, height: Int) {
// Resize your screen here. The parameters represent the new window size.
uiStage.resize(width, height)
promptStage.resize(width, height)
gameState.dialogStage.resize(width, height)
viewport.update(width, height)
viewport.apply()
@ -267,19 +298,18 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
override fun pause() {
pause = true
gameState.soundEngine.stop()
}
override fun resume() {
pause = false
gameState.soundEngine.resume();
this.viewport.apply()
this.updateCamera()
// Invoked when your application is resumed after pause.
}
override fun hide() {
pause()
//gameState.soundEngine.stop()
}
override fun dispose() {

@ -3,6 +3,7 @@ package com.last.commit.screen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputProcessor
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.math.MathUtils
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Stage
import com.badlogic.gdx.scenes.scene2d.ui.Skin
@ -21,6 +22,7 @@ class MainMenu(val parent: Game) : TimeTravelScreen() {
var table = Table()
val uiSkin: Skin
val state = ColorState()
init {
parent.state.assetManager.finishLoading()
@ -60,7 +62,7 @@ class MainMenu(val parent: Game) : TimeTravelScreen() {
table.setFillParent(true);
val newGame = TextButton("Play Game", uiSkin)
val preferences = TextButton("Preferences", uiSkin)
val preferences = TextButton("Settings", uiSkin)
preferences.setSize(stage.viewport.screenWidth.toFloat(), stage.viewport.screenHeight.toFloat())
val exit = TextButton("Exit", uiSkin)
@ -93,13 +95,17 @@ class MainMenu(val parent: Game) : TimeTravelScreen() {
}
val state = ColorState()
override fun render(delta: Float) {
state.step((delta * 1000).toLong())
// Draw your screen here. "delta" is the time since last render in seconds.
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
Gdx.gl.glClearColor(state.red, state.green, state.blue, 1f)
var red = MathUtils.clamp(state.red,0.1F, 0.5F)
var blue = MathUtils.clamp(state.green,0.1F, 0.5F)
var green = MathUtils.clamp(state.blue,0.1F, 0.5F)
Gdx.gl.glClearColor(red, green, blue, 1f)
// tell our stage to do actions and draw itself
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));

@ -3,15 +3,16 @@ package com.last.commit.screen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputProcessor
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.math.MathUtils
import com.badlogic.gdx.scenes.scene2d.Stage
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.utils.viewport.ScreenViewport
import com.last.commit.ColorState
import com.last.commit.Game
import com.last.commit.config.ActionCommand
class Settings(val parent: Game) : TimeTravelScreen() {
var stage: Stage
val skin: Skin
@ -22,38 +23,24 @@ class Settings(val parent: Game) : TimeTravelScreen() {
lateinit var musicOnOffLabel: Label
lateinit var soundOnOffLabel: Label
var sfxMusicSlider: Slider
var volumeMusicSlider: Slider
var musicCheckbox: CheckBox
var soundEffectsCheckbox: CheckBox
var backButton: Button
val state = ColorState()
val table = Table()
init {
parent.state.assetManager.finishLoading()
stage = Stage(ScreenViewport())
skin = parent.state.assetManager.getUiTexture()
}
override fun handleKeyInput(action: ActionCommand) {
}
override fun handleMouseInput(screenX: Int, screenY: Int, pointer: Int, button: Int) {
stage.touchDown(screenX, screenY, pointer, button)
stage.touchUp(screenX, screenY, pointer, button)
}
override fun getInputProcessors(): Array<InputProcessor> {
return emptyArray()
}
override fun show() {
stage.clear()
// Create a table that fills the screen. Everything else will go inside
// this table.
val table = Table()
table.setFillParent(true)
//table.setDebug(true);
stage.addActor(table)
// music volume
val volumeMusicSlider = Slider(0f, 1f, 0.1f, false, skin)
volumeMusicSlider = Slider(0f, 1f, 0.1f, false, skin)
volumeMusicSlider.value = parent.state.settings.musicVolume
volumeMusicSlider.addListener {
parent.state.settings.musicVolume = volumeMusicSlider.value
@ -62,38 +49,68 @@ class Settings(val parent: Game) : TimeTravelScreen() {
}
// sound volume
val soundMusicSlider = Slider(0f, 1f, 0.1f, false, skin)
soundMusicSlider.value = parent.state.settings.sfxVolume
soundMusicSlider.addListener {
parent.state.settings.sfxVolume = soundMusicSlider.value
sfxMusicSlider = Slider(0f, 1f, 0.1f, false, skin)
sfxMusicSlider.value = parent.state.settings.sfxVolume
sfxMusicSlider.addListener {
parent.state.settings.sfxVolume = sfxMusicSlider.value
// updateVolumeLabel();
false
}
// music on/off
val musicCheckbox = CheckBox(null, skin)
musicCheckbox.isChecked = parent.state.settings.musicEnabled
musicCheckbox = CheckBox(null, skin)
musicCheckbox.isChecked = !parent.state.settings.musicEnabled
musicCheckbox.addListener {
val enabled: Boolean = musicCheckbox.isChecked()
parent.state.settings.musicEnabled = enabled
parent.state.settings.musicEnabled = !enabled
false
}
// sound on/off
val soundEffectsCheckbox = CheckBox(null, skin)
soundEffectsCheckbox.isChecked = parent.state.settings.sfxEnabled
soundEffectsCheckbox = CheckBox(null, skin)
soundEffectsCheckbox.isChecked = !parent.state.settings.sfxEnabled
soundEffectsCheckbox.addListener {
val enabled: Boolean = soundEffectsCheckbox.isChecked()
parent.state.settings.sfxEnabled = enabled
parent.state.settings.sfxEnabled = !enabled
false
}
// return to main screen button
val backButton = TextButton("Back", skin)
backButton = TextButton("Back", skin)
backButton.addListener {
parent.changeScreen(Screens.MAIN_MENU)
false
}
}
override fun handleKeyInput(action: ActionCommand) {
}
override fun handleMouseInput(screenX: Int, screenY: Int, pointer: Int, button: Int) {
stage.touchDown(screenX, screenY, pointer, button)
stage.touchUp(screenX, screenY, pointer, button)
}
override fun getInputProcessors(): Array<InputProcessor> {
return emptyArray()
}
override fun show() {
stage.clear()
}
fun renderTable(x: Float, y: Float) {
table.reset()
table.setFillParent(true)
//table.setDebug(true);
stage.addActor(table)
titleLabel = Label("Preferences", skin)
volumeMusicLabel = Label("Music Volume", skin)
volumeSoundLabel = Label("Sound Volume", skin)
@ -101,25 +118,38 @@ class Settings(val parent: Game) : TimeTravelScreen() {
soundOnOffLabel = Label("Sound Effect", skin)
table.add(titleLabel).colspan(2)
table.row().pad(10F, 0F, 0F, 10F)
table.row().size(x, y);
table.add(volumeMusicLabel).left()
table.add(volumeMusicSlider)
table.row().size(x, y);
table.row().pad(10F, 0F, 0F, 10F)
table.add(musicOnOffLabel).left()
table.add(musicCheckbox)
table.row().size(x, y);
table.row().pad(10F, 0F, 0F, 10F)
table.add(volumeSoundLabel).left()
table.add(soundMusicSlider)
table.add(sfxMusicSlider)
table.row().size(x, y);
table.row().pad(10F, 0F, 0F, 10F)
table.add(soundOnOffLabel).left()
table.add(soundEffectsCheckbox)
table.row().size(x, y);
table.row().pad(10F, 0F, 0F, 10F)
table.add(backButton).colspan(2)
}
override fun render(delta: Float) {
// clear the screen ready for next set of images to be drawn
Gdx.gl.glClearColor(0f, 0f, 0f, 1f)
state.step((delta * 1000).toLong())
// Draw your screen here. "delta" is the time since last render in seconds.
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
var red = MathUtils.clamp(state.red,0.1F, 0.5F)
var blue = MathUtils.clamp(state.green,0.1F, 0.5F)
var green = MathUtils.clamp(state.blue,0.1F, 0.5F)
Gdx.gl.glClearColor(red, green, blue, 1f)
// tell our stage to do actions and draw itself
stage.act(Math.min(Gdx.graphics.deltaTime, 1 / 30f))
@ -127,7 +157,14 @@ class Settings(val parent: Game) : TimeTravelScreen() {
}
override fun resize(width: Int, height: Int) {
stage.viewport.update(width, height)
println("width $width, height $height")
stage.viewport.update(width, height, true);
val y = stage.viewport.screenHeight.toFloat() / 6
val x = stage.viewport.screenWidth.toFloat() / 4
renderTable(x, y)
}
override fun pause() {
@ -140,5 +177,6 @@ class Settings(val parent: Game) : TimeTravelScreen() {
}
override fun dispose() {
stage.dispose();
}
}

@ -15,6 +15,7 @@ class DialogStage(skin: Skin?) : Stage(ExtendViewport(512f, 512f)) {
private var isVisible = false
private val texts = com.badlogic.gdx.utils.Array<String>()
private val area: TextArea
var closeIn: Long? = null
init {
area = TextArea("#", skin)
@ -29,6 +30,13 @@ class DialogStage(skin: Skin?) : Stage(ExtendViewport(512f, 512f)) {
next()
}
fun setTexts(duration: Long, vararg texts: String?) {
this.texts.clear()
this.texts.addAll(*texts)
this.closeIn = System.currentTimeMillis() + duration
next()
}
fun show() {
isVisible = true
}
@ -45,14 +53,24 @@ class DialogStage(skin: Skin?) : Stage(ExtendViewport(512f, 512f)) {
override fun draw() {
if (isVisible) {
this.viewport.apply()
super.draw()
if (closeIn != null && closeIn!! < System.currentTimeMillis()) {
closeIn = null
this.hide()
} else {
this.viewport.apply()
super.draw()
}
}
}
override fun act() {
if (isVisible) {
super.act()
if (closeIn != null && closeIn!! < System.currentTimeMillis()) {
closeIn = null
this.hide()
} else {
super.act()
}
}
}
@ -75,7 +93,7 @@ class DialogStage(skin: Skin?) : Stage(ExtendViewport(512f, 512f)) {
hide()
}
}
return true
return false
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {

@ -0,0 +1,81 @@
package com.last.commit.stages
import com.badlogic.gdx.utils.viewport.ExtendViewport
import com.badlogic.gdx.utils.Align
import com.badlogic.gdx.scenes.scene2d.Stage
import com.badlogic.gdx.scenes.scene2d.ui.TextArea
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.Input
class PromptStage(skin: Skin?): Stage(ExtendViewport(300f, 300f)) {
private val textArea: TextArea;
var visible = false
private val text: ArrayList<String> = ArrayList()
init {
textArea = TextArea("", skin)
textArea.setSize(viewport.worldWidth * 0.8f, viewport.worldHeight * 0.6f)
textArea.setPosition(viewport.worldWidth * 0.1f, viewport.worldHeight * 0.2f)
textArea.setAlignment(Align.center)
this.addActor(textArea)
}
override fun act(delta: Float) {
if (visible) {
if (this.textArea.text.isEmpty()) {
this.next()
}
super.act(delta)
}
}
override fun draw() {
if (visible) {
this.viewport.apply()
super.draw()
}
}
fun clearText() {
this.text.clear()
}
fun addText(text: String) {
this.text.add(text)
}
fun resize(width: Int, height: Int) {
this.viewport.update(width, height)
this.camera.update()
}
override fun keyDown(keyCode: Int): Boolean {
return if (!visible) {
false
} else if (keyCode == Input.Keys.SPACE) {
next()
false
} else {
false
}
}
private operator fun next() {
textArea.clear()
if (text.isNotEmpty()) {
val text = text.removeAt(0).trimIndent()
textArea.text = text
} else {
textArea.text = ""
visible = false
}
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return keyDown(Input.Keys.SPACE)
}
}
Loading…
Cancel
Save