From 563de84132e2c659b9bd14a46c391088fb4cdc4d Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 19 Nov 2022 20:49:59 +0100 Subject: [PATCH] Broken viewport stuff --- .../kotlin/com/last/commit/FirstScreen.kt | 238 ++---------------- .../main/kotlin/com/last/commit/GameState.kt | 19 +- .../src/main/kotlin/com/last/commit/Player.kt | 29 ++- .../com/last/commit/inventory/Inventory.kt | 19 +- .../inventory/InventoryItemTextureLoader.kt | 1 + .../kotlin/com/last/commit/map/TimeMap.kt | 14 +- .../com/last/commit/stages/InventoryStage.kt | 35 +-- .../com/last/commit/stages/WorldStage.kt | 190 ++++++++++++++ 8 files changed, 292 insertions(+), 253 deletions(-) create mode 100644 core/src/main/kotlin/com/last/commit/stages/WorldStage.kt diff --git a/core/src/main/kotlin/com/last/commit/FirstScreen.kt b/core/src/main/kotlin/com/last/commit/FirstScreen.kt index a7e54c3..6708726 100644 --- a/core/src/main/kotlin/com/last/commit/FirstScreen.kt +++ b/core/src/main/kotlin/com/last/commit/FirstScreen.kt @@ -21,47 +21,27 @@ import com.last.commit.config.GameConfig import com.last.commit.map.Interactable import com.last.commit.map.TimeMap import com.last.commit.stages.InventoryStage +import com.last.commit.stages.WorldStage import com.last.commit.audio.GameSoundEffect import com.last.commit.audio.GameMusic import kotlin.math.floor /** First screen of the application. Displayed after the application is created. */ class FirstScreen(val gameState: GameState) : Screen, InputProcessor { - - val viewportSize = 800f - - private var delta = 0f - private var isColliding = false val state = ColorState() - val batch = SpriteBatch() - val camera = OrthographicCamera(viewportSize, viewportSize) - lateinit var map: TimeMap // = TimeMap("tiled/base.tmx") - val playerTexture = Texture("sprites/characters.png") - val player = Player(TextureRegion(playerTexture, 300, 44, 35, 43), gameState) - var shapeRenderer = ShapeRenderer() - - val highlightColor = Color(0f, 0f, 1f, 0.5f) - lateinit var inventoryStage: InventoryStage + lateinit var worldStage: WorldStage override fun show() { // Prepare your screen here. - val gameConfig = this.loadGameConfig() - val randomMap = gameConfig.getRandomMap() - map = TimeMap(randomMap, gameState) - handleRatioChange() - - this.spawnPlayer() - this.updateCamera() - - player.addItemToInventory("drill") inventoryStage = InventoryStage("sprites/genericItems_spritesheet_colored", gameState.inventory) - shapeRenderer.setAutoShapeType(true) + worldStage = WorldStage(1200f, 1200f, gameState) + inventoryStage.viewport.setCamera(worldStage.camera) Gdx.input.setInputProcessor(this) - gameState.soundEngine.play(GameMusic.WORLD_MUSIC, 0.25f) + // gameState.soundEngine.play(GameMusic.WORLD_MUSIC, 0.25f) } fun loadGameConfig(): GameConfig { @@ -72,157 +52,21 @@ class FirstScreen(val gameState: GameState) : Screen, InputProcessor { } override fun render(delta: Float) { - this.delta = delta // 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) - handleInput() - handleMapBorderCollision() - - val mousePosition: Vector2 = getMousePosition() - player.lookAt(mousePosition) - val interactables = map.getInteractablesAt(player.getAbsoluteDirection()) - - batch.projectionMatrix = camera.combined - batch.begin() - this.map.render(batch, camera, delta) - this.player.render(batch) - batch.end() - - // TODO: auslagern in sperate Methode - renderInteractables(interactables) - + worldStage.act(delta) + worldStage.draw() + inventoryStage.act(delta) inventoryStage.draw() } - - fun renderInteractables(interactables: List) { - Gdx.gl.glEnable(GL20.GL_BLEND) - Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA) - shapeRenderer.setProjectionMatrix(this.camera.combined) - shapeRenderer.setColor(highlightColor) - shapeRenderer.begin(ShapeRenderer.ShapeType.Filled) - for (interactable in interactables) { - shapeRenderer.rect( - interactable.getCollider().x, - interactable.getCollider().y, - interactable.getCollider().width, - interactable.getCollider().height - ) - } - shapeRenderer.end() - Gdx.gl.glDisable(GL20.GL_BLEND) - } - - private fun getMousePosition(): Vector2 { - val unprojectedMousePosition = - camera.unproject(Vector3(Gdx.input.x.toFloat(), Gdx.input.y.toFloat(), 0f)) - return Vector2(unprojectedMousePosition.x, unprojectedMousePosition.y) - } - - private fun handleMapBorderCollision() { - val mapWidth: Int = map.width - val mapHeight: Int = map.height - val playerSize: Float = player.getSize() - val playerX: Float = MathUtils.clamp(this.player.getX(), 0f, mapWidth - playerSize) - val playerY: Float = MathUtils.clamp(this.player.getY(), 0f, mapHeight - playerSize) - this.player.setPosition(playerX, playerY) - } - - private fun handleInput() { - val horizontalMovement = Vector2() - if (Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)) { - horizontalMovement.sub(Vector2.X) - } - if (Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)) { - horizontalMovement.add(Vector2.X) - } - this.player.move(horizontalMovement, delta) - checkCollision() - if (this.isColliding) { - horizontalMovement.rotateDeg(180f) - this.player.move(horizontalMovement, delta) - } - val verticalMovement = Vector2() - if (Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)) { - verticalMovement.add(Vector2.Y) - } - if (Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)) { - verticalMovement.sub(Vector2.Y) - } - this.player.move(verticalMovement, delta) - checkCollision() - if (this.isColliding) { - verticalMovement.rotateDeg(180f) - this.player.move(verticalMovement, delta) - } - val hasMoved = !horizontalMovement.isZero || !verticalMovement.isZero - if (hasMoved) { - updateCamera() - } - } - - private fun spawnPlayer() { - val playerSpawn: Vector2 = map.getPlayerSpawn() - this.player.position = playerSpawn - } - - private fun checkCollision() { - this.isColliding = map.isCollidingWith(player) - } - - fun updateCamera() { - val cX: Float - val cY: Float - - val halfScreenWidth = camera.viewportWidth / 2 - val halfScreenHeight = camera.viewportHeight / 2 - val playerXPosition: Float = this.player.getX() - val playerYPosition: Float = this.player.getY() - val mapWidth: Int = map.width - val mapHeight: Int = map.height - - cX = if (playerXPosition < halfScreenWidth) { - halfScreenWidth - } else if (playerXPosition > mapWidth - halfScreenWidth) { - mapWidth - halfScreenWidth - } else { - playerXPosition - } - - cY = if (playerYPosition < halfScreenHeight) { - halfScreenHeight - } else if (playerYPosition > mapHeight - halfScreenHeight) { - mapHeight - halfScreenHeight - } else { - playerYPosition - } - - camera.position[cX, cY] = 0f - camera.update() - } - + override fun resize(width: Int, height: Int) { // Resize your screen here. The parameters represent the new window size. inventoryStage.resize(width, height) - handleRatioChange() - } - - fun handleRatioChange() { - val height = Gdx.graphics.height - val width = Gdx.graphics.width - - val wRatio = width.toFloat() / height.toFloat() - val hRatio = height.toFloat() / width.toFloat() - if (wRatio < 1) { - camera.viewportWidth = viewportSize * wRatio - camera.viewportHeight = viewportSize - } else { - camera.viewportHeight = viewportSize * hRatio - camera.viewportWidth = viewportSize - } - updateCamera() + worldStage.resize(width, height) } override fun pause() { @@ -239,72 +83,27 @@ class FirstScreen(val gameState: GameState) : Screen, InputProcessor { override fun dispose() { // Destroy screen's assets here. - batch.dispose() - shapeRenderer.dispose() } override fun keyDown(keycode: Int): Boolean { - // TODO: Auto-generated method stub - return false + return this.worldStage.keyDown(keycode) } override fun keyUp(keycode: Int): Boolean { if (gameState.settings.getAction(keycode) == ActionCommand.OPEN_MENU) { Gdx.app.exit() } + this.worldStage.keyUp(keycode) return false } - override fun keyTyped(character: Char): Boolean { - val characterUpperCase = character.uppercase() - val characterKey = Keys.valueOf(characterUpperCase) - - if (gameState.settings.getAction(characterKey) == ActionCommand.INTERACT) { - openDoor() - } else if (gameState.settings.getAction(characterKey) == ActionCommand.TIME_TRAVEL) { - map.teleport(player) - } else if (gameState.settings.getAction(characterKey) == ActionCommand.OPEN_INVENTORY) { - inventoryStage.visible = !inventoryStage.visible - } else if (character == 'p') { - gameState.inventory.add("compass") - inventoryStage.refresh() - } - return false - } - - override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean { - val mouseCoordinates: Vector2 = toWorldCoordinates(screenX.toFloat(), screenY.toFloat()) - println("Mouse World coordinates is ${mouseCoordinates.x}:${mouseCoordinates.y}") - - val playerDirection: Vector2 = player.getAbsoluteDirection() - println("Player interactor is ${playerDirection.x}:${playerDirection.y}") - map.interactWith(playerDirection.x, playerDirection.y, player.getCollider()) - // TODO Auto-generated method stub - return false - } - - fun openDoor() { - println("Attempt to toggle door") - val playerDirection: Vector2 = player.getAbsoluteDirection() - println("Player interactor is ${playerDirection.x}:${playerDirection.y}") - map.interactWith(playerDirection.x, playerDirection.y, player.getCollider()) - } - - fun toWorldCoordinates(x: Float, y: Float): Vector2 { - val mouseInWorldPosition = camera.unproject(Vector3(x, y, 0f)) - return Vector2( - floor(mouseInWorldPosition.x.toDouble() / this.map.getTileWidth()).toFloat(), - floor(mouseInWorldPosition.y.toDouble() / this.map.getTileHeight()).toFloat() - ) - } - override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean { - // TODO: ("Not yet implemented") + this.worldStage.touchUp(screenX, screenY, pointer, button) return false } override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean { - // TODO: ("Not yet implemented") + this.worldStage.touchDragged(screenX, screenY, pointer) return false } @@ -317,4 +116,13 @@ class FirstScreen(val gameState: GameState) : Screen, InputProcessor { // TODO: Not yet implemented return false } + + + override fun keyTyped(character: Char): Boolean { + return this.worldStage.keyTyped(character) + } + + override fun touchDown(p0: Int, p1: Int, p2: Int, p3: Int): Boolean { + return this.worldStage.touchDown(p0, p1, p2, p3) + } } diff --git a/core/src/main/kotlin/com/last/commit/GameState.kt b/core/src/main/kotlin/com/last/commit/GameState.kt index 96c0650..1de1910 100644 --- a/core/src/main/kotlin/com/last/commit/GameState.kt +++ b/core/src/main/kotlin/com/last/commit/GameState.kt @@ -1,9 +1,22 @@ import com.last.commit.inventory.Inventory import com.last.commit.config.GameSettings +import com.last.commit.config.GameConfig import com.last.commit.audio.SoundEngine +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.utils.Json -data class GameState( +class GameState( val inventory: Inventory, val settings: GameSettings, - public val soundEngine: SoundEngine, -) \ No newline at end of file + val soundEngine: SoundEngine, +) { + val gameConfig: GameConfig + get() = loadGameConfig() + + fun loadGameConfig(): GameConfig { + val jsonFileHandle = Gdx.files.local("config.json") + val json = Json() + + return json.fromJson(GameConfig::class.java, jsonFileHandle) + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/last/commit/Player.kt b/core/src/main/kotlin/com/last/commit/Player.kt index 11d4d9b..d1c795f 100644 --- a/core/src/main/kotlin/com/last/commit/Player.kt +++ b/core/src/main/kotlin/com/last/commit/Player.kt @@ -2,14 +2,18 @@ package com.last.commit import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.TextureRegion +import com.badlogic.gdx.graphics.g2d.Batch +import com.badlogic.gdx.graphics.glutils.ShapeRenderer +import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.math.Rectangle import com.badlogic.gdx.math.Vector2 +import com.badlogic.gdx.scenes.scene2d.Actor import com.last.commit.inventory.Inventory import com.last.commit.audio.GameSoundEffect import GameState -class Player(private val textureRegion: TextureRegion, private val gameState: GameState) : Collidable { +class Player(private val textureRegion: TextureRegion, private val gameState: GameState) : Collidable, Actor() { private var collider: Rectangle = Rectangle(0f, 0f, 0f, 0f) var position: Vector2 = Vector2.Zero @@ -17,22 +21,23 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga private val movementSpeed = 200f private val interactionRange = 60f private var lastStep = 0L + val batch = SpriteBatch() + val renderer = ShapeRenderer() init { val size = Math.max(textureRegion.regionWidth, textureRegion.regionHeight).toFloat() collider = Rectangle(0f, 0f, size, size) - position = Vector2() } fun addItemToInventory(name: String) { gameState.inventory.add(name) } - fun getX(): Float { + override fun getX(): Float { return position.x } - fun getY(): Float { + override fun getY(): Float { return position.y } @@ -61,15 +66,15 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga return collider } - fun setPosition(x: Float, y: Float) { + override fun setPosition(x: Float, y: Float) { position[x] = y } - fun getWidth(): Float { + override fun getWidth(): Float { return collider.getWidth() } - fun getHeight(): Float { + override fun getHeight(): Float { return collider.getHeight() } @@ -105,22 +110,24 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga private fun getHalfPlayerWidth(): Float { - return getWidth() / 2 + return getWidth()/ 2 } private fun getHalfPlayerHeight(): Float { return getHeight() / 2 } - fun getRotation(): Float { + override fun getRotation(): Float { return direction.angleDeg() } - - fun render(batch: SpriteBatch) { + + override fun draw(batch: Batch, parentAlpha: Float) { val halfPlayerWidth: Float = getHalfPlayerWidth() // TODO maybe use collider // dimensions val halfPlayerHeight: Float = getHalfPlayerHeight() // TODO maybe use collider // dimensions + + batch.draw( textureRegion, getX(), getY(), halfPlayerWidth, halfPlayerHeight, getWidth(), diff --git a/core/src/main/kotlin/com/last/commit/inventory/Inventory.kt b/core/src/main/kotlin/com/last/commit/inventory/Inventory.kt index 41aa062..62bbb84 100644 --- a/core/src/main/kotlin/com/last/commit/inventory/Inventory.kt +++ b/core/src/main/kotlin/com/last/commit/inventory/Inventory.kt @@ -1,11 +1,27 @@ package com.last.commit.inventory -class Inventory { +import com.badlogic.gdx.scenes.scene2d.Actor +import com.badlogic.gdx.scenes.scene2d.ui.Image +import com.badlogic.gdx.graphics.g2d.Batch +class Inventory: Actor() { + + val textureLoader = InventoryItemTextureLoader("sprites/genericItems_spritesheet_colored") val items: MutableList = ArrayList() public var updated = false private set + override fun draw(batch: Batch, delta: Float) { + items.mapIndexed { index, inventoryItem -> + val image = Image(textureLoader.getTexture(inventoryItem.name)) + image.x = index * 32f + image.width = 32f + image.height = 32f + + image + }.forEach{image -> image.draw(batch, 1f)} + } + /** * @param name the name of the subtexture loaded from xml */ @@ -17,4 +33,5 @@ class Inventory { fun remove(name: String) { items.removeIf() {item -> item.name == name} } + } \ No newline at end of file diff --git a/core/src/main/kotlin/com/last/commit/inventory/InventoryItemTextureLoader.kt b/core/src/main/kotlin/com/last/commit/inventory/InventoryItemTextureLoader.kt index 4c2322c..7a9b5e5 100644 --- a/core/src/main/kotlin/com/last/commit/inventory/InventoryItemTextureLoader.kt +++ b/core/src/main/kotlin/com/last/commit/inventory/InventoryItemTextureLoader.kt @@ -17,6 +17,7 @@ class InventoryItemTextureLoader(path: String) { init { itemsSpriteSheet = Texture("${path}.png") textureMapping = Gdx.files.local("${path}.xml") + this.parse() } fun getTexture(itemName: String): TextureRegion { diff --git a/core/src/main/kotlin/com/last/commit/map/TimeMap.kt b/core/src/main/kotlin/com/last/commit/map/TimeMap.kt index 1553f3b..fe0edc3 100644 --- a/core/src/main/kotlin/com/last/commit/map/TimeMap.kt +++ b/core/src/main/kotlin/com/last/commit/map/TimeMap.kt @@ -3,6 +3,8 @@ package com.last.commit.map import com.badlogic.gdx.Gdx import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.graphics.g2d.Batch +import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.maps.objects.RectangleMapObject import com.badlogic.gdx.maps.tiled.TiledMap import com.badlogic.gdx.maps.tiled.TiledMapTileLayer @@ -11,6 +13,7 @@ import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer import com.badlogic.gdx.math.Rectangle import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.utils.Array +import com.badlogic.gdx.scenes.scene2d.Actor import com.last.commit.Collidable import com.last.commit.Player import com.last.commit.Wall @@ -19,7 +22,7 @@ import Position import GameState -class TimeMap(fileName: String, val state: GameState) { +class TimeMap(fileName: String, val state: GameState): Actor() { private val CELL_SIZE = 64 private val walls = Array() @@ -51,7 +54,7 @@ class TimeMap(fileName: String, val state: GameState) { for (teleporter in teleporters) { if (teleporter is RectangleMapObject) { if (teleporter.rectangle.contains(player.getX(), player.getY())) { - state.soundEngine.play(GameSoundEffect.TIME_TRAVEL) + state.soundEngine.play(GameSoundEffect.TIME_TRAVEL, 0.5f) val targetMap = teleporter.properties.get("target", String::class.java) System.out.println("Teleporting to targetMap $targetMap") map = mapLoader.load("tiled/$targetMap") @@ -183,14 +186,13 @@ class TimeMap(fileName: String, val state: GameState) { fun getTileHeight(): Float { return mapTileHeight.toFloat() } - - fun render(batch: SpriteBatch, camera: OrthographicCamera, delta: Float) { - mapRenderer.setView(camera) + + override fun draw(batch: Batch, parentAlpha: Float) { + mapRenderer.setView(batch.projectionMatrix, x, y, width.toFloat(), height.toFloat()) mapRenderer.render() } fun isCollidingWith(collidable: Collidable): Boolean { - for (wall in walls) { if (wall.collidesWidth(collidable)) { return true diff --git a/core/src/main/kotlin/com/last/commit/stages/InventoryStage.kt b/core/src/main/kotlin/com/last/commit/stages/InventoryStage.kt index e7c4d30..599c4f5 100644 --- a/core/src/main/kotlin/com/last/commit/stages/InventoryStage.kt +++ b/core/src/main/kotlin/com/last/commit/stages/InventoryStage.kt @@ -2,24 +2,25 @@ package com.last.commit.stages import com.badlogic.gdx.scenes.scene2d.Stage import com.badlogic.gdx.scenes.scene2d.ui.Image +import com.badlogic.gdx.scenes.scene2d.ui.Table +import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup +import com.badlogic.gdx.graphics.OrthographicCamera +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.utils.viewport.FitViewport import com.last.commit.inventory.Inventory import com.last.commit.inventory.InventoryItemTextureLoader -class InventoryStage(path: String, val inventory: Inventory) : Stage() { +class InventoryStage(path: String, val inventory: Inventory) : Stage(FitViewport(1200f, 1200f)) { val textureLoader = InventoryItemTextureLoader(path) - + var images: List = ArrayList() + val batch = SpriteBatch() + init { textureLoader.parse() + this.refresh() + this.setDebugAll(true) } - var visible = false - set(visible) { - field = visible - if (visible) { - refresh() - } - } - fun refresh() { super.clear() inventory.items.forEachIndexed { index, inventoryItem -> @@ -33,15 +34,15 @@ class InventoryStage(path: String, val inventory: Inventory) : Stage() { } fun resize(width: Int, height: Int) { - viewport.update(width, height, true) + this.viewport.update(width, height, true) + } + + override fun act() { + this.refresh() + super.act() } override fun draw() { - if (inventory.updated) { - this.refresh() - } - if (visible) { - super.draw() - } + super.draw() } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/last/commit/stages/WorldStage.kt b/core/src/main/kotlin/com/last/commit/stages/WorldStage.kt new file mode 100644 index 0000000..9705a5b --- /dev/null +++ b/core/src/main/kotlin/com/last/commit/stages/WorldStage.kt @@ -0,0 +1,190 @@ +package com.last.commit.stages + +import GameState +import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.g2d.TextureRegion +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.graphics.glutils.ShapeRenderer +import com.badlogic.gdx.graphics.GL20 +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.scenes.scene2d.Stage +import com.badlogic.gdx.utils.viewport.FillViewport +import com.badlogic.gdx.math.Vector2 +import com.badlogic.gdx.math.MathUtils +import com.badlogic.gdx.math.Vector3 +import com.badlogic.gdx.Gdx +import com.last.commit.Player +import com.last.commit.map.TimeMap +import com.last.commit.map.Interactable +import com.last.commit.config.ActionCommand +import com.badlogic.gdx.Input.Keys +import kotlin.math.floor + +public class WorldStage(height: Float, width: Float, val state: GameState) : + Stage(FillViewport(height, width)) { + + val player = Player(TextureRegion(Texture("sprites/characters.png"), 300, 44, 35, 43), state) + var map = TimeMap(state.gameConfig.getRandomMap(), state) + var overlayRenderer = ShapeRenderer() + val highlightColor = Color(0f, 0f, 1f, 0.5f) + + init { + player.addItemToInventory("drill") + this.spawnPlayer() + this.updateCamera() + overlayRenderer.setAutoShapeType(true) + } + + fun resize(width: Int, height: Int) { + this.viewport.update(width, height, true) + } + + override fun act(delta: Float) { + super.act(delta) + this.handleInput(delta) + this.handleMapBorderCollision() + } + + override fun draw() { + super.draw() + val interactables = map.getInteractablesAt(player.getAbsoluteDirection()) + this.renderInteractables(interactables) + val mousePosition: Vector2 = getMousePosition() + player.lookAt(mousePosition) + + batch.projectionMatrix = camera.combined + } + + override fun keyTyped(character: Char): Boolean { + super.keyTyped(character) + val characterUpperCase = character.uppercase() + val characterKey = Keys.valueOf(characterUpperCase) + + if (state.settings.getAction(characterKey) == ActionCommand.INTERACT) { + openDoor() + } else if (state.settings.getAction(characterKey) == ActionCommand.TIME_TRAVEL) { + map.teleport(player) + } + return false + } + + override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean { + val mouseCoordinates: Vector2 = toWorldCoordinates(screenX.toFloat(), screenY.toFloat()) + println("Mouse World coordinates is ${mouseCoordinates.x}:${mouseCoordinates.y}") + + val playerDirection: Vector2 = player.getAbsoluteDirection() + println("Player interactor is ${playerDirection.x}:${playerDirection.y}") + map.interactWith(playerDirection.x, playerDirection.y, player.getCollider()) + return false + } + + private fun openDoor() { + println("Attempt to toggle door") + val playerDirection: Vector2 = player.getAbsoluteDirection() + println("Player interactor is ${playerDirection.x}:${playerDirection.y}") + map.interactWith(playerDirection.x, playerDirection.y, player.getCollider()) + } + + private fun spawnPlayer() { + val playerSpawn: Vector2 = map.getPlayerSpawn() + this.player.position = playerSpawn + this.addActor(player) + this.addActor(map) + } + + private fun renderInteractables(interactables: List) { + Gdx.gl.glEnable(GL20.GL_BLEND) + Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA) + overlayRenderer.setProjectionMatrix(this.camera.combined) + overlayRenderer.setColor(highlightColor) + overlayRenderer.begin(ShapeRenderer.ShapeType.Filled) + + for (interactable in interactables) { + overlayRenderer + .rect( + interactable.getCollider().x, + interactable.getCollider().y, + interactable.getCollider().width, + interactable.getCollider().height + ) + } + overlayRenderer.end() + Gdx.gl.glDisable(GL20.GL_BLEND) + } + + private fun updateCamera() { + val mapSize = Vector2(map.width.toFloat(), map.height.toFloat()) + + val scale = viewport.worldHeight / viewport.screenHeight + camera.position.x = MathUtils.clamp( + player.position.x, + (viewport.worldWidth / 2f) + (viewport.leftGutterWidth * scale), + mapSize.x - (viewport.worldWidth / 2f) - (viewport.rightGutterWidth * scale) + ) + camera.position.y = MathUtils.clamp( + player.position.y, + (viewport.worldHeight / 2f) + (viewport.topGutterHeight * scale), + mapSize.y - (viewport.worldHeight / 2f) - (viewport.bottomGutterHeight * scale) + ) + camera.update() + } + + private fun handleInput(delta: Float) { + val horizontalMovement = Vector2() + if (Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)) { + horizontalMovement.sub(Vector2.X) + } + if (Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)) { + horizontalMovement.add(Vector2.X) + } + this.player.move(horizontalMovement, delta) + var isColliding = this.map.isCollidingWith(player) + + if (isColliding) { + horizontalMovement.rotateDeg(180f) + this.player.move(horizontalMovement, delta) + } + val verticalMovement = Vector2() + if (Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)) { + verticalMovement.add(Vector2.Y) + } + if (Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)) { + verticalMovement.sub(Vector2.Y) + } + this.player.move(verticalMovement, delta) + isColliding = this.map.isCollidingWith(player) + if (isColliding) { + verticalMovement.rotateDeg(180f) + this.player.move(verticalMovement, delta) + } + val hasMoved = !horizontalMovement.isZero || !verticalMovement.isZero + + if (hasMoved) { + this.updateCamera() + } + } + + + private fun handleMapBorderCollision() { + val mapWidth: Int = map.width + val mapHeight: Int = map.height + val playerSize: Float = player.getSize() + val playerX: Float = MathUtils.clamp(this.player.getX(), 0f, mapWidth - playerSize) + val playerY: Float = MathUtils.clamp(this.player.getY(), 0f, mapHeight - playerSize) + this.player.setPosition(playerX, playerY) + } + + private fun getMousePosition(): Vector2 { + val unprojectedMousePosition = + viewport.unproject(Vector3(Gdx.input.x.toFloat(), Gdx.input.y.toFloat(), 0f)) + return Vector2(unprojectedMousePosition.x, unprojectedMousePosition.y) + } + + fun toWorldCoordinates(x: Float, y: Float): Vector2 { + val mouseInWorldPosition = viewport.unproject(Vector3(x, y, 0f)) + return Vector2( + floor(mouseInWorldPosition.x.toDouble() / this.map.getTileWidth()).toFloat(), + floor(mouseInWorldPosition.y.toDouble() / this.map.getTileHeight()).toFloat() + ) + } +}