Huge refactoring

main
Matthias 1 year ago
parent 9711e28341
commit 960577bcb1

@ -0,0 +1,62 @@
package com.last.commit
import com.badlogic.gdx.assets.AssetManager
import com.badlogic.gdx.audio.Music
import com.badlogic.gdx.audio.Sound
import com.badlogic.gdx.scenes.scene2d.ui.Skin
object TimeTravelAssetManager {
private val skin = "ui/uiskin.json"
private val assetManager = AssetManager()
fun loadSounds(vararg paths: String) {
println("Loading ${paths.size} sounds")
for (path in paths) {
assetManager.load(path, Sound::class.java)
}
}
fun loadMusics(vararg paths: String) {
println("Loading ${paths.size} musics")
for (path in paths) {
assetManager.load(path, Music::class.java)
}
}
fun loadSkins(vararg paths: String) {
println("Loading ${paths.size} skins")
for (path in paths) {
assetManager.load(path, Skin::class.java)
}
assetManager.load(skin, Skin::class.java);
}
fun loadTextures(vararg paths: String) {
println("Loading ${paths.size} textures")
for (path in paths) {
assetManager.load(path, Music::class.java)
}
}
fun getSkin(): Skin {
return assetManager.get(skin)
}
fun <T> get(path: String): T {
return assetManager.get(path)
}
fun finishLoading() {
assetManager.finishLoading()
}
fun update(): Boolean {
return assetManager.update()
}
fun dispose() {
assetManager.dispose()
}
}

@ -2,11 +2,10 @@ package com.last.commit
import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputMultiplexer
import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.last.commit.audio.SoundEngine
import com.last.commit.config.GameSettings
import com.last.commit.config.TimeTravelAssetManager
import com.last.commit.inventory.Inventory
import com.last.commit.screen.*
import com.last.commit.stages.DialogStage
@ -17,25 +16,23 @@ class Game : Game() {
lateinit var state: GameState
lateinit var menu: TimeTravelScreen
lateinit var gameplay: TimeTravelScreen
lateinit var settings: TimeTravelScreen
val inputProcessors = InputMultiplexer()
lateinit var inputProcessor: GameInputProcessor
lateinit var loading: Screen
lateinit var menu: Screen
lateinit var gameplay: Screen
lateinit var settings: Screen
lateinit var font: BitmapFont
override fun create() {
font = BitmapFont()
createState()
createScreens()
inputProcessor = GameInputProcessor(this)
gameplay.getInputProcessors().forEach { it -> inputProcessors.addProcessor(it) }
inputProcessors.addProcessor(inputProcessor)
Gdx.input.inputProcessor = inputProcessors
changeScreen(Screens.MAIN_MENU)
changeScreen(Screens.LOADING)
}
private fun createScreens() {
loading = LoadingScreen(TimeTravelAssetManager, this)
menu = MainMenu(this)
gameplay = FirstScreen(this)
settings = Settings(this)
@ -44,22 +41,17 @@ class Game : Game() {
fun changeScreen(screen: Screens) {
println("changing screen to $screen")
when (screen) {
Screens.LOADING -> setScreen(loading)
Screens.MAIN_MENU -> setScreen(menu)
Screens.SETTINGS -> setScreen(settings)
Screens.GAME -> setScreen(gameplay)
}
inputProcessor.activeScreen = getScreen() as TimeTravelScreen
}
fun createState() {
val settings = GameSettings()
val soundEngine = SoundEngine(settings.sfxVolume, settings.musicVolume)
settings.soundEngin = soundEngine
state = GameState(
Inventory(),
settings,
soundEngine,
TimeTravelAssetManager(),
SoundEngine,
null,
DialogStage(Skin(Gdx.files.internal("ui/uiskin.json")))
)

@ -1,46 +0,0 @@
package com.last.commit
import com.badlogic.gdx.InputProcessor
import com.last.commit.screen.TimeTravelScreen
class GameInputProcessor(val game: Game) : InputProcessor {
lateinit var activeScreen: TimeTravelScreen
override fun keyUp(keycode: Int): Boolean {
return false
}
override fun keyTyped(character: Char): Boolean {
return false
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
activeScreen.handleMouseInput(screenX, screenY, pointer, button)
return false
}
override fun keyDown(keycode: Int): Boolean {
game.state.settings.getAction(keycode)?.let {
activeScreen.handleKeyInput(it)
}
return false
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return false
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
return false
}
override fun mouseMoved(screenX: Int, screenY: Int): Boolean {
return false
}
override fun scrolled(amountX: Float, amountY: Float): Boolean {
return false
}
}

@ -1,17 +1,13 @@
package com.last.commit
import com.last.commit.audio.SoundEngine
import com.last.commit.config.GameSettings
import com.last.commit.config.TimeTravelAssetManager
import com.last.commit.inventory.Inventory
import com.last.commit.map.MapState
import com.last.commit.stages.DialogStage
data class GameState(
val inventory: Inventory,
val settings: GameSettings,
val soundEngine: SoundEngine,
val assetManager: TimeTravelAssetManager,
var map: MapState? = null,
val dialogStage: DialogStage
) {

@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.math.Rectangle
import com.badlogic.gdx.math.Vector2
import com.last.commit.audio.GameSoundEffect
class Player(private val textureRegion: TextureRegion, private val gameState: GameState) : Collidable {
@ -36,7 +35,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("STEPS_INDOOR") //0.5F
lastStep = System.currentTimeMillis()
}
}

@ -1,9 +0,0 @@
package com.last.commit.audio
import com.last.commit.audio.GameSound
class GameMusic(name: String): GameSound(name) {
companion object {
val WORLD_MUSIC = GameMusic("world_music.mp3")
}
}

@ -1,5 +0,0 @@
package com.last.commit.audio;
public abstract class GameSound(public val name: String) {
}

@ -1,19 +0,0 @@
package com.last.commit.audio;
import com.last.commit.audio.GameSound
public class GameSoundEffect(name: String): GameSound(name) {
companion object {
val STEPS_INDOOR: GameSoundEffect
get() = listOf(
GameSoundEffect("steps/steps_indoor_1.mp3"),
GameSoundEffect("steps/steps_indoor_2.mp3"),
GameSoundEffect("steps/steps_indoor_3.mp3"),
).random()
val DOOR_OPEN = GameSoundEffect("door_open.mp3")
val DOOR_CLOSE = GameSoundEffect("door_close.mp3")
val TIME_TRAVEL = GameSoundEffect("time_travel.mp3")
val GRAB = GameSoundEffect("grab.mp3")
}
}

@ -1,75 +1,80 @@
package com.last.commit.audio
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.audio.Music
import com.badlogic.gdx.audio.Sound
import com.last.commit.TimeTravelAssetManager
public class SoundEngine(private val sfx: Float, private val music: Float) {
object SoundEngine {
var volumeSfx = sfx
var volumeMusic = music
var sfxVolume = 1.0f
var musicVolume = 1.0f
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() }
fun play(gameSound: String) {
when (gameSound) {
"STEPS_INDOOR" -> {
val soundName = listOf(
"steps/steps_indoor_1.mp3",
"steps/steps_indoor_2.mp3",
"steps/steps_indoor_3.mp3",
).random()
val sound = loadEffect(soundName)
sound.play(sfxVolume)
}
var backgroundMusic: Music
"DOOR_OPEN" -> {
val sound = loadEffect("door_open.mp3")
sound.play(sfxVolume)
}
init {
backgroundMusic = loadMusic("world_music.mp3")
resume()
}
"DOOR_CLOSE" -> {
val sound = loadEffect("door_close.mp3")
sound.play(sfxVolume)
}
fun play(gameSound: GameSound, ) {
if (gameSound is GameSoundEffect) {
val sound = loadEffect(gameSound.name)
sound.play(volumeSfx)
} else if (gameSound is GameMusic) {
backgroundMusic.setLooping(true)
resume()
"TIME_TRAVEL" -> {
val sound = loadEffect("time_travel.mp3")
sound.play(sfxVolume)
}
"GRAB" -> {
val sound = loadEffect("grab.mp3")
sound.play(sfxVolume)
}
"BACKGROUND_MUSIC" -> {
loadMusic("world_music.mp3").play()
}
else -> {
println("Could not find sound/music $gameSound")
}
}
}
fun stop() {
backgroundMusic.pause()
loadMusic("world_music.mp3").pause()
}
fun resume() {
backgroundMusic.volume = volumeMusic
if (!backgroundMusic.isPlaying) {
backgroundMusic.play()
loadMusic("world_music.mp3").volume = musicVolume
if (!loadMusic("world_music.mp3").isPlaying) {
loadMusic("world_music.mp3").play()
}
}
private fun loadEffect(name: String): Sound {
return loadSound("effects/$name")
}
private fun loadMusic(name: String): Music {
var music = musicTracks.get().get(name)
if (music == null) {
println("Loading sound $name")
music = Gdx.audio.newMusic(Gdx.files.internal("sounds/music/$name"))
musicTracks.get()[name] = music
}
return music!!
return TimeTravelAssetManager.get("sounds/music/$name")
}
private fun loadSound(name: String): Sound {
var sound = sounds.get().get(name)
if (sound == null) {
println("Loading sound $name")
sound = Gdx.audio.newSound(Gdx.files.internal("sounds/$name"))
sounds.get()[name] = sound
}
return sound!!
return TimeTravelAssetManager.get("sounds/$name")
}
}

@ -1,16 +0,0 @@
package com.last.commit.config
enum class ActionCommand {
//move
UP, DOWN, LEFT, RIGHT,
//interaction
TIME_TRAVEL,
INTERACT,
//program interaction
OPEN_MENU,
JUMP
}

@ -1,91 +0,0 @@
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() {
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 = newValue
soundEngin?.volumeMusic = musicVolume
}
var sfxVolume: Float = 0.5F
get() {
return if (sfxEnabled) {
field
} else {
0F
}
}
set(newValue: Float) {
field = newValue
soundEngin?.volumeSfx = sfxVolume
}
init {
actionKeys[ActionCommand.UP] = listOf(Keys.UP, Keys.W)
actionKeys[ActionCommand.DOWN] = listOf(Keys.DOWN, Keys.S)
actionKeys[ActionCommand.LEFT] = listOf(Keys.LEFT, Keys.A)
actionKeys[ActionCommand.RIGHT] = listOf(Keys.RIGHT, Keys.D)
actionKeys[ActionCommand.OPEN_MENU] = listOf(Keys.ESCAPE)
actionKeys[ActionCommand.TIME_TRAVEL] = listOf(Keys.T)
actionKeys[ActionCommand.INTERACT] = listOf(Keys.E)
actionKeys[ActionCommand.JUMP] = listOf(Keys.SPACE)
setReversed(actionKeys)
}
private fun setReversed(actionKeys: EnumMap<ActionCommand, List<Int>>) {
for (actionCode in actionKeys.keys) {
for (key in actionKeys.getValue(actionCode)) {
actionKeysReversed[key] = actionCode
}
}
}
fun getAction(keyCode: Int): ActionCommand? {
return actionKeysReversed[keyCode]
}
fun getKeyCode(actionCommand: ActionCommand): List<Int> {
return if (Objects.nonNull(actionKeys[actionCommand])) {
actionKeys[actionCommand]!!
} else {
listOf()
}
}
}

@ -1,22 +0,0 @@
package com.last.commit.config
import com.badlogic.gdx.assets.AssetManager
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.scenes.scene2d.ui.Skin
class TimeTravelAssetManager : AssetManager() {
val UI_TEXTURE_PATH = "ui/uiskin.json"
init {
loadTextures()
}
fun loadTextures() {
load(UI_TEXTURE_PATH, Skin::class.java)
}
fun getUiTexture() : Skin {
return get(UI_TEXTURE_PATH)
}
}

@ -7,8 +7,8 @@ class Inventory() {
private val requiredItems = listOf("ram", "iphone", "ipod", "screwdriver")
/**
* @param name the name of the subtexture loaded from xml
* @return wether the item was added
* @param name the name of the subTexture loaded from xml
* @return whether the item was added
*/
fun add(name: String) {
items.add(InventoryItem(name))
@ -16,7 +16,7 @@ class Inventory() {
}
fun hasItem(name: String): Boolean {
return this.items.find { it.name == name } == null
return this.items.find { it.name == name } != null
}
fun isFull(): Boolean {
@ -24,7 +24,7 @@ class Inventory() {
}
fun remove(name: String) {
items.removeIf() { item -> item.name == name }
items.removeIf { item -> item.name == name }
}
fun checkVictoryCondition(): Boolean {

@ -4,8 +4,6 @@ import com.badlogic.gdx.math.Rectangle
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.last.commit.GameState
import com.last.commit.audio.GameSoundEffect
import com.last.commit.inventory.InventoryItem
class Collectible(
name: String,
@ -23,9 +21,9 @@ class Collectible(
this.collider = Rectangle(pos.x, pos.y, size.x, size.y)
}
override fun interact(otherCollider: Rectangle, state: GameState) {
override fun interact(otherCollider: Rectangle, state: GameState): Boolean {
println("Interacting with item $name")
state.soundEngine.play(GameSoundEffect.GRAB)
state.soundEngine.play("GRAB")
if (state.inventory.hasItem(this.name)) {
state.dialogStage.setTexts("You already have this item.")
state.dialogStage.show()
@ -33,18 +31,16 @@ class Collectible(
state.dialogStage.setTexts("You can't carry anymore items.")
} else {
state.inventory.add(this.name)
return true
}
return false
}
override fun canInteract(state: GameState): Boolean {
if (requiredItem == "") {
return true
}
val item: InventoryItem? = state.inventory.items.find { it.name == requiredItem }
if (item == null) {
return false
}
state.inventory.items.find { it.name == requiredItem } ?: return false
return true

@ -4,7 +4,6 @@ import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell
import com.badlogic.gdx.math.Rectangle
import com.last.commit.GameState
import com.last.commit.Wall
import com.last.commit.audio.GameSoundEffect
import com.last.commit.inventory.InventoryItem
class Door(gridX: Int, gridY: Int, wallCollider: Rectangle, cell: Cell) :
@ -24,29 +23,29 @@ class Door(gridX: Int, gridY: Int, wallCollider: Rectangle, cell: Cell) :
result = requiredItem == item.name
}
if (result) {
} else {
if (!result) {
state.dialogStage.setTexts("This dor is blocked. You need a key")
state.dialogStage.show()
}
return result
}
override fun interact(otherCollider: Rectangle, state: GameState) {
override fun interact(otherCollider: Rectangle, state: GameState): Boolean {
println("interacting with door $this")
if (isClosed) {
state.soundEngine.play(GameSoundEffect.DOOR_OPEN)
state.soundEngine.play("DOOR_OPEN")
isOpen = true
} else if (isOpen) {
if (getCollider().overlaps(otherCollider)) {
// can't close the door cause it is colliding with given collider
} else {
state.soundEngine.play(GameSoundEffect.DOOR_CLOSE)
state.soundEngine.play("DOOR_CLOSE")
isOpen = false
}
}
println("Door is now open = $isOpen")
return false
}
var isOpen: Boolean

@ -6,7 +6,7 @@ import com.last.commit.GameState
interface Interactable {
fun getCollider(): Rectangle
fun interact(otherCollider: Rectangle, state: GameState)
fun interact(otherCollider: Rectangle, state: GameState): Boolean
fun canInteract(state: GameState): Boolean
}

@ -12,7 +12,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.last.commit.Collidable
import com.last.commit.GameState
import com.last.commit.Player
import com.last.commit.audio.GameSoundEffect
import com.last.commit.inventory.SpritesheetTextureLoader
@ -58,7 +57,7 @@ class TimeMap(fileName: String, val state: GameState) {
it.rectangle.contains(player.getX(), player.getY())
}
if (teleporter != null) {
state.soundEngine.play(GameSoundEffect.TIME_TRAVEL)
state.soundEngine.play("TIME_TRAVEL")
val targetMap = teleporter.properties.get("target", String::class.java)
System.out.println("Teleporting to targetMap $targetMap")
loadMap("tiled/$targetMap")
@ -125,7 +124,10 @@ class TimeMap(fileName: String, val state: GameState) {
if (interactable.canInteract(state)) {
println("Interacting with element at $gridX:$gridY")
interactable.interact(blockingCollider, state)
val collected = interactable.interact(blockingCollider, state)
if (collected && interactable is Collectible) {
state.map?.collectibles?.remove(interactable)
}
} else {
println("Cannot interact with $gridX:$gridY")
}

@ -1,7 +1,6 @@
package com.last.commit.screen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputProcessor
import com.badlogic.gdx.*
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.OrthographicCamera
@ -12,37 +11,32 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.math.MathUtils
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.math.Vector3
import com.badlogic.gdx.scenes.scene2d.ui.Skin
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
import com.last.commit.config.ActionCommand
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 com.last.commit.stages.UIStage
import kotlin.math.floor
/** First screen of the application. Displayed after the application is created. */
class FirstScreen(private val parent: Game) : TimeTravelScreen() {
class FirstScreen(private val parent: Game) : Screen, InputProcessor {
val gameState = parent.state
val viewportSize = 1200f
private var delta = 0.008f
private var isColliding = false
val batch = SpriteBatch()
val viewport = FillViewport(viewportSize, viewportSize)
val camera = OrthographicCamera(viewportSize, viewportSize)
var map: TimeMap
lateinit var map: TimeMap
val playerTexture = Texture("sprites/characters.png")
val player = Player(TextureRegion(playerTexture, 300, 44, 35, 43), gameState)
@ -50,11 +44,17 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
val highlightColor = Color(0f, 0f, 1f, 0.5f)
var uiStage: UIStage
val promptStage: PromptStage
lateinit var uiStage: UIStage
lateinit var promptStage: PromptStage
val inputProcessors = InputMultiplexer()
init {
}
override fun show() {
val gameConfig = this.loadGameConfig()
val randomMap = gameConfig.getRandomMap()
map = TimeMap(randomMap, gameState)
@ -66,77 +66,51 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
shapeRenderer.setAutoShapeType(true)
promptStage = PromptStage(Skin(Gdx.files.internal("ui/uiskin.json")))
promptStage.addText("""
promptStage.addText(
"""
You are stranded in time.
The time traveling device you carry with you cannot be controlled anymore.
""".trimIndent())
promptStage.addText("""
""".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("""
""".trimIndent()
)
promptStage.addText(
"""
You can use <W>, <A>, <S> and <D> to walk around the map.
""".trimIndent())
promptStage.addText("""
""".trimIndent()
)
promptStage.addText(
"""
Doors can be opened and items picked up with <E>.
Some doors require keys to be opened.
""")
promptStage.addText("""
"""
)
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("""
""".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())
""".trimIndent()
)
promptStage.visible = true
viewport.camera = camera
viewport.apply()
}
override fun getInputProcessors(): Array<InputProcessor> {
return arrayOf(gameState.dialogStage, promptStage)
}
override fun handleKeyInput(action: ActionCommand) {
when (action) {
ActionCommand.INTERACT -> {
openDoor()
}
ActionCommand.TIME_TRAVEL -> {
map.teleport(player)
}
ActionCommand.JUMP -> {
gameState.dialogStage.setTexts("Hello", "Please read the documentation")
gameState.dialogStage.show()
}
else -> {}
}
if (action == ActionCommand.OPEN_MENU) {
//Gdx.app.exit()
parent.changeScreen(Screens.MAIN_MENU)
}
}
override fun handleMouseInput(screenX: Int, screenY: Int, pointer: Int, button: Int) {
val mouseCoordinates: Vector2 = toWorldCoordinates(screenX.toFloat(), screenY.toFloat())
val playerDirection: Vector2 = player.getAbsoluteDirection()
map.interactWith(playerDirection.x, playerDirection.y, player.getCollider())
}
override fun show() {
resume()
inputProcessors.addProcessor(gameState.dialogStage)
inputProcessors.addProcessor(promptStage)
inputProcessors.addProcessor(this)
Gdx.input.inputProcessor = inputProcessors
}
fun loadGameConfig(): GameConfig {
@ -147,16 +121,14 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
}
override fun render(delta: Float) {
uiStage.act(delta)
gameState.dialogStage.act(delta)
promptStage.act(delta)
if (gameState.inventory.checkVictoryCondition()) {
promptStage.visible = true
promptStage.clearText()
promptStage.addText("You won!")
promptStage.act(delta)
promptStage.draw()
} else {
uiStage.act(delta)
gameState.dialogStage.act(delta)
promptStage.act(delta)
if (!promptStage.visible) {
handleInput(delta)
@ -166,7 +138,7 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
val mousePosition: Vector2 = getMousePosition()
player.lookAt(mousePosition)
batch.projectionMatrix = camera.combined
batch.begin()
this.map.render(batch, camera, delta)
@ -176,12 +148,12 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
val interactables = map.getInteractablesAt(player.getAbsoluteDirection())
renderInteractables(interactables)
uiStage.draw()
gameState.dialogStage.draw()
promptStage.draw()
viewport.apply()
updateCamera()
}
promptStage.draw()
uiStage.draw()
gameState.dialogStage.draw()
}
fun renderInteractables(interactables: List<Interactable>) {
@ -219,10 +191,10 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
private fun handleInput(delta: Float) {
val horizontalMovement = Vector2()
if (isKeyPressed(gameState.settings.getKeyCode(ActionCommand.LEFT))) {
if (Gdx.input.isKeyPressed(Input.Keys.A) || Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
horizontalMovement.sub(Vector2.X)
}
if (isKeyPressed(gameState.settings.getKeyCode(ActionCommand.RIGHT))) {
if (Gdx.input.isKeyPressed(Input.Keys.D) || Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
horizontalMovement.add(Vector2.X)
}
this.player.move(horizontalMovement, delta)
@ -232,10 +204,10 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
this.player.move(horizontalMovement, delta)
}
val verticalMovement = Vector2()
if (isKeyPressed(gameState.settings.getKeyCode(ActionCommand.UP))) {
if (Gdx.input.isKeyPressed(Input.Keys.W) || Gdx.input.isKeyPressed(Input.Keys.UP)) {
verticalMovement.add(Vector2.Y)
}
if (isKeyPressed(gameState.settings.getKeyCode(ActionCommand.DOWN))) {
if (Gdx.input.isKeyPressed(Input.Keys.S) || Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
verticalMovement.sub(Vector2.Y)
}
this.player.move(verticalMovement, delta)
@ -244,7 +216,6 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
verticalMovement.rotateDeg(180f)
this.player.move(verticalMovement, delta)
}
val hasMoved = !horizontalMovement.isZero || !verticalMovement.isZero
if (hasMoved) {
updateCamera()
@ -268,8 +239,8 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
private fun checkCollision() {
this.isColliding = map.isCollidingWith(player)
}
private fun updateCamera() {
val mapSize = Vector2(map.width.toFloat(), map.height.toFloat())
@ -286,6 +257,7 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
)
camera.update()
}
override fun resize(width: Int, height: Int) {
// Resize your screen here. The parameters represent the new window size.
uiStage.resize(width, height)
@ -331,4 +303,59 @@ class FirstScreen(private val parent: Game) : TimeTravelScreen() {
)
}
override fun keyDown(keycode: Int): Boolean {
return false
}
override fun keyUp(keycode: Int): Boolean {
when (keycode) {
Input.Keys.E -> {
openDoor()
}
Input.Keys.T -> {
map.teleport(player)
}
Input.Keys.ESCAPE -> {
parent.changeScreen(Screens.MAIN_MENU)
}
}
return false
}
override fun keyTyped(character: Char): Boolean {
return false
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
val mouseCoordinates: Vector2 = toWorldCoordinates(screenX.toFloat(), screenY.toFloat())
val playerDirection: Vector2 = player.getAbsoluteDirection()
map.interactWith(playerDirection.x, playerDirection.y, player.getCollider())
return false
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
//TODO:("Not yet implemented")
return false
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
//TODO:("Not yet implemented")
return false
}
override fun mouseMoved(screenX: Int, screenY: Int): Boolean {
//TODO:("Not yet implemented")
return false
}
override fun scrolled(amountX: Float, amountY: Float): Boolean {
//TODO:("Not yet implemented")
return false
}
}

@ -0,0 +1,104 @@
package com.last.commit.screen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.GlyphLayout
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.last.commit.Game
import com.last.commit.TimeTravelAssetManager
class LoadingScreen(private val assetManager: TimeTravelAssetManager, private val game: Game) : Screen {
companion object {
private const val FONTS = 1
private const val TEXTURES = 2
private const val SKINS = 3
private const val MUSICS = 4
private const val SOUNDS = 5
private const val FINISHED = 6
}
private var currentLoadingStage = 0
private val layout = GlyphLayout()
private var currentText = ""
private val camera = OrthographicCamera()
// timer for exiting loading screen
private var countDown = 1f // 5 seconds of waiting before menu screen
private val batch = SpriteBatch()
init {
camera.setToOrtho(false, 800f, 600f)
}
override fun show() {}
override fun render(delta: Float) {
Gdx.gl.glClearColor(0f, 0f, 0.2f, 1f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
if (assetManager.update()) {
currentLoadingStage += 1
when (currentLoadingStage) {
TEXTURES -> {
currentText = "Loading textures"
assetManager.loadTextures()
}
SKINS -> {
currentText = "Loading skins"
assetManager.loadSkins()
}
MUSICS -> {
currentText = "Loading musics"
assetManager.loadMusics("sounds/music/world_music.mp3")
}
SOUNDS -> {
currentText = "Loading sounds"
assetManager.loadSounds(
"sounds/effects/steps/steps_indoor_1.mp3",
"sounds/effects/steps/steps_indoor_2.mp3",
"sounds/effects/steps/steps_indoor_3.mp3",
"sounds/effects/door_open.mp3",
"sounds/effects/door_close.mp3",
"sounds/effects/time_travel.mp3",
"sounds/effects/grab.mp3"
)
}
FINISHED -> currentText = "Finished"
else -> currentText = "Key no found"
}
if (currentLoadingStage > 5) {
countDown -= delta // timer to stay on loading screen for short preiod once done loading
currentLoadingStage =
5 // cap loading stage to 5 as will use later to display progress bar anbd more than 5 would go off the screen
if (countDown < 0) { // countdown is complete
// game.getAudioManager().load()
game.changeScreen(Screens.MAIN_MENU)
}
}
}
layout.setText(game.font, currentText)
camera.update()
batch.projectionMatrix = camera.combined
batch.begin()
game.font.draw(batch, currentText, 800 / 2 - layout.width / 2, layout.height + 10)
batch.end()
}
override fun resize(width: Int, height: Int) {}
override fun pause() {}
override fun resume() {}
override fun hide() {
assetManager.finishLoading()
}
override fun dispose() {}
}

@ -1,7 +1,7 @@
package com.last.commit.screen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputProcessor
import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.math.MathUtils
import com.badlogic.gdx.scenes.scene2d.Actor
@ -13,67 +13,40 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.badlogic.gdx.utils.viewport.ScreenViewport
import com.last.commit.ColorState
import com.last.commit.Game
import com.last.commit.config.ActionCommand
import com.last.commit.TimeTravelAssetManager
import com.last.commit.audio.SoundEngine
class MainMenu(val parent: Game) : TimeTravelScreen() {
class MainMenu(val parent: Game) : Screen {
var stage: Stage
var table = Table()
val uiSkin: Skin
var stage = Stage(ScreenViewport())
val state = ColorState()
init {
parent.state.assetManager.finishLoading()
stage = Stage(ScreenViewport())
uiSkin = parent.state.assetManager.getUiTexture()
}
override fun handleKeyInput(action: ActionCommand) {
parent.changeScreen(Screens.GAME)
}
override fun handleMouseInput(screenX: Int, screenY: Int, pointer: Int, button: Int) {
stage.touchDown(screenX, screenY, pointer, button)
stage.touchUp(screenX, screenY, pointer, button)
}
lateinit var uiSkin: Skin
override fun getInputProcessors(): Array<InputProcessor> {
return emptyArray()
}
val state = ColorState()
override fun show() {
stage.addActor(table);
val y = stage.viewport.screenHeight.toFloat() / 6
val x = stage.viewport.screenWidth.toFloat() / 4
println("x: $x, y: $y")
Gdx.input.setInputProcessor(stage);
SoundEngine.resume()
uiSkin = TimeTravelAssetManager.getSkin()
stage.clear()
//add buttons to table
renderTable(x, y);
createTable();
}
fun renderTable(x: Float, y: Float) {
table.reset()
fun createTable(): Table {
var table = Table()
table.setFillParent(true);
table.setDebug(true)
stage.addActor(table);
val newGame = TextButton("Play Game", uiSkin)
val preferences = TextButton("Settings", uiSkin)
preferences.setSize(stage.viewport.screenWidth.toFloat(), stage.viewport.screenHeight.toFloat())
val exit = TextButton("Exit", uiSkin)
table.row().size(x, y);
table.add(newGame).fillX().uniformX()
table.row().pad(10F, 0F, 10F, 0F)
table.row().size(x, y);
table.add(preferences).fillX().uniformX()
table.row().size(x, y);
table.add(exit).fillX().uniformX()
exit.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
Gdx.app.exit()
@ -92,6 +65,13 @@ class MainMenu(val parent: Game) : TimeTravelScreen() {
}
})
table.add(newGame).fillX().uniformX()
table.row().pad(10F, 0F, 10F, 0F)
table.add(preferences).fill().uniformX()
table.row()
table.add(exit).fillX().uniformX()
return table
}
@ -101,9 +81,9 @@ class MainMenu(val parent: Game) : TimeTravelScreen() {
// 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)
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)
@ -117,12 +97,6 @@ class MainMenu(val parent: Game) : TimeTravelScreen() {
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() {

@ -3,5 +3,6 @@ package com.last.commit.screen
enum class Screens {
MAIN_MENU,
SETTINGS,
GAME
GAME,
LOADING
}

@ -1,20 +1,23 @@
package com.last.commit.screen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputProcessor
import com.badlogic.gdx.Screen
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.*
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.badlogic.gdx.utils.viewport.ScreenViewport
import com.last.commit.ColorState
import com.last.commit.Game
import com.last.commit.config.ActionCommand
import com.last.commit.TimeTravelAssetManager
import com.last.commit.audio.SoundEngine
class Settings(val parent: Game) : TimeTravelScreen() {
class Settings(val parent: Game) : Screen {
var stage: Stage
val skin: Skin
val stage = Stage(ScreenViewport())
lateinit var skin: Skin
lateinit var titleLabel: Label
@ -23,83 +26,68 @@ 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
lateinit var sfxMusicSlider: Slider
lateinit var volumeMusicSlider: Slider
lateinit var musicCheckbox: CheckBox
lateinit var soundEffectsCheckbox: CheckBox
lateinit var backButton: Button
val state = ColorState()
val table = Table()
init {
parent.state.assetManager.finishLoading()
stage = Stage(ScreenViewport())
skin = parent.state.assetManager.getUiTexture()
override fun show() {
stage.clear()
Gdx.input.setInputProcessor(stage)
skin = TimeTravelAssetManager.getSkin()
// music volume
volumeMusicSlider = Slider(0f, 1f, 0.1f, false, skin)
volumeMusicSlider.value = parent.state.settings.musicVolume
volumeMusicSlider.value = SoundEngine.musicVolume
volumeMusicSlider.addListener {
parent.state.settings.musicVolume = volumeMusicSlider.value
SoundEngine.musicVolume = volumeMusicSlider.value
// updateVolumeLabel();
false
}
// sound volume
sfxMusicSlider = Slider(0f, 1f, 0.1f, false, skin)
sfxMusicSlider.value = parent.state.settings.sfxVolume
sfxMusicSlider.value = SoundEngine.sfxVolume
sfxMusicSlider.addListener {
parent.state.settings.sfxVolume = sfxMusicSlider.value
SoundEngine.sfxVolume = sfxMusicSlider.value
// updateVolumeLabel();
false
}
// music on/off
musicCheckbox = CheckBox(null, skin)
musicCheckbox.isChecked = !parent.state.settings.musicEnabled
musicCheckbox.isChecked = SoundEngine.musicVolume > 0
musicCheckbox.addListener {
val enabled: Boolean = musicCheckbox.isChecked()
parent.state.settings.musicEnabled = !enabled
//TODO: reimplement this
SoundEngine.musicVolume = if (enabled) 0.5f else 0f
false
}
// sound on/off
soundEffectsCheckbox = CheckBox(null, skin)
soundEffectsCheckbox.isChecked = !parent.state.settings.sfxEnabled
soundEffectsCheckbox.isChecked = SoundEngine.sfxVolume > 0
soundEffectsCheckbox.addListener {
val enabled: Boolean = soundEffectsCheckbox.isChecked()
parent.state.settings.sfxEnabled = !enabled
//TODO: reimplement this
SoundEngine.sfxVolume = if (enabled) 0.5f else 0f
false
}
// return to main screen button
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()
backButton.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
parent.changeScreen(Screens.MAIN_MENU)
}
})
}
@ -144,15 +132,15 @@ class Settings(val parent: Game) : TimeTravelScreen() {
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)
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))
stage.act(Math.min(delta, 1 / 30f))
stage.draw()
}

@ -1,13 +0,0 @@
package com.last.commit.screen
import com.badlogic.gdx.InputProcessor
import com.badlogic.gdx.Screen
import com.last.commit.config.ActionCommand
abstract class TimeTravelScreen : Screen {
abstract fun handleKeyInput(action: ActionCommand)
abstract fun handleMouseInput(screenX: Int, screenY: Int, pointer: Int, button: Int)
abstract fun getInputProcessors(): Array<InputProcessor>
}

@ -1,14 +1,13 @@
package com.last.commit.stages
import com.badlogic.gdx.utils.viewport.ExtendViewport
import com.badlogic.gdx.utils.Align
import com.badlogic.gdx.Input
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
import com.badlogic.gdx.scenes.scene2d.ui.TextArea
import com.badlogic.gdx.utils.Align
import com.badlogic.gdx.utils.viewport.ExtendViewport
class PromptStage(skin: Skin?): Stage(ExtendViewport(300f, 300f)) {
class PromptStage(skin: Skin?) : Stage(ExtendViewport(300f, 300f)) {
private val textArea: TextArea;
var visible = false
@ -38,15 +37,15 @@ class PromptStage(skin: Skin?): Stage(ExtendViewport(300f, 300f)) {
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()
@ -57,7 +56,7 @@ class PromptStage(skin: Skin?): Stage(ExtendViewport(300f, 300f)) {
false
} else if (keyCode == Input.Keys.SPACE) {
next()
false
true
} else {
false
}

@ -66,4 +66,6 @@ class UIStage(path: String, val state: GameState) : Stage(ExtendViewport(512f, 5
addActor(mapLabel)
}
}
}

Loading…
Cancel
Save