com.github.mathiewz.slick.util.pathfinding.navmesh.NavMeshBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of modernized-slick Show documentation
Show all versions of modernized-slick Show documentation
The main purpose of this libraryis to modernize and maintain the slick2D library.
The newest version!
package com.github.mathiewz.slick.util.pathfinding.navmesh;
import java.util.ArrayList;
import com.github.mathiewz.slick.util.pathfinding.Mover;
import com.github.mathiewz.slick.util.pathfinding.PathFindingContext;
import com.github.mathiewz.slick.util.pathfinding.TileBasedMap;
/**
* The builder responsible for converting a tile based map into
* a navigation mesh
*
* @author kevin
*/
public class NavMeshBuilder implements PathFindingContext {
/** The current x position we're searching */
private int sx;
/** The current y position we've searching */
private int sy;
/** The smallest space allowed */
private final float smallestSpace = 0.2f;
/** True if we're working tile based */
private boolean tileBased;
/**
* Build a navigation mesh based on a tile map
*
* @param map
* The map to build the navigation mesh from
*
* @return The newly created navigation mesh
*/
public NavMesh build(TileBasedMap map) {
return build(map, true);
}
/**
* Build a navigation mesh based on a tile map
*
* @param map
* The map to build the navigation mesh from
* @param tileBased
* True if we'll use the tiles for the mesh initially
* rather than quad spacing
* @return The newly created navigation mesh
*/
public NavMesh build(TileBasedMap map, boolean tileBased) {
this.tileBased = tileBased;
ArrayList spaces = new ArrayList<>();
if (tileBased) {
for (int x = 0; x < map.getWidthInTiles(); x++) {
for (int y = 0; y < map.getHeightInTiles(); y++) {
if (!map.blocked(this, x, y)) {
spaces.add(new Space(x, y, 1, 1));
}
}
}
} else {
Space space = new Space(0, 0, map.getWidthInTiles(), map.getHeightInTiles());
subsection(map, space, spaces);
}
while (mergeSpaces(spaces)) {
}
linkSpaces(spaces);
return new NavMesh(spaces);
}
/**
* Merge the spaces that have been created to optimize out anywhere
* we can.
*
* @param spaces
* The list of spaces to be merged
* @return True if a merge occured and we'll have to start the merge
* process again
*/
private boolean mergeSpaces(ArrayList spaces) {
for (int source = 0; source < spaces.size(); source++) {
Space a = spaces.get(source);
for (int target = source + 1; target < spaces.size(); target++) {
Space b = spaces.get(target);
if (a.canMerge(b)) {
spaces.remove(a);
spaces.remove(b);
spaces.add(a.merge(b));
return true;
}
}
}
return false;
}
/**
* Determine the links between spaces
*
* @param spaces
* The spaces to link up
*/
private void linkSpaces(ArrayList spaces) {
for (int source = 0; source < spaces.size(); source++) {
Space a = spaces.get(source);
for (int target = source + 1; target < spaces.size(); target++) {
Space b = spaces.get(target);
if (a.hasJoinedEdge(b)) {
a.link(b);
b.link(a);
}
}
}
}
/**
* Check if a particular space is clear of blockages
*
* @param map
* The map the spaces are being built from
* @param space
* The space to check
* @return True if there are no blockages in the space
*/
public boolean clear(TileBasedMap map, Space space) {
if (tileBased) {
return true;
}
float x = 0;
boolean donex = false;
while (x < space.getWidth()) {
float y = 0;
boolean doney = false;
while (y < space.getHeight()) {
sx = (int) (space.getX() + x);
sy = (int) (space.getY() + y);
if (map.blocked(this, sx, sy)) {
return false;
}
y += 0.1f;
if (y > space.getHeight() && !doney) {
y = space.getHeight();
doney = true;
}
}
x += 0.1f;
if (x > space.getWidth() && !donex) {
x = space.getWidth();
donex = true;
}
}
return true;
}
/**
* Subsection a space into smaller spaces if required to find a non-blocked
* area.
*
* @param map
* The map being processed
* @param space
* The space being sections
* @param spaces
* The list of spaces that have been created
*/
private void subsection(TileBasedMap map, Space space, ArrayList spaces) {
if (!clear(map, space)) {
float width2 = space.getWidth() / 2;
float height2 = space.getHeight() / 2;
if (width2 < smallestSpace && height2 < smallestSpace) {
return;
}
subsection(map, new Space(space.getX(), space.getY(), width2, height2), spaces);
subsection(map, new Space(space.getX(), space.getY() + height2, width2, height2), spaces);
subsection(map, new Space(space.getX() + width2, space.getY(), width2, height2), spaces);
subsection(map, new Space(space.getX() + width2, space.getY() + height2, width2, height2), spaces);
} else {
spaces.add(space);
}
}
/**
* Path finding context implementation
*
* @return The current mover
*/
@Override
public Mover getMover() {
return null;
}
/**
* Path finding context implementation
*
* @return The current search distance
*/
@Override
public int getSearchDistance() {
return 0;
}
/**
* Path finding context implementation
*
* @return The current x location
*/
@Override
public int getSourceX() {
return sx;
}
/**
* Path finding context implementation
*
* @return The current y location
*/
@Override
public int getSourceY() {
return sy;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy