flood fill room discovery

v5stable
ondra 10 years ago
parent c5374f5f6e
commit 7f7b58733d
  1. 47
      src/mightypork/rogue/world/Sides.java
  2. 7
      src/mightypork/rogue/world/entity/Entity.java
  3. 2
      src/mightypork/rogue/world/entity/models/PlayerModel.java
  4. 6
      src/mightypork/rogue/world/gen/ScratchMap.java
  5. 49
      src/mightypork/rogue/world/level/Level.java
  6. 5
      src/mightypork/rogue/world/pathfinding/FillContext.java
  7. 30
      src/mightypork/rogue/world/pathfinding/FloodFill.java
  8. 9
      src/mightypork/rogue/world/pathfinding/PathFinder.java
  9. 3
      src/mightypork/rogue/world/pathfinding/PathFindingContext.java
  10. 1
      src/mightypork/rogue/world/tile/TileModel.java
  11. 1
      src/mightypork/util/files/ion/IonBinary.java

@ -2,26 +2,26 @@ 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 N = 0b01000000;
public static final byte NE = 0b00100000;
public static final byte E = 0b00010000;
public static final byte E = 0b00010000;
public static final byte SE = 0b00001000;
public static final byte S = 0b00000100;
public static final byte S = 0b00000100;
public static final byte SW = 0b00000010;
public static final byte W = 0b00000001;
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);
Collection<Coord> filled = FloodFill.fill(center, exploreFc);
for(Coord c : filled) getTile(c).setExplored();
}
private FillContext exploreFc = new FillContext() {
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();
}
}
@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 class FloodFill {
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);
while (!active.isEmpty()) {
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;
/**

Loading…
Cancel
Save