diff --git a/FakeMon/src/fmon/config.yaml b/FakeMon/src/fmon/config.yaml index dfdabd1..9d899f1 100644 --- a/FakeMon/src/fmon/config.yaml +++ b/FakeMon/src/fmon/config.yaml @@ -8,4 +8,4 @@ maxBoost: 6 newday: 02:00 tileSize: 48 yOffset: -4 -moveSpeed: 2.0 +moveSpeed: 3.0 diff --git a/FakeMon/src/fmon/world/GameMap.scala b/FakeMon/src/fmon/world/GameMap.scala index d063852..167eee6 100644 --- a/FakeMon/src/fmon/world/GameMap.scala +++ b/FakeMon/src/fmon/world/GameMap.scala @@ -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) diff --git a/FakeMon/src/fmon/world/Tileset.scala b/FakeMon/src/fmon/world/Tileset.scala index 3d02251..d6c47af 100644 --- a/FakeMon/src/fmon/world/Tileset.scala +++ b/FakeMon/src/fmon/world/Tileset.scala @@ -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( diff --git a/FakeMon/src/fmon/world/ui/GameView.scala b/FakeMon/src/fmon/world/ui/GameView.scala index 3c443f9..9fdbb9b 100644 --- a/FakeMon/src/fmon/world/ui/GameView.scala +++ b/FakeMon/src/fmon/world/ui/GameView.scala @@ -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)) } }