import uk.co.nickthecoder.glok.scene.Color
import uk.co.nickthecoder.glok.util.log
import uk.co.nickthecoder.kyd.Actor
import uk.co.nickthecoder.kyd.Behaviour
import uk.co.nickthecoder.kyd.util.Vector2
/**
* The base-class for items in the [Grid].
*
* Using the grid, we can [look] at neighbouring places to check if they are empty etc.
*/
abstract class Item : Behaviour {
/**
* Can [Player] blast this? Only used by [Soil].
* Note. soil.canBlast == `false` while it is being blasted.
*/
open val canBlast: Boolean get() = false
/**
* Can [Player] / [Monster] / [Rock] move here?
*
* True for [Player] and any empty spots.
* When [Monster] or [Rock] moves onto a [Player], the player dies.
*/
open val isEmpty: Boolean get() = false
/**
* The references to our position in the [Grid].
* (Note, I refer to these as _references_, not _indexes_, because they can be negative)
*/
var gridX = 0
var gridY = 0
override fun onEnteredStage(actor: Actor) {
val existing = PlayDirector.instance.grid.getAt(actor.position)
if (existing != null) {
log.error("Two items @ ${actor.position} : ${existing.behaviour} and $this")
actor.appearance.tintIfAvailable = Color.RED
existing.appearance.tintIfAvailable = Color.GREEN
}
val (x, y) = PlayDirector.instance.grid.putAt(actor.position, actor)
gridX = x
gridY = y
}
fun look(dx: Int, dy: Int): Actor? = PlayDirector.instance.grid[gridX + dx][gridY + dy]
fun move(actor: Actor, dx: Int, dy: Int): Boolean {
val grid = PlayDirector.instance.grid
val otherActor = grid[gridX + dx][gridY + dy]
if (otherActor.isEmpty()) {
grid[gridX][gridY] = null
actor.position += Vector2(dx * grid.gridSize, dy * grid.gridSize)
gridX += dx
gridY += dy
grid[gridX][gridY] = actor
return true
}
return false
}
}
fun Actor?.isEmpty(): Boolean {
if (this == null) return true
val item = behaviour as? Item ?: return true
return item.isEmpty
}
fun Actor?.isWall(): Boolean {
if (this == null) return false
return behaviour !is Monster
}
fun Actor?.isSoil(): Boolean {
if (this == null) return false
val item = behaviour as? Item ?: return false
return item.canBlast
}