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] = {
|
def getNeighbours(c: RawCase): Iterable[RawCase] = {
|
||||||
var list = Nil: List[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, 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 - 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 = {
|
def getCase(x: Int, y: Int): RawCase = {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package fr.ynerant.leveleditor.game
|
package fr.ynerant.leveleditor.game
|
||||||
|
|
||||||
import java.awt.event.{MouseEvent, MouseListener}
|
|
||||||
import java.awt._
|
import java.awt._
|
||||||
|
import java.awt.event.{MouseEvent, MouseListener}
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
import fr.ynerant.leveleditor.api.editor.sprites.SpriteRegister
|
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 reward = 20
|
||||||
private var mobs = ListBuffer[Mob]()
|
private var mobs = ListBuffer[Mob]()
|
||||||
private var towers = ListBuffer[Tower]()
|
private var towers = ListBuffer[Tower]()
|
||||||
|
private val pathFinder = PathFinder(this)
|
||||||
final private var basicTower = null: JRadioButton
|
final private var basicTower = null: JRadioButton
|
||||||
final private var nullTower = null: JRadioButton
|
final private var nullTower = null: JRadioButton
|
||||||
final private var autoTower = null: JRadioButton
|
final private var autoTower = null: JRadioButton
|
||||||
|
@ -70,10 +71,16 @@ class GameFrame(val map: RawMap) extends JFrame("Jeu") {
|
||||||
pane.add(winLabel)
|
pane.add(winLabel)
|
||||||
setVisible(true)
|
setVisible(true)
|
||||||
new Thread(() => {
|
new Thread(() => {
|
||||||
while ( {
|
pathFinder.calculatePath()
|
||||||
hp > 0 && (round < 4 || mobs.nonEmpty)
|
|
||||||
}) {
|
while (hp > 0 && (round < 4 || mobs.nonEmpty)) {
|
||||||
|
try
|
||||||
tick()
|
tick()
|
||||||
|
catch {
|
||||||
|
case e: Throwable =>
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
try Thread.sleep(50L)
|
try Thread.sleep(50L)
|
||||||
catch {
|
catch {
|
||||||
case e: InterruptedException =>
|
case e: InterruptedException =>
|
||||||
|
@ -85,10 +92,12 @@ class GameFrame(val map: RawMap) extends JFrame("Jeu") {
|
||||||
|
|
||||||
def getMap: RawMap = map
|
def getMap: RawMap = map
|
||||||
|
|
||||||
|
def getPathFinder: PathFinder = pathFinder
|
||||||
|
|
||||||
def tick(): Unit = {
|
def tick(): Unit = {
|
||||||
if (mobs.isEmpty && round < 4) {
|
if (mobs.isEmpty && round < 4) {
|
||||||
round += 1
|
round += 1
|
||||||
val nb_mobs = round * (RANDOM.nextInt(16) + 1)
|
val nb_mobs = round * (RANDOM.nextInt(8) + 1)
|
||||||
for (_ <- 1 to nb_mobs) {
|
for (_ <- 1 to nb_mobs) {
|
||||||
val mob = Mob.getRandomMob
|
val mob = Mob.getRandomMob
|
||||||
do mob.move(RANDOM.nextInt(getMap.getWidth / 16), RANDOM.nextInt(getMap.getHeight / 16)) while ( {
|
do mob.move(RANDOM.nextInt(getMap.getWidth / 16), RANDOM.nextInt(getMap.getHeight / 16)) while ( {
|
||||||
|
@ -144,12 +153,24 @@ class GameFrame(val map: RawMap) extends JFrame("Jeu") {
|
||||||
else null
|
else null
|
||||||
if (tower == null || tower.getPrice > reward) return
|
if (tower == null || tower.getPrice > reward) return
|
||||||
val c = getMap.getCase(x, y)
|
val c = getMap.getCase(x, y)
|
||||||
println(x + ", " + y + ", " + tower + ", " + c)
|
|
||||||
if (c == null || !c.getCollision.equals(Collision.ANY)) return
|
if (c == null || !c.getCollision.equals(Collision.ANY)) return
|
||||||
c.setCollision(Collision.FULL)
|
c.setCollision(Collision.FULL)
|
||||||
|
|
||||||
|
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
|
reward -= tower.getPrice
|
||||||
towers += tower
|
towers += tower
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override def mouseClicked(event: MouseEvent): Unit = {
|
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
|
package fr.ynerant.leveleditor.game.mobs
|
||||||
|
|
||||||
import java.util
|
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
import fr.ynerant.leveleditor.api.editor.RawCase
|
import fr.ynerant.leveleditor.api.editor.RawCase
|
||||||
|
@ -76,30 +75,8 @@ abstract class Mob() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var visited = Nil: List[RawCase]
|
val newCase: RawCase = game.getPathFinder.nextPos(getX, getY)
|
||||||
val queue = new util.ArrayDeque[RawCase]
|
move(newCase.getPosX, newCase.getPosY)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue