package org.newdawn.slick.tests; import java.io.IOException; import org.newdawn.slick.BasicGame; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; import org.newdawn.slick.util.Bootstrap; import org.newdawn.slick.util.ResourceLoader; import org.newdawn.slick.util.pathfinding.Mover; import org.newdawn.slick.util.pathfinding.PathFindingContext; import org.newdawn.slick.util.pathfinding.TileBasedMap; import org.newdawn.slick.util.pathfinding.navmesh.Link; import org.newdawn.slick.util.pathfinding.navmesh.NavMesh; import org.newdawn.slick.util.pathfinding.navmesh.NavMeshBuilder; import org.newdawn.slick.util.pathfinding.navmesh.NavPath; import org.newdawn.slick.util.pathfinding.navmesh.Space; /** * A test to show nav-mesh generation on tile based maps. * * @author kevin */ public class NavMeshTest extends BasicGame implements PathFindingContext { /** The mesh built for this map */ private NavMesh navMesh; /** The builder used to create the nav-mesh from the tile based map */ private NavMeshBuilder builder; /** True if we're showing the open spaces from the mesh */ private boolean showSpaces = true; /** True if we're showing the linking points */ private boolean showLinks = true; /** The path if there is one current found between the two points */ private NavPath path; /** The x coordinate of the start of the search */ private float sx; /** The y coordinate of the start of the search */ private float sy; /** The x coordinate of the end of the search */ private float ex; /** The y coordinate of the end of the search */ private float ey; /** The tile based map we're searching across - loaded from a raw file */ private DataMap dataMap; /** * Create a new test */ public NavMeshTest() { super("Nav-mesh Test"); } /** * Initialise resources and the map data * * @param container the container the game is running in */ public void init(GameContainer container) throws SlickException { container.setShowFPS(false); try { dataMap = new DataMap("testdata/map.dat"); } catch (IOException e) { throw new SlickException("Failed to load map data", e); } builder = new NavMeshBuilder(); navMesh = builder.build(dataMap); System.out.println("Navmesh shapes: "+navMesh.getSpaceCount()); } /** * Update data map etc */ public void update(GameContainer container, int delta) throws SlickException { if (container.getInput().isKeyPressed(Input.KEY_1)) { showLinks = !showLinks; } if (container.getInput().isKeyPressed(Input.KEY_2)) { showSpaces = !showSpaces; } } /** * Render the game - in this case render the map and diagnostic data * * @param container The container we're running the game in * @param g The graphics context on which to render */ public void render(GameContainer container, Graphics g) throws SlickException { g.translate(50,50); for (int x=0;x<50;x++) { for (int y=0;y<50;y++) { if (dataMap.blocked(this, x, y)) { g.setColor(Color.gray); g.fillRect((x*10)+1,(y*10)+1,8,8); } } } if (showSpaces) { for (int i=0;i<navMesh.getSpaceCount();i++) { Space space = navMesh.getSpace(i); if (builder.clear(dataMap, space)) { g.setColor(new Color(1,1,0,0.5f)); g.fillRect(space.getX()*10, space.getY()*10, space.getWidth()*10, space.getHeight()*10); } g.setColor(Color.yellow); g.drawRect(space.getX()*10, space.getY()*10, space.getWidth()*10, space.getHeight()*10); if (showLinks) { int links = space.getLinkCount(); for (int j=0;j<links;j++) { Link link = space.getLink(j); g.setColor(Color.red); g.fillRect((link.getX()*10)-2, (link.getY()*10)-2,5,5); } } } } if (path != null) { g.setColor(Color.white); for (int i=0;i<path.length()-1;i++) { g.drawLine(path.getX(i)*10, path.getY(i)*10, path.getX(i+1)*10, path.getY(i+1)*10); } } } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.PathFindingContext#getMover() */ public Mover getMover() { return null; } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.PathFindingContext#getSearchDistance() */ public int getSearchDistance() { return 0; } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.PathFindingContext#getSourceX() */ public int getSourceX() { return 0; } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.PathFindingContext#getSourceY() */ public int getSourceY() { return 0; } /* * (non-Javadoc) * @see org.newdawn.slick.BasicGame#mousePressed(int, int, int) */ public void mousePressed(int button, int x, int y) { float mx = (x - 50) / 10.0f; float my = (y - 50) / 10.0f; if (button == 0) { sx = mx; sy = my; } else { ex = mx; ey = my; } path = navMesh.findPath(sx,sy,ex,ey,true); } /** * A simple raw map implementation for testing purposes * * @author kevin */ private class DataMap implements TileBasedMap { /** The map data */ private byte[] map = new byte[50*50]; /** * Create a new map loading it from a file * * @param ref The location to load the map from * @throws IOException Indicatese a failure to access map data */ public DataMap(String ref) throws IOException { ResourceLoader.getResourceAsStream(ref).read(map); } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.TileBasedMap#blocked(org.newdawn.slick.util.pathfinding.PathFindingContext, int, int) */ public boolean blocked(PathFindingContext context, int tx, int ty) { if ((tx < 0) || (ty < 0) || (tx >= 50) || (ty >= 50)) { return false; } return map[tx+(ty*50)] != 0; } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.TileBasedMap#getCost(org.newdawn.slick.util.pathfinding.PathFindingContext, int, int) */ public float getCost(PathFindingContext context, int tx, int ty) { return 1; } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.TileBasedMap#getHeightInTiles() */ public int getHeightInTiles() { return 50; } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.TileBasedMap#getWidthInTiles() */ public int getWidthInTiles() { return 50; } /* * (non-Javadoc) * @see org.newdawn.slick.util.pathfinding.TileBasedMap#pathFinderVisited(int, int) */ public void pathFinderVisited(int x, int y) { } } /** * Entry point to out application * * @param argv The arguments passed to the application */ public static void main(String[] argv) { Bootstrap.runAsApplication(new NavMeshTest(), 600, 600, false); } }