-
-
Notifications
You must be signed in to change notification settings - Fork 558
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
update pathfinding API to use any AStarCell derivative
- Loading branch information
Showing
14 changed files
with
301 additions
and
168 deletions.
There are no files selected for viewing
98 changes: 0 additions & 98 deletions
98
fxgl-core/src/main/java/com/almasb/fxgl/core/collection/grid/Dungeon.java
This file was deleted.
Oops, something went wrong.
24 changes: 0 additions & 24 deletions
24
fxgl-core/src/main/java/com/almasb/fxgl/core/collection/grid/DungeonCell.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,6 @@ | |
|
||
package com.almasb.fxgl.pathfinding.astar; | ||
|
||
import com.almasb.fxgl.core.collection.grid.Grid; | ||
import com.almasb.fxgl.entity.Entity; | ||
import com.almasb.fxgl.entity.GameWorld; | ||
import com.almasb.fxgl.pathfinding.CellState; | ||
|
@@ -17,9 +16,13 @@ | |
import java.util.stream.Collectors; | ||
|
||
/** | ||
* Default implementation of the TraversableGrid<AStarCell> for pathfinding purposes. | ||
* Domain-specific grids, or those that require extra functionality, should extend | ||
* TraversableGrid directly. | ||
* | ||
* @author Almas Baimagambetov (AlmasB) ([email protected]) | ||
*/ | ||
public class AStarGrid extends Grid<AStarCell> { | ||
public final class AStarGrid extends TraversableGrid<AStarCell> { | ||
|
||
/** | ||
* Constructs A* grid with A* cells using given width and height. | ||
|
@@ -29,13 +32,6 @@ public AStarGrid(int width, int height) { | |
super(AStarCell.class, width, height, (x, y) -> new AStarCell(x, y, CellState.WALKABLE)); | ||
} | ||
|
||
public List<AStarCell> getWalkableCells() { | ||
return getCells() | ||
.stream() | ||
.filter(c -> c.getState().isWalkable()) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
/** | ||
* Generates an A* grid from the given world data. | ||
* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,13 +25,13 @@ | |
* @author Almas Baimagambetov ([email protected]) | ||
*/ | ||
@Required(CellMoveComponent.class) | ||
public final class AStarMoveComponent extends Component { | ||
public final class AStarMoveComponent<T extends AStarCell> extends Component { | ||
|
||
private CellMoveComponent moveComponent; | ||
|
||
private LazyValue<AStarPathfinder> pathfinder; | ||
private LazyValue<AStarPathfinder<T>> pathfinder; | ||
|
||
private List<AStarCell> path = new ArrayList<>(); | ||
private List<T> path = new ArrayList<>(); | ||
|
||
private Runnable delayedPathCalc = EmptyRunnable.INSTANCE; | ||
|
||
|
@@ -44,21 +44,21 @@ public final class AStarMoveComponent extends Component { | |
} | ||
}; | ||
|
||
public AStarMoveComponent(AStarGrid grid) { | ||
public AStarMoveComponent(TraversableGrid<T> grid) { | ||
this(new LazyValue<>(() -> grid)); | ||
} | ||
|
||
/** | ||
* This ctor is for cases when the grid has not been constructed yet. | ||
*/ | ||
public AStarMoveComponent(LazyValue<AStarGrid> grid) { | ||
pathfinder = new LazyValue<>(() -> new AStarPathfinder(grid.get())); | ||
public AStarMoveComponent(LazyValue<TraversableGrid<T>> grid) { | ||
pathfinder = new LazyValue<>(() -> new AStarPathfinder<>(grid.get())); | ||
} | ||
|
||
/** | ||
* This ctor is for cases when using a pre-built pathfinder. | ||
*/ | ||
public AStarMoveComponent(AStarPathfinder pathfinderValue) { | ||
public AStarMoveComponent(AStarPathfinder<T> pathfinderValue) { | ||
pathfinder = new LazyValue<>(() -> pathfinderValue); | ||
} | ||
|
||
|
@@ -93,7 +93,7 @@ public boolean isAtDestination() { | |
return isAtDestinationProp.get(); | ||
} | ||
|
||
public AStarGrid getGrid() { | ||
public TraversableGrid<T> getGrid() { | ||
return pathfinder.get().getGrid(); | ||
} | ||
|
||
|
@@ -104,7 +104,7 @@ public AStarGrid getGrid() { | |
* | ||
* @return cell where this entity is located | ||
*/ | ||
public Optional<AStarCell> getCurrentCell() { | ||
public Optional<T> getCurrentCell() { | ||
var cellX = moveComponent.getCellX(); | ||
var cellY = moveComponent.getCellY(); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,27 +21,27 @@ | |
/** | ||
* @author Almas Baimagambetov ([email protected]) | ||
*/ | ||
public final class AStarPathfinder implements Pathfinder<AStarCell> { | ||
public final class AStarPathfinder<T extends AStarCell> implements Pathfinder<T> { | ||
|
||
private final AStarGrid grid; | ||
private final TraversableGrid<T> grid; | ||
|
||
private final Heuristic<AStarCell> defaultHeuristic; | ||
private final DiagonalHeuristic<AStarCell> diagonalHeuristic; | ||
private final Heuristic<T> defaultHeuristic; | ||
private final DiagonalHeuristic<T> diagonalHeuristic; | ||
|
||
private boolean isCachingPaths = false; | ||
private Map<CacheKey, List<AStarCell>> cache = new HashMap<>(); | ||
private Map<CacheKey, List<T>> cache = new HashMap<>(); | ||
|
||
public AStarPathfinder(AStarGrid grid) { | ||
public AStarPathfinder(TraversableGrid<T> grid) { | ||
this(grid, new ManhattanDistance<>(), new OctileDistance<>()); | ||
} | ||
|
||
public AStarPathfinder(AStarGrid grid, Heuristic<AStarCell> defaultHeuristic, DiagonalHeuristic<AStarCell> diagonalHeuristic) { | ||
public AStarPathfinder(TraversableGrid<T> grid, Heuristic<T> defaultHeuristic, DiagonalHeuristic<T> diagonalHeuristic) { | ||
this.grid = grid; | ||
this.defaultHeuristic = defaultHeuristic; | ||
this.diagonalHeuristic = diagonalHeuristic; | ||
} | ||
|
||
public AStarGrid getGrid() { | ||
public TraversableGrid<T> getGrid() { | ||
return grid; | ||
} | ||
|
||
|
@@ -58,22 +58,22 @@ public boolean isCachingPaths() { | |
} | ||
|
||
@Override | ||
public List<AStarCell> findPath(int sourceX, int sourceY, int targetX, int targetY) { | ||
public List<T> findPath(int sourceX, int sourceY, int targetX, int targetY) { | ||
return findPath(grid.getData(), grid.get(sourceX, sourceY), grid.get(targetX, targetY)); | ||
} | ||
|
||
@Override | ||
public List<AStarCell> findPath(int sourceX, int sourceY, int targetX, int targetY, NeighborDirection neighborDirection) { | ||
public List<T> findPath(int sourceX, int sourceY, int targetX, int targetY, NeighborDirection neighborDirection) { | ||
return findPath(grid.getData(), grid.get(sourceX, sourceY), grid.get(targetX, targetY), neighborDirection); | ||
} | ||
|
||
@Override | ||
public List<AStarCell> findPath(int sourceX, int sourceY, int targetX, int targetY, List<AStarCell> busyCells) { | ||
return findPath(grid.getData(), grid.get(sourceX, sourceY), grid.get(targetX, targetY), busyCells.toArray(new AStarCell[0])); | ||
public List<T> findPath(int sourceX, int sourceY, int targetX, int targetY, List<T> busyCells) { | ||
return findPath(grid.getData(), grid.get(sourceX, sourceY), grid.get(targetX, targetY), NeighborDirection.FOUR_DIRECTIONS, busyCells.toArray(new AStarCell[0])); | ||
} | ||
|
||
@Override | ||
public List<AStarCell> findPath(int sourceX, int sourceY, int targetX, int targetY, NeighborDirection neighborDirection, List<AStarCell> busyCells) { | ||
public List<T> findPath(int sourceX, int sourceY, int targetX, int targetY, NeighborDirection neighborDirection, List<T> busyCells) { | ||
return findPath(grid.getData(), grid.get(sourceX, sourceY), grid.get(targetX, targetY), neighborDirection, busyCells.toArray(new AStarCell[0])); | ||
} | ||
|
||
|
@@ -87,7 +87,7 @@ public List<AStarCell> findPath(int sourceX, int sourceY, int targetX, int targe | |
* @param busyNodes busy "unwalkable" nodes | ||
* @return path as list of nodes from start (excl) to target (incl) or empty list if no path found | ||
*/ | ||
public List<AStarCell> findPath(AStarCell[][] grid, AStarCell start, AStarCell target, AStarCell... busyNodes) { | ||
public List<T> findPath(T[][] grid, T start, T target, T... busyNodes) { | ||
return findPath(grid, start, target, NeighborDirection.FOUR_DIRECTIONS, busyNodes); | ||
} | ||
|
||
|
@@ -101,7 +101,7 @@ public List<AStarCell> findPath(AStarCell[][] grid, AStarCell start, AStarCell t | |
* @param busyNodes busy "unwalkable" nodes | ||
* @return path as list of nodes from start (excl) to target (incl) or empty list if no path found | ||
*/ | ||
public List<AStarCell> findPath(AStarCell[][] grid, AStarCell start, AStarCell target, NeighborDirection neighborDirection, AStarCell... busyNodes) { | ||
public List<T> findPath(T[][] grid, T start, T target, NeighborDirection neighborDirection, AStarCell... busyNodes) { | ||
if (start == target || target.getState() == CellState.NOT_WALKABLE) | ||
return Collections.emptyList(); | ||
|
||
|
@@ -115,7 +115,7 @@ public List<AStarCell> findPath(AStarCell[][] grid, AStarCell start, AStarCell t | |
} | ||
} | ||
|
||
Heuristic<AStarCell> heuristic = (neighborDirection == FOUR_DIRECTIONS) ? defaultHeuristic : diagonalHeuristic; | ||
Heuristic<T> heuristic = (neighborDirection == FOUR_DIRECTIONS) ? defaultHeuristic : diagonalHeuristic; | ||
|
||
// reset grid cells data | ||
for (int y = 0; y < grid[0].length; y++) { | ||
|
@@ -195,13 +195,13 @@ public List<AStarCell> findPath(AStarCell[][] grid, AStarCell start, AStarCell t | |
return new ArrayList<>(path); | ||
} | ||
|
||
private List<AStarCell> buildPath(AStarCell start, AStarCell target) { | ||
List<AStarCell> path = new ArrayList<>(); | ||
private List<T> buildPath(T start, T target) { | ||
List<T> path = new ArrayList<>(); | ||
|
||
AStarCell tmp = target; | ||
T tmp = target; | ||
do { | ||
path.add(tmp); | ||
tmp = tmp.getParent(); | ||
tmp = (T) tmp.getParent(); | ||
} while (tmp != start); | ||
|
||
Collections.reverse(path); | ||
|
@@ -213,7 +213,7 @@ private List<AStarCell> buildPath(AStarCell start, AStarCell target) { | |
* @param busyNodes nodes which are busy, i.e. walkable but have a temporary obstacle | ||
* @return neighbors of the node | ||
*/ | ||
private List<AStarCell> getValidNeighbors(AStarCell node, NeighborDirection neighborDirection, AStarCell... busyNodes) { | ||
private List<T> getValidNeighbors(AStarCell node, NeighborDirection neighborDirection, AStarCell... busyNodes) { | ||
var result = grid.getNeighbors(node.getX(), node.getY(), neighborDirection); | ||
result.removeAll(Arrays.asList(busyNodes)); | ||
result.removeIf(cell -> !cell.isWalkable()); | ||
|
@@ -223,5 +223,4 @@ private List<AStarCell> getValidNeighbors(AStarCell node, NeighborDirection neig | |
private boolean isDiagonal(Cell current, Cell neighbor) { | ||
return neighbor.getX() - current.getX() != 0 && neighbor.getY() - current.getY() != 0; | ||
} | ||
|
||
} |
43 changes: 43 additions & 0 deletions
43
fxgl-entity/src/main/java/com/almasb/fxgl/pathfinding/astar/TraversableGrid.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* FXGL - JavaFX Game Library. The MIT License (MIT). | ||
* Copyright (c) AlmasB ([email protected]). | ||
* See LICENSE for details. | ||
*/ | ||
|
||
package com.almasb.fxgl.pathfinding.astar; | ||
|
||
import com.almasb.fxgl.core.collection.grid.CellGenerator; | ||
import com.almasb.fxgl.core.collection.grid.Grid; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* The supertype for any grid that can be traversed using A* pathfinding. | ||
* | ||
* @author Almas Baim (https://github.com/AlmasB) | ||
*/ | ||
public abstract class TraversableGrid<T extends AStarCell> extends Grid<T> { | ||
|
||
public TraversableGrid(Class<T> type, int width, int height) { | ||
super(type, width, height); | ||
} | ||
|
||
public TraversableGrid(Class<T> type, int width, int height, CellGenerator<T> populateFunction) { | ||
super(type, width, height, populateFunction); | ||
} | ||
|
||
public TraversableGrid(Class<T> type, int width, int height, int cellWidth, int cellHeight, CellGenerator<T> populateFunction) { | ||
super(type, width, height, cellWidth, cellHeight, populateFunction); | ||
} | ||
|
||
/** | ||
* @return all cells whose state is CellState.WALKABLE | ||
*/ | ||
public List<T> getWalkableCells() { | ||
return getCells() | ||
.stream() | ||
.filter(c -> c.getState().isWalkable()) | ||
.collect(Collectors.toList()); | ||
} | ||
} |
Oops, something went wrong.