You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gamejam-22/core/src/main/kotlin/com/last/commit/map/TimeMap.kt

219 lines
8.0 KiB
Kotlin

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
import com.badlogic.gdx.maps.tiled.TmxMapLoader
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
import com.last.commit.audio.GameSoundEffect
import Position
import GameState
class TimeMap(fileName: String, val state: GameState): Actor() {
private val CELL_SIZE = 64
private val walls = Array<Wall>()
private val doors = Array<Door>()
private val collectibles = Array<Collectible>()
val mapLoader: TmxMapLoader = TmxMapLoader()
var mapRenderer: OrthogonalTiledMapRenderer
var map: TiledMap
var gridWidth = 0
var gridHeight = 0
var width = 0
var height = 0
var mapTileWidth = 0
var mapTileHeight = 0
var halfMapTileWidth = 0f
var halfMapTileHeight = 0f
init {
map = mapLoader.load(fileName)
mapRenderer = OrthogonalTiledMapRenderer(map)
loadDimensions()
loadWalls()
loadCollectibles()
}
fun teleport(player: Player) {
val teleporters = map.layers["Teleporter"].objects
for (teleporter in teleporters) {
if (teleporter is RectangleMapObject) {
if (teleporter.rectangle.contains(player.getX(), player.getY())) {
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")
mapRenderer.map = map
loadDimensions()
loadWalls()
loadCollectibles()
}
} else {
println("Found illegal teleporter. ${teleporter.properties.get("id")}")
}
}
}
fun getPlayerSpawn(): Vector2 {
val mapLayers = map.layers
val spawnPoints = mapLayers["Spawnpoints"].objects
for (spawnPoint in spawnPoints) {
val spawnPointProperties = spawnPoint.properties
if (spawnPointProperties != null && spawnPointProperties.containsKey("playerSpawn")) {
val isPlayerSpawn = spawnPointProperties.get("playerSpawn", Boolean::class.java)
if (java.lang.Boolean.TRUE == isPlayerSpawn) {
val x = spawnPointProperties.get("x", Float::class.java)
val y = spawnPointProperties.get("y", Float::class.java)
return Vector2(x, y)
}
}
}
Gdx.app.debug("SurvislandMap", "No spawn point found in map. Return map origin.")
return Vector2.Zero
}
private fun loadDimensions() {
val prop = map.properties
this.gridWidth = prop.get("width", Int::class.java)
this.gridHeight = prop.get("height", Int::class.java)
this.width = gridWidth * CELL_SIZE
this.height = gridHeight * CELL_SIZE
this.mapTileWidth = map.properties.get("tilewidth", Int::class.java)
this.mapTileHeight = map.properties.get("tileheight", Int::class.java)
this.halfMapTileWidth = mapTileWidth / 2f
this.halfMapTileHeight = mapTileHeight / 2f
}
private fun loadWalls() {
walls.clear()
doors.clear()
val wallsLayer = map.layers["Walls"] as TiledMapTileLayer
for (column in 0 until wallsLayer.width) {
for (row in 0 until wallsLayer.height) {
val cell: TiledMapTileLayer.Cell? = wallsLayer.getCell(column, row)
if (cell != null) {
val isDoor: Boolean = cell.getTile().getProperties().get("isDoor", false, Boolean::class.java)
val wallCollider = Rectangle(
column.toFloat() * wallsLayer.tileWidth,
row.toFloat() * wallsLayer.tileHeight, wallsLayer.tileWidth.toFloat(),
wallsLayer.tileHeight.toFloat()
)
if (java.lang.Boolean.TRUE == isDoor) {
doors.add(Door(column, row, wallCollider, cell))
} else {
walls.add(Wall(column, row, wallCollider, cell))
}
}
}
}
}
fun loadCollectibles() {
this.collectibles.clear()
val collectiableLayer = map.layers["Collectibles"]
if (collectiableLayer == null) {
println("Could not load collectibles layer. Check map.")
return
}
val collectibleMapObjects = collectiableLayer.objects
for (mapObject in collectibleMapObjects) {
val mapObjectProperties = mapObject.properties
val x = mapObjectProperties.get("x", Float::class.java)
val gridX = Math.round(x / mapTileWidth)
val y = mapObjectProperties.get("y", Float::class.java)
val gridY = Math.round(y / mapTileHeight)
val width = mapObjectProperties.get("width", Float::class.java)
val height = mapObjectProperties.get("height", Float::class.java)
if (mapObject is RectangleMapObject) {
val itemName = mapObjectProperties.get("item", String::class.java)
this.collectibles.add(Collectible(itemName, Position(x, y, gridX, gridY), width, height))
} else {
println("Found non-rectangular map object at ${x}-${y} skipping it")
}
}
println("Loaded ${collectibles.size} collectibles")
}
private fun findInteractableAtPosition(gridX: Int, gridY: Int): Interactable? {
for (door in doors) {
if (door.gridX == gridX && door.gridY == gridY && door is Door) {
return door
}
}
for (collectible in collectibles) {
if (collectible.pos.gridX == gridX && collectible.pos.gridY == gridY) {
return collectible
}
}
return null
}
fun interactWith(x: Float, y: Float, blockingCollider: Rectangle) {
val gridX = x.toInt() / CELL_SIZE
val gridY = y.toInt() / CELL_SIZE
println("Interacting with element at $gridX:$gridY")
//if no door is found return
val interactable: Interactable = this.findInteractableAtPosition(gridX, gridY) ?: return
//else continue
interactable.interact(blockingCollider, state)
}
fun getTileWidth(): Float {
return mapTileWidth.toFloat()
}
fun getTileHeight(): Float {
return mapTileHeight.toFloat()
}
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
}
}
for (door in doors) {
if (door.collidesWidth(collidable)) {
return true
}
}
return false
}
fun getInteractablesAt(absoluteDirection: Vector2): List<Interactable> {
val interactables = ArrayList<Interactable>()
val c = collectibles.filter { it.getCollider().contains(absoluteDirection) }
interactables.addAll(c)
val w = doors.filter { it.getCollider().contains(absoluteDirection) }
interactables.addAll(w)
return interactables
}
}