Compare commits

...

2 Commits

Author SHA1 Message Date
Yohann D'ANELLO 1347711d30 Readme 2020-05-29 23:51:54 +02:00
Yohann D'ANELLO def19e5750 Les mobs peuvent se déplacer en diagonale 2020-05-29 23:40:11 +02:00
4 changed files with 52 additions and 9 deletions

View File

@ -161,7 +161,7 @@ Cette tour tire des rayons laser dans les quatre directions et chaque mob reçoi
## Implémentation ## Implémentation
Le projet est intégralement fait en Java. On ne détaillera pas ici la partie éditeur de niveau, bien qu'elle soit Le projet est intégralement fait en Scala. On ne détaillera pas ici la partie éditeur de niveau, bien qu'elle soit
conséquente. conséquente.
Une fois que l'utilisateur a choisi la carte à utilisateur via un menu de sélection, le jeu se lance dans une fenêtre Une fois que l'utilisateur a choisi la carte à utilisateur via un menu de sélection, le jeu se lance dans une fenêtre
@ -190,3 +190,15 @@ Il en est de même pour les tours, qui hérite de `Tower`.
L'intérêt de l'héritage par rapport à un type donné à une classe Mob (paramètres donnés dans une enumération `MobType` L'intérêt de l'héritage par rapport à un type donné à une classe Mob (paramètres donnés dans une enumération `MobType`
par exemple) est de pouvoir mieux personnaliser les fonctions, par exemple en intégrant les dégâts aléatoires. par exemple) est de pouvoir mieux personnaliser les fonctions, par exemple en intégrant les dégâts aléatoires.
### Déplacement dynamique
Le déplacement des mobs apparaît continu. Il n'est en rien dans le fond : la carte est discrétisée, et les mobs se
situent sur des coordonnées entières. La position affichée d'un mob est calculée selon sa case de départ, sa case
d'arrivée et le temps qu'il lui reste à attendre avant de pouvoir se déplacer. La vitesse varie alors selon les mobs.
### Déplacement en diagonale
Les mobs peuvent se déplacer en diagonale. Cela est comptabilisé comme un déplacement de coût 1 : la topologie de la
carte est alors un plan muni de la norme infinie. Ce n'est plus un simple parcours en largeur : à distance égale de
l'objectif, on préférera se déplacer de manière horizontale plutôt qu'en diagonale, de manière à avoir un déplacement
plus naturel.

Binary file not shown.

View File

@ -28,6 +28,10 @@ case class RawMap(var cases: List[RawCase], var width: Int, var height: Int) {
list ::= getCase(c.getPosX + 1, c.getPosY) 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 - 1, c.getPosY)
list ::= getCase(c.getPosX - 1, c.getPosY + 1)
list ::= getCase(c.getPosX - 1, c.getPosY - 1)
list ::= getCase(c.getPosX + 1, c.getPosY + 1)
list ::= getCase(c.getPosX + 1, c.getPosY - 1)
list.filter((_c: RawCase) => _c != null) list.filter((_c: RawCase) => _c != null)
} }

View File

@ -11,28 +11,55 @@ case class PathFinder(game: GameFrame) {
def calculatePath(): Unit = { def calculatePath(): Unit = {
pred = Map() pred = Map()
val queue = new util.ArrayDeque[RawCase] val queueactu = new util.ArrayDeque[RawCase]
val queuesuivdroit = new util.ArrayDeque[(RawCase, RawCase)]
val queuesuivdiag = new util.ArrayDeque[(RawCase, RawCase)]
var edges = List(): List[(RawCase, RawCase)]
for (i <- 0 until game.getMap.getHeight / 16) { for (i <- 0 until game.getMap.getHeight / 16) {
val start = game.getMap.getCase(0, i) val start = game.getMap.getCase(0, i)
if (!start.getCollision.equals(Collision.FULL)) { if (!start.getCollision.equals(Collision.FULL)) {
pred += (coords(start) -> null) pred += (coords(start) -> null)
queue.add(start) queueactu.add(start)
} }
} }
while (!queue.isEmpty) { while (!queueactu.isEmpty) {
val visiting = queue.poll val visiting = queueactu.poll
game.getMap.getNeighbours(visiting).foreach(neighbour => { game.getMap.getNeighbours(visiting).foreach(neighbour => {
if (neighbour != null && !neighbour.collision.equals(Collision.FULL) && !pred.contains(coords(neighbour))) { if ((neighbour != null && !neighbour.collision.equals(Collision.FULL)) && !edges.contains(visiting, neighbour)
pred += (coords(neighbour) -> visiting) && (!game.getMap.getCase(neighbour.getPosX, visiting.getPosY).collision.equals(Collision.FULL)
queue.add(neighbour) && !game.getMap.getCase(visiting.getPosX, neighbour.getPosY).collision.equals(Collision.FULL))) {
edges ::= (visiting, neighbour)
if (visiting.getPosY == neighbour.getPosY || visiting.getPosX == neighbour.getPosX) {
queuesuivdroit.add((neighbour, visiting))
}
else {
queuesuivdiag.add((neighbour, visiting))
}
} }
}) })
if (queueactu.isEmpty) {
while (!queuesuivdroit.isEmpty) {
val (actu, prev) = queuesuivdroit.poll
if (!pred.contains(coords(actu))) {
pred += (coords(actu) -> prev)
queueactu.add(actu)
}
}
while (!queuesuivdiag.isEmpty) {
val (actu, prev) = queuesuivdiag.poll
if (!pred.contains(coords(actu))) {
pred += (coords(actu) -> prev)
queueactu.add(actu)
}
}
}
} }
} }
def coords(rawCase: RawCase): Int = rawCase.getPosY * game.getMap.getWidth / 16 + rawCase.getPosX def coords(RawCase: RawCase): Int = RawCase.getPosY * game.getMap.getWidth / 16 + RawCase.getPosX
def nextPos(x: Int, y: Int): RawCase = { def nextPos(x: Int, y: Int): RawCase = {
pred.getOrElse(y * game.getMap.getWidth / 16 + x, null) pred.getOrElse(y * game.getMap.getWidth / 16 + x, null)