flood fill room discovery
This commit is contained in:
@@ -3,7 +3,6 @@ package mightypork.rogue.world;
|
||||
|
||||
public class Sides {
|
||||
|
||||
//@formatter:off
|
||||
public static final byte NW = (byte) 0b10000000;
|
||||
public static final byte N = 0b01000000;
|
||||
public static final byte NE = 0b00100000;
|
||||
@@ -13,15 +12,16 @@ public class Sides {
|
||||
public static final byte SW = 0b00000010;
|
||||
public static final byte W = 0b00000001;
|
||||
|
||||
public static final byte CARDINAL = N|S|E|W;
|
||||
public static final byte DIAGONAL = NE|NW|SE|SW;
|
||||
public static final byte CARDINAL = N | S | E | W;
|
||||
public static final byte DIAGONAL = NE | NW | SE | SW;
|
||||
|
||||
public static final byte NW_CORNER = W|NW|N;
|
||||
public static final byte NE_CORNER = E|NE|N;
|
||||
public static final byte SW_CORNER = W|SW|S;
|
||||
public static final byte SE_CORNER = E|SE|S;
|
||||
public static final byte NW_CORNER = W | NW | N;
|
||||
public static final byte NE_CORNER = E | NE | N;
|
||||
public static final byte SW_CORNER = W | SW | S;
|
||||
public static final byte SE_CORNER = E | SE | S;
|
||||
|
||||
private final static Coord[] side = {
|
||||
//@formatter:off
|
||||
public final static Coord[] allSides = {
|
||||
Coord.make(-1, -1),
|
||||
Coord.make(0, -1),
|
||||
Coord.make(1, -1),
|
||||
@@ -31,13 +31,28 @@ public class Sides {
|
||||
Coord.make(-1, 1),
|
||||
Coord.make(-1, 0)
|
||||
};
|
||||
|
||||
public final static Coord[] cardinalSides = {
|
||||
Coord.make(0, -1),
|
||||
Coord.make(1, 0),
|
||||
Coord.make(0, 1),
|
||||
Coord.make(-1, 0)
|
||||
};
|
||||
|
||||
//@formatter:on
|
||||
|
||||
/**
|
||||
* Get element from all sides
|
||||
*
|
||||
* @param i side index
|
||||
* @return the side coord
|
||||
*/
|
||||
public static Coord get(int i)
|
||||
{
|
||||
return side[i]; // FIXME Coord is mutable
|
||||
return allSides[i]; // FIXME Coord is mutable
|
||||
}
|
||||
|
||||
|
||||
public static byte bit(int i)
|
||||
{
|
||||
return (byte) (1 << (7 - i));
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.Sides;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.entity.models.EntityModel;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
@@ -78,6 +79,12 @@ public final class Entity implements IonBinary {
|
||||
{
|
||||
return model.getPathCost(Entity.this, from, to);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Coord[] getWalkSides() {
|
||||
return Sides.cardinalSides;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class PlayerModel extends EntityModel {
|
||||
|
||||
private void exploreSurroundings(Entity entity)
|
||||
{
|
||||
entity.getLevel().markExplored(entity.getCoord(), 4.5);
|
||||
entity.getLevel().explore(entity.getCoord());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
import mightypork.rogue.world.pathfinding.PathFindingContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.rogue.world.tile.TileType;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.util.logging.Log;
|
||||
import mightypork.util.math.Calc;
|
||||
@@ -78,6 +77,11 @@ public class ScratchMap {
|
||||
return PathFinder.CORNER_HEURISTIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Coord[] getWalkSides() {
|
||||
return Sides.cardinalSides;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Coord genMin;
|
||||
|
||||
@@ -9,17 +9,20 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.Sides;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.pathfinding.FillContext;
|
||||
import mightypork.rogue.world.pathfinding.FloodFill;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.rogue.world.tile.TileType;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.util.files.ion.IonBinary;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
import mightypork.util.logging.Log;
|
||||
import mightypork.util.math.Calc;
|
||||
import mightypork.util.math.noise.NoiseGen;
|
||||
|
||||
|
||||
@@ -319,20 +322,40 @@ public class Level implements MapAccess, IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public void markExplored(Coord coord, double radius)
|
||||
public void explore(Coord center)
|
||||
{
|
||||
final int cr = (int) Math.ceil(radius);
|
||||
|
||||
final Coord c = Coord.zero();
|
||||
for (c.y = coord.y - cr; c.y <= coord.y + cr; c.y++) {
|
||||
for (c.x = coord.x - cr; c.x <= coord.x + cr; c.x++) {
|
||||
if (Calc.dist(coord.x, coord.y, c.x, c.y) > radius) continue;
|
||||
final Tile t = getTile(c);
|
||||
if (!t.isNull()) {
|
||||
t.setExplored();
|
||||
}
|
||||
}
|
||||
Collection<Coord> filled = FloodFill.fill(center, exploreFc);
|
||||
for(Coord c : filled) getTile(c).setExplored();
|
||||
}
|
||||
|
||||
private FillContext exploreFc = new FillContext() {
|
||||
|
||||
@Override
|
||||
public Coord[] getSpreadSides()
|
||||
{
|
||||
return Sides.allSides;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getMaxDistance()
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canSpreadFrom(Coord pos)
|
||||
{
|
||||
Tile t = getTile(pos);
|
||||
return t.isWalkable() && t.getType() != TileType.DOOR;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canEnter(Coord pos)
|
||||
{
|
||||
return !getTile(pos).isNull();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,13 +9,14 @@ public interface FillContext {
|
||||
boolean canEnter(Coord pos);
|
||||
|
||||
|
||||
boolean canSpread(Coord pos);
|
||||
boolean canSpreadFrom(Coord pos);
|
||||
|
||||
Coord[] getSpreadSides();
|
||||
|
||||
/**
|
||||
* Get the max distance filled form start point. Use -1 for unlimited range.
|
||||
*
|
||||
* @return max distance
|
||||
*/
|
||||
int getMaxDistance();
|
||||
double getMaxDistance();
|
||||
}
|
||||
|
||||
@@ -1,37 +1,47 @@
|
||||
package mightypork.rogue.world.pathfinding;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
|
||||
|
||||
public class FloodFill {
|
||||
|
||||
private static final Coord[] spread = { Coord.make(0, -1), Coord.make(0, 1), Coord.make(1, 0), Coord.make(-1, 0) };
|
||||
|
||||
|
||||
public static final Collection<Coord> fill(Coord start, FillContext context)
|
||||
{
|
||||
Set<Coord> filled = new HashSet<>();
|
||||
Stack<Coord> active = new Stack<>();
|
||||
|
||||
int maxDist = context.getMaxDistance();
|
||||
double maxDist = context.getMaxDistance();
|
||||
|
||||
active.push(start);
|
||||
|
||||
Coord[] sides = context.getSpreadSides();
|
||||
boolean first = true;
|
||||
|
||||
while (!active.isEmpty()) {
|
||||
Coord current = active.pop();
|
||||
|
||||
filled.add(current);
|
||||
|
||||
for (Coord spr : spread) {
|
||||
if(!context.canSpreadFrom(current) && !first) continue;
|
||||
|
||||
first = false;
|
||||
|
||||
|
||||
for (Coord spr : sides) {
|
||||
Coord next = current.add(spr);
|
||||
if(active.contains(next) || filled.contains(next)) continue;
|
||||
|
||||
if (next.dist(start) > maxDist) continue;
|
||||
|
||||
if (context.canSpread(next)) {
|
||||
if (context.canEnter(next)) {
|
||||
active.push(next);
|
||||
} else {
|
||||
filled.add(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,14 +58,7 @@ public class PathFinder {
|
||||
open.add(n);
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
final Coord[] walkDirs = {
|
||||
Coord.make(0, -1),
|
||||
Coord.make(0, 1),
|
||||
Coord.make(-1, 0),
|
||||
Coord.make(1, 0)
|
||||
};
|
||||
//@formatter:on
|
||||
final Coord[] walkDirs = context.getWalkSides();
|
||||
|
||||
Node current = null;
|
||||
|
||||
|
||||
@@ -33,4 +33,7 @@ public interface PathFindingContext {
|
||||
* @return used heuristic
|
||||
*/
|
||||
Heuristic getHeuristic();
|
||||
|
||||
|
||||
Coord[] getWalkSides();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package mightypork.rogue.world.tile;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user