/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package transientlibs.maps.utils.fov;
/**
*
* @author kibertoad
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import transientlibs.rlforj.los.IFovAlgorithm;
import transientlibs.rlforj.los.ILosBoard;
import transientlibs.rlforj.los.PrecisePermissive;
import transientlibs.rlforj.math.Point2I;
import transientlibs.maps.container.TransientAssembledMap;
import transientlibs.maps.units.Unit;
public class FOVBoard implements ILosBoard {
public TransientAssembledMap map;
int w, h;
public enum SightTracking {
PLAYER, OTHER;
}
public List<List<Boolean>> canSee;
public List<List<Boolean>> haveSeen;
public SightTracking sightTracking;
public Unit observer;
//public TransientAssembledMap map;
IFovAlgorithm fov;
boolean[][] obstacles;
//boolean[][] visited;
Map<Point2I, Character> marks = new HashMap<Point2I, Character>();
public char visibleFloor = '.', invisibleFloor = ' ', invisibleWall = ' ';
public final void setObstacles() {
for (int y = 0; y < map.getHeight(); y++) {
for (int x = 0; x < map.getWidth(); x++) {
if (map.blocksSight(x, y)) {
setObstacle(x, y);
}
}
}
}
public FOVBoard(TransientAssembledMap setMap, Unit setObserver) {
map = setMap;
w = map.storedWidthInTiles;
h = map.storedHeightInTiles;
obstacles = new boolean[w][h];
//visited = new boolean[w][h];
observer = setObserver;
this.canSee = buildBoolArray();
this.haveSeen = buildBoolArray();
fov = new PrecisePermissive();
//fov = new ConePrecisePremisive();
//fov = new ShadowCasting();
this.setObstacles();
}
/**
* Entity, for which FOV is calculated now, is player.
*/
public void trackPlayerSight() {
sightTracking = SightTracking.PLAYER;
}
/**
* Recalculate, which tiles are currently seen
*/
public void updateFov() {
clearSight();
trackPlayerSight();
fov.visitFieldOfView(this, observer.getMapCoords().getIntX(), observer.getMapCoords().getIntY(), observer.sightRange.value);
//Log.info("Coord 1:1 is visible: " + this.canSee.get(1).get(1).toString());
}
/**
* Prepare map-sized array for storing FOV flags.
*/
public final List<List<Boolean>> buildBoolArray() {
List<List<Boolean>> boolArray = new ArrayList<List<Boolean>>();
for (int y = 0; y < map.getHeight(); y++) {
boolArray.add(new ArrayList<Boolean>());
for (int x = 0; x < map.getWidth(); x++) {
boolArray.get(y).add(false);
}
}
return boolArray;
}
/**
* Reset "can see" flags on each tile.
*/
public void clearSight() {
for (int y = 0; y < map.getHeight(); y++) {
for (int x = 0; x < map.getWidth(); x++) {
canSee.get(y).set(x, false);
}
}
}
public void resetVisitedAndMarks() {
marks.clear();
clearSight();
//visited = new boolean[w][h];
}
public void mark(int x, int y, char c) {
marks.put(new Point2I(x, y), c);
}
/**
* Mark tile as non-transparent
*/
public void setObstacle(int x, int y) {
obstacles[x][y] = true;
}
@Override
public boolean contains(int x, int y) {
return x >= 0 && y >= 0 && x < w && y < h;
}
/**
* Check if tile is transparent
*/
@Override
public boolean isObstacle(int x, int y) {
return obstacles[x][y];
}
/**
* Mark tile as visible.
*/
@Override
public void visit(int x, int y) {
//visited[x][y]=true;
if (sightTracking == SightTracking.PLAYER) {
haveSeen.get(y).set(x, true);
canSee.get(y).set(x, true);
} else if (sightTracking == SightTracking.OTHER) {
//otherSightTracking.add(new Point2I(x, y));
}
//Log.info("Marked "+x+":"+y+" as visible.");
}
/**
* Debug output of what tiles are visible
*/
public void print(int ox, int oy) {
Point2I p = new Point2I(0, 0);
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
p.x = i;
p.y = j;
Character c = marks.get(p);
if (c != null) {
System.out.print(c);
} else if (i == ox && j == oy) {
System.out.print('@');
} else {
System.out.print(wasVisited(i,j) ? (obstacles[i][j] ? '#'
: visibleFloor) : (obstacles[i][j] ? invisibleWall
: invisibleFloor));
}
}
System.out.println();
}
}
public boolean wasVisited(int x, int y) {
//return visited[i][j];
if ((x >= 0) && (y >= 0) && (y < canSee.size()) && (x < canSee.get(y).size())) {
return canSee.get(y).get(x);
} else {
return false;
}
}
}