Broken viewport stuff

viewport-stuff
trivernis 1 year ago
parent 2a4820db24
commit 563de84132
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -21,47 +21,27 @@ import com.last.commit.config.GameConfig
import com.last.commit.map.Interactable import com.last.commit.map.Interactable
import com.last.commit.map.TimeMap import com.last.commit.map.TimeMap
import com.last.commit.stages.InventoryStage import com.last.commit.stages.InventoryStage
import com.last.commit.stages.WorldStage
import com.last.commit.audio.GameSoundEffect import com.last.commit.audio.GameSoundEffect
import com.last.commit.audio.GameMusic import com.last.commit.audio.GameMusic
import kotlin.math.floor import kotlin.math.floor
/** First screen of the application. Displayed after the application is created. */ /** First screen of the application. Displayed after the application is created. */
class FirstScreen(val gameState: GameState) : Screen, InputProcessor { class FirstScreen(val gameState: GameState) : Screen, InputProcessor {
val viewportSize = 800f
private var delta = 0f
private var isColliding = false
val state = ColorState() 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 inventoryStage: InventoryStage
lateinit var worldStage: WorldStage
override fun show() { override fun show() {
// Prepare your screen here. // 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) 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) Gdx.input.setInputProcessor(this)
gameState.soundEngine.play(GameMusic.WORLD_MUSIC, 0.25f) // gameState.soundEngine.play(GameMusic.WORLD_MUSIC, 0.25f)
} }
fun loadGameConfig(): GameConfig { fun loadGameConfig(): GameConfig {
@ -72,157 +52,21 @@ class FirstScreen(val gameState: GameState) : Screen, InputProcessor {
} }
override fun render(delta: Float) { override fun render(delta: Float) {
this.delta = delta
// state.step((delta * 1000).toLong()) // state.step((delta * 1000).toLong())
// Draw your screen here. "delta" is the time since last render in seconds. // Draw your screen here. "delta" is the time since last render in seconds.
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
Gdx.gl.glClearColor(state.red, state.green, state.blue, 1f) Gdx.gl.glClearColor(state.red, state.green, state.blue, 1f)
handleInput() worldStage.act(delta)
handleMapBorderCollision() worldStage.draw()
inventoryStage.act(delta)
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)
inventoryStage.draw() inventoryStage.draw()
} }
fun renderInteractables(interactables: List<Interactable>) {
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) { override fun resize(width: Int, height: Int) {
// Resize your screen here. The parameters represent the new window size. // Resize your screen here. The parameters represent the new window size.
inventoryStage.resize(width, height) inventoryStage.resize(width, height)
handleRatioChange() worldStage.resize(width, height)
}
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()
} }
override fun pause() { override fun pause() {
@ -239,72 +83,27 @@ class FirstScreen(val gameState: GameState) : Screen, InputProcessor {
override fun dispose() { override fun dispose() {
// Destroy screen's assets here. // Destroy screen's assets here.
batch.dispose()
shapeRenderer.dispose()
} }
override fun keyDown(keycode: Int): Boolean { override fun keyDown(keycode: Int): Boolean {
// TODO: Auto-generated method stub return this.worldStage.keyDown(keycode)
return false
} }
override fun keyUp(keycode: Int): Boolean { override fun keyUp(keycode: Int): Boolean {
if (gameState.settings.getAction(keycode) == ActionCommand.OPEN_MENU) { if (gameState.settings.getAction(keycode) == ActionCommand.OPEN_MENU) {
Gdx.app.exit() Gdx.app.exit()
} }
this.worldStage.keyUp(keycode)
return false 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 { 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 return false
} }
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean { override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
// TODO: ("Not yet implemented") this.worldStage.touchDragged(screenX, screenY, pointer)
return false return false
} }
@ -317,4 +116,13 @@ class FirstScreen(val gameState: GameState) : Screen, InputProcessor {
// TODO: Not yet implemented // TODO: Not yet implemented
return false 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)
}
} }

@ -1,9 +1,22 @@
import com.last.commit.inventory.Inventory import com.last.commit.inventory.Inventory
import com.last.commit.config.GameSettings import com.last.commit.config.GameSettings
import com.last.commit.config.GameConfig
import com.last.commit.audio.SoundEngine 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 inventory: Inventory,
val settings: GameSettings, val settings: GameSettings,
public val soundEngine: SoundEngine, 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)
}
}

@ -2,14 +2,18 @@ package com.last.commit
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion 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.Rectangle
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.scenes.scene2d.Actor
import com.last.commit.inventory.Inventory import com.last.commit.inventory.Inventory
import com.last.commit.audio.GameSoundEffect import com.last.commit.audio.GameSoundEffect
import GameState 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) private var collider: Rectangle = Rectangle(0f, 0f, 0f, 0f)
var position: Vector2 = Vector2.Zero 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 movementSpeed = 200f
private val interactionRange = 60f private val interactionRange = 60f
private var lastStep = 0L private var lastStep = 0L
val batch = SpriteBatch()
val renderer = ShapeRenderer()
init { init {
val size = Math.max(textureRegion.regionWidth, textureRegion.regionHeight).toFloat() val size = Math.max(textureRegion.regionWidth, textureRegion.regionHeight).toFloat()
collider = Rectangle(0f, 0f, size, size) collider = Rectangle(0f, 0f, size, size)
position = Vector2()
} }
fun addItemToInventory(name: String) { fun addItemToInventory(name: String) {
gameState.inventory.add(name) gameState.inventory.add(name)
} }
fun getX(): Float { override fun getX(): Float {
return position.x return position.x
} }
fun getY(): Float { override fun getY(): Float {
return position.y return position.y
} }
@ -61,15 +66,15 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga
return collider return collider
} }
fun setPosition(x: Float, y: Float) { override fun setPosition(x: Float, y: Float) {
position[x] = y position[x] = y
} }
fun getWidth(): Float { override fun getWidth(): Float {
return collider.getWidth() return collider.getWidth()
} }
fun getHeight(): Float { override fun getHeight(): Float {
return collider.getHeight() return collider.getHeight()
} }
@ -105,22 +110,24 @@ class Player(private val textureRegion: TextureRegion, private val gameState: Ga
private fun getHalfPlayerWidth(): Float { private fun getHalfPlayerWidth(): Float {
return getWidth() / 2 return getWidth()/ 2
} }
private fun getHalfPlayerHeight(): Float { private fun getHalfPlayerHeight(): Float {
return getHeight() / 2 return getHeight() / 2
} }
fun getRotation(): Float { override fun getRotation(): Float {
return direction.angleDeg() return direction.angleDeg()
} }
fun render(batch: SpriteBatch) { override fun draw(batch: Batch, parentAlpha: Float) {
val halfPlayerWidth: Float = getHalfPlayerWidth() // TODO maybe use collider val halfPlayerWidth: Float = getHalfPlayerWidth() // TODO maybe use collider
// dimensions // dimensions
val halfPlayerHeight: Float = getHalfPlayerHeight() // TODO maybe use collider val halfPlayerHeight: Float = getHalfPlayerHeight() // TODO maybe use collider
// dimensions // dimensions
batch.draw( batch.draw(
textureRegion, getX(), getY(), textureRegion, getX(), getY(),
halfPlayerWidth, halfPlayerHeight, getWidth(), halfPlayerWidth, halfPlayerHeight, getWidth(),

@ -1,11 +1,27 @@
package com.last.commit.inventory 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<InventoryItem> = ArrayList() val items: MutableList<InventoryItem> = ArrayList()
public var updated = false public var updated = false
private set 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 * @param name the name of the subtexture loaded from xml
*/ */
@ -17,4 +33,5 @@ class Inventory {
fun remove(name: String) { fun remove(name: String) {
items.removeIf() {item -> item.name == name} items.removeIf() {item -> item.name == name}
} }
} }

@ -17,6 +17,7 @@ class InventoryItemTextureLoader(path: String) {
init { init {
itemsSpriteSheet = Texture("${path}.png") itemsSpriteSheet = Texture("${path}.png")
textureMapping = Gdx.files.local("${path}.xml") textureMapping = Gdx.files.local("${path}.xml")
this.parse()
} }
fun getTexture(itemName: String): TextureRegion { fun getTexture(itemName: String): TextureRegion {

@ -3,6 +3,8 @@ package com.last.commit.map
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch 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.objects.RectangleMapObject
import com.badlogic.gdx.maps.tiled.TiledMap import com.badlogic.gdx.maps.tiled.TiledMap
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer 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.Rectangle
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.utils.Array import com.badlogic.gdx.utils.Array
import com.badlogic.gdx.scenes.scene2d.Actor
import com.last.commit.Collidable import com.last.commit.Collidable
import com.last.commit.Player import com.last.commit.Player
import com.last.commit.Wall import com.last.commit.Wall
@ -19,7 +22,7 @@ import Position
import GameState import GameState
class TimeMap(fileName: String, val state: GameState) { class TimeMap(fileName: String, val state: GameState): Actor() {
private val CELL_SIZE = 64 private val CELL_SIZE = 64
private val walls = Array<Wall>() private val walls = Array<Wall>()
@ -51,7 +54,7 @@ class TimeMap(fileName: String, val state: GameState) {
for (teleporter in teleporters) { for (teleporter in teleporters) {
if (teleporter is RectangleMapObject) { if (teleporter is RectangleMapObject) {
if (teleporter.rectangle.contains(player.getX(), player.getY())) { 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) val targetMap = teleporter.properties.get("target", String::class.java)
System.out.println("Teleporting to targetMap $targetMap") System.out.println("Teleporting to targetMap $targetMap")
map = mapLoader.load("tiled/$targetMap") map = mapLoader.load("tiled/$targetMap")
@ -183,14 +186,13 @@ class TimeMap(fileName: String, val state: GameState) {
fun getTileHeight(): Float { fun getTileHeight(): Float {
return mapTileHeight.toFloat() return mapTileHeight.toFloat()
} }
fun render(batch: SpriteBatch, camera: OrthographicCamera, delta: Float) { override fun draw(batch: Batch, parentAlpha: Float) {
mapRenderer.setView(camera) mapRenderer.setView(batch.projectionMatrix, x, y, width.toFloat(), height.toFloat())
mapRenderer.render() mapRenderer.render()
} }
fun isCollidingWith(collidable: Collidable): Boolean { fun isCollidingWith(collidable: Collidable): Boolean {
for (wall in walls) { for (wall in walls) {
if (wall.collidesWidth(collidable)) { if (wall.collidesWidth(collidable)) {
return true return true

@ -2,24 +2,25 @@ package com.last.commit.stages
import com.badlogic.gdx.scenes.scene2d.Stage import com.badlogic.gdx.scenes.scene2d.Stage
import com.badlogic.gdx.scenes.scene2d.ui.Image 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.Inventory
import com.last.commit.inventory.InventoryItemTextureLoader 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) val textureLoader = InventoryItemTextureLoader(path)
var images: List<Image> = ArrayList()
val batch = SpriteBatch()
init { init {
textureLoader.parse() textureLoader.parse()
this.refresh()
this.setDebugAll(true)
} }
var visible = false
set(visible) {
field = visible
if (visible) {
refresh()
}
}
fun refresh() { fun refresh() {
super.clear() super.clear()
inventory.items.forEachIndexed { index, inventoryItem -> inventory.items.forEachIndexed { index, inventoryItem ->
@ -33,15 +34,15 @@ class InventoryStage(path: String, val inventory: Inventory) : Stage() {
} }
fun resize(width: Int, height: Int) { 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() { override fun draw() {
if (inventory.updated) { super.draw()
this.refresh()
}
if (visible) {
super.draw()
}
} }
} }

@ -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<Interactable>) {
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()
)
}
}
Loading…
Cancel
Save