Added some collision with terrain. Needs some fixing since it doesn't stop in quite the right location and 'sticks'

This commit is contained in:
James Daly 2019-07-26 09:42:42 -04:00
parent c10da7ccf9
commit 0071e5af80
4 changed files with 72 additions and 7 deletions

View File

@ -8,4 +8,4 @@ maxBoost: 6
newday: 02:00
tileSize: 48
yOffset: -4
moveSpeed: 2.0
moveSpeed: 3.0

View File

@ -15,6 +15,8 @@ class GameMap(val width: Int, val height: Int, val tileset: Tileset) {
var tiles: IndexedSeq[AutoTile] = for (y <- 0 until height; x <- 0 until width) yield tileset.groundTiles.head
var doodads: IndexedSeq[AutoTile] = for (y <- 0 until height; x <- 0 until width) yield tileset.doodadTiles.head
def tileInfo(index: Int) = tileset.infoOf(tiles(index))
def saveTo(file: File): Unit = {
val ostream = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))
ostream.writeInt(width)

View File

@ -7,7 +7,9 @@ import fmon.draw.tile._
class Tileset(val groundTiles: IndexedSeq[AutoTile], val doodadTiles: IndexedSeq[AutoTile], val info: IndexedSeq[TileInfo]) {
def groundInfo(index: Int) = info(index)
def doodadInfo(index: Int) = info(index - groundTiles.size)
def doodadInfo(index: Int) = info(index + groundTiles.size)
val infoOf = (groundTiles.zipWithIndex.map{case (t, i) => (t, groundInfo(i))} ++ doodadTiles.zipWithIndex.map{case (t, i) => (t, doodadInfo(i))}).toMap
}
case class TileInfo(

View File

@ -14,6 +14,7 @@ import scalafx.Includes._
import scalafx.animation.AnimationTimer
import scalafx.beans.property._
import scalafx.collections.ObservableBuffer
import scalafx.geometry.Point2D
import scalafx.scene.control._
import scalafx.scene.image.ImageView
import scalafx.scene.input.{KeyCode, MouseEvent}
@ -41,6 +42,8 @@ class GameView {
var heroImg: AnimatedImageView = _
var currDir: Option[Direction.Value] = None
var level: GameMap = _
var lastTime = 0L
val timer = AnimationTimer(t => {
if (lastTime != 0L) {
@ -50,6 +53,7 @@ class GameView {
})
def loadLevel(level: GameMap): Unit = {
this.level = level
background.prefColumns = level.width
val tiles = for (y <- 0 until level.height; x <- 0 until level.width) yield {
new ImageView(level.smoothed(x, y)).delegate
@ -109,14 +113,71 @@ class GameView {
def act(dur: Duration): Unit = {
currDir match {
case Some(North) => hero.y -= dur.toSeconds() * Config.moveSpeed
case Some(East) => hero.x += dur.toSeconds() * Config.moveSpeed
case Some(West) => hero.x -= dur.toSeconds() * Config.moveSpeed
case Some(South) => hero.y += dur.toSeconds() * Config.moveSpeed
case Some(North) => slide(hero, 0, -dur.toSeconds() * Config.moveSpeed)
case Some(East) => slide(hero, dur.toSeconds() * Config.moveSpeed, 0)
case Some(West) => slide(hero, -dur.toSeconds() * Config.moveSpeed, 0)
case Some(South) => slide(hero, 0, +dur.toSeconds() * Config.moveSpeed)
case _ => ()
}
heroImg.x = hero.x * Config.tileSize
heroImg.y = hero.y * Config.tileSize
heroImg.y = hero.y * Config.tileSize + Config.yOffset
}
def slide(actor: Actor, dx: Double, dy: Double): Unit = {
// Need to do all corners
val px = if (dx < 0) actor.x else actor.x + 1
val py = if (dy < 0) actor.y else actor.y + 1
val tiles = tilesOnLine(new Point2D(px, py), new Point2D(px + dx, py + dy))
val condition = if (dx < 0 && dy < 0) {
info:TileInfo => info.doesPassSouth && info.doesPassEast
} else if (dx < 0) {
info: TileInfo => info.doesPassNorth && info.doesPassEast
} else if (dy < 0) {
info: TileInfo => info.doesPassSouth && info.doesPassWest
} else {
info: TileInfo => info.doesPassNorth && info.doesPassWest
}
val collisions = tiles.filterNot{case (i, _) => condition(level.tileInfo(i))}
if (!collisions.isEmpty) {
val (i, pt) = collisions.head
println(actor.y, pt.y)
actor.x += (pt.x - px)
actor.y += (pt.y - py)
//println(actor.x, actor.y)
} else {
actor.x += dx
actor.y += dy
}
}
def tilesOnLine(p: Point2D, q: Point2D): Seq[(Int, Point2D)] = {
val dx = q.x - p.x
val dy = q.y - p.y
val nx = Math.abs(dx).toInt
val ny = Math.abs(dy).toInt
val sx = Math.signum(dx)
val sy = Math.signum(dy)
var pts = Seq(p)
var pt = p
var ix = 0
var iy = 0
while (ix < nx || iy < ny) {
if ((0.5+ix) * ny < (0.5+iy) * nx) {
// next step is horizontal
pt = new Point2D(pt.x + sx, pt.y)
ix += 1
} else {
// next step is vertical
pt = new Point2D(pt.x, pt.y + sy)
ix += 1
}
pts :+= pt
}
pts.map(pt => (level.pt2index(pt.x.toInt, pt.y.toInt), pt))
}
}