Fix pathfinder, increase performance
This commit is contained in:
parent
3b55678835
commit
8b745c068a
|
@ -24,11 +24,11 @@ case class RawMap(var cases: List[RawCase], var width: Int, var height: Int) {
|
|||
|
||||
def getNeighbours(c: RawCase): Iterable[RawCase] = {
|
||||
var list = Nil: List[RawCase]
|
||||
list ::= getCase(c.getPosX, c.getPosY + 1)
|
||||
list ::= getCase(c.getPosX + 1, c.getPosY)
|
||||
list ::= getCase(c.getPosX, c.getPosY - 1)
|
||||
list ::= getCase(c.getPosX + 1, c.getPosY)
|
||||
list ::= getCase(c.getPosX, c.getPosY + 1)
|
||||
list ::= getCase(c.getPosX - 1, c.getPosY)
|
||||
list.filter((_c: RawCase) => _c != null && _c.getCollision.equals(Collision.ANY))
|
||||
list.filter((_c: RawCase) => _c != null)
|
||||
}
|
||||
|
||||
def getCase(x: Int, y: Int): RawCase = {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package fr.ynerant.leveleditor.game
|
||||
|
||||
import java.awt.event.{MouseEvent, MouseListener}
|
||||
import java.awt._
|
||||
import java.awt.event.{MouseEvent, MouseListener}
|
||||
import java.util.Random
|
||||
|
||||
import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister
|
||||
|
@ -21,6 +21,7 @@ class GameFrame(val map: RawMap) extends JFrame("Jeu") {
|
|||
private var reward = 20
|
||||
private var mobs = ListBuffer[Mob]()
|
||||
private var towers = ListBuffer[Tower]()
|
||||
private val pathFinder = PathFinder(this)
|
||||
final private var basicTower = null: JRadioButton
|
||||
final private var nullTower = null: JRadioButton
|
||||
final private var autoTower = null: JRadioButton
|
||||
|
@ -70,10 +71,16 @@ class GameFrame(val map: RawMap) extends JFrame("Jeu") {
|
|||
pane.add(winLabel)
|
||||
setVisible(true)
|
||||
new Thread(() => {
|
||||
while ( {
|
||||
hp > 0 && (round < 4 || mobs.nonEmpty)
|
||||
}) {
|
||||
tick()
|
||||
pathFinder.calculatePath()
|
||||
|
||||
while (hp > 0 && (round < 4 || mobs.nonEmpty)) {
|
||||
try
|
||||
tick()
|
||||
catch {
|
||||
case e: Throwable =>
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
try Thread.sleep(50L)
|
||||
catch {
|
||||
case e: InterruptedException =>
|
||||
|
@ -85,10 +92,12 @@ class GameFrame(val map: RawMap) extends JFrame("Jeu") {
|
|||
|
||||
def getMap: RawMap = map
|
||||
|
||||
def getPathFinder: PathFinder = pathFinder
|
||||
|
||||
def tick(): Unit = {
|
||||
if (mobs.isEmpty && round < 4) {
|
||||
round += 1
|
||||
val nb_mobs = round * (RANDOM.nextInt(16) + 1)
|
||||
val nb_mobs = round * (RANDOM.nextInt(8) + 1)
|
||||
for (_ <- 1 to nb_mobs) {
|
||||
val mob = Mob.getRandomMob
|
||||
do mob.move(RANDOM.nextInt(getMap.getWidth / 16), RANDOM.nextInt(getMap.getHeight / 16)) while ( {
|
||||
|
@ -144,11 +153,23 @@ class GameFrame(val map: RawMap) extends JFrame("Jeu") {
|
|||
else null
|
||||
if (tower == null || tower.getPrice > reward) return
|
||||
val c = getMap.getCase(x, y)
|
||||
println(x + ", " + y + ", " + tower + ", " + c)
|
||||
if (c == null || !c.getCollision.equals(Collision.ANY)) return
|
||||
c.setCollision(Collision.FULL)
|
||||
reward -= tower.getPrice
|
||||
towers += tower
|
||||
|
||||
pathFinder.invalidate()
|
||||
|
||||
val accessible = getMap.getCases.filter(c => !Collision.FULL.equals(c.getCollision))
|
||||
if (accessible.exists(c => c.getPosX > 0 && pathFinder.nextPos(c.getPosX, c.getPosY) == null) || !accessible.exists(c => c.getPosX == 0 && !c.getCollision.equals(Collision.FULL))) {
|
||||
println(accessible.exists(c => c.getPosX > 0 && pathFinder.nextPos(c.getPosX, c.getPosY) == null))
|
||||
println(!accessible.exists(c => c.getPosX == 0 && pathFinder.nextPos(c.getPosX, c.getPosY) != null))
|
||||
// We ensure that the end of the game is accessible from everywhere, the tower should not block the game
|
||||
c.setCollision(Collision.ANY)
|
||||
pathFinder.invalidate()
|
||||
}
|
||||
else {
|
||||
reward -= tower.getPrice
|
||||
towers += tower
|
||||
}
|
||||
}
|
||||
|
||||
override def mouseClicked(event: MouseEvent): Unit = {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package fr.ynerant.leveleditor.game
|
||||
|
||||
import java.util
|
||||
|
||||
import fr.ynerant.leveleditor.api.editor.{Collision, RawCase}
|
||||
|
||||
case class PathFinder(game: GameFrame) {
|
||||
var pred: Map[Int, RawCase] = Map(): Map[Int, RawCase]
|
||||
|
||||
def invalidate(): Unit = calculatePath()
|
||||
|
||||
def calculatePath(): Unit = {
|
||||
pred = Map()
|
||||
val queue = new util.ArrayDeque[RawCase]
|
||||
|
||||
for (i <- 0 until game.getMap.getHeight / 16) {
|
||||
val start = game.getMap.getCase(0, i)
|
||||
if (!start.getCollision.equals(Collision.FULL)) {
|
||||
pred += (coords(start) -> null)
|
||||
queue.add(start)
|
||||
}
|
||||
}
|
||||
|
||||
while (!queue.isEmpty) {
|
||||
val visiting = queue.poll
|
||||
game.getMap.getNeighbours(visiting).foreach(neighbour => {
|
||||
if (neighbour != null && !neighbour.collision.equals(Collision.FULL) && !pred.contains(coords(neighbour))) {
|
||||
pred += (coords(neighbour) -> visiting)
|
||||
queue.add(neighbour)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
def coords(rawCase: RawCase): Int = rawCase.getPosY * game.getMap.getWidth / 16 + rawCase.getPosX
|
||||
|
||||
def nextPos(x: Int, y: Int): RawCase = {
|
||||
pred.getOrElse(y * game.getMap.getWidth / 16 + x, null)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package fr.ynerant.leveleditor.game.mobs
|
||||
|
||||
import java.util
|
||||
import java.util.Random
|
||||
|
||||
import fr.ynerant.leveleditor.api.editor.RawCase
|
||||
|
@ -76,30 +75,8 @@ abstract class Mob() {
|
|||
return
|
||||
}
|
||||
|
||||
var visited = Nil: List[RawCase]
|
||||
val queue = new util.ArrayDeque[RawCase]
|
||||
var pred = Map(): Map[RawCase, RawCase]
|
||||
var last = null: RawCase
|
||||
queue.add(current)
|
||||
while (!queue.isEmpty) {
|
||||
val visiting = queue.poll
|
||||
visited ::= visiting
|
||||
game.getMap.getNeighbours(visiting).foreach(neighbour => {
|
||||
if (neighbour != null && !visited.contains(neighbour)) {
|
||||
pred += (neighbour -> visiting)
|
||||
queue.add(neighbour)
|
||||
if (neighbour.getPosX == 0) {
|
||||
last = neighbour
|
||||
queue.clear()
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
if (last != null) {
|
||||
while (pred(last) != current) last = pred(last)
|
||||
move(last.getPosX, last.getPosY)
|
||||
}
|
||||
}
|
||||
val newCase: RawCase = game.getPathFinder.nextPos(getX, getY)
|
||||
move(newCase.getPosX, newCase.getPosY)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue