Package squidpony.squidgrid
Class FOV
java.lang.Object
squidpony.squidgrid.FOV
- All Implemented Interfaces:
Serializable
public class FOV extends Object implements Serializable
This class provides methods for calculating Field of View in grids. Field of
View (FOV) algorithms determine how much area surrounding a point can be
seen. They return a 2D array of doubles, representing the amount of view
(typically sight, but perhaps sound, smell, etc.) which the origin has of
each cell. In the returned 2D array, 1.0 is always "fully seen," while 0.0
is always "unseen." Values in between are much more common, and they enable
this class to be used for lighting effects.
The input resistanceMap is considered the percent of opacity. This resistance is on top of the resistance applied from the light spreading out. You can obtain a resistance map easily with the
The returned light map is considered the percent of light in the cells.
All implementations for FOV here (that is, Ripple FOV and Shadow FOV) provide percentage levels for partially-lit or partially-seen cells. This leads to a straightforward implementation of soft lighting using an FOV result -- just mix the background or floor color of a cell, however you represent it, with a very light color (like pastel yellow), with the percentage of the light color to mix in equal to the percent of light in the FOV map.
All solvers perform bounds checking so solid borders in the map are not required.
For calculating FOV maps, this class provides both instance methods, which attempt to reuse the same 2D array for light stored in the object, and static methods, which take a light 2D array as an argument and edit it in-place. In older versions of SquidLib, constantly allocating and returning 2D double arrays on each call dragged performance down, but both of the new methods should perform well.
Static methods are provided to add together FOV maps in the simple way (disregarding visibility of distant FOV from a given cell), or the more practical way for roguelikes (where a cell needs to be within line-of-sight in the first place for a distant light to illuminate it). The second method relies on an LOS map, which is essentially the same as a very-high-radius FOV map and can be easily obtained with calculateLOSMap().
If you want to iterate through cells that are visible in a double[][] returned by FOV, you can pass that double[][] to the constructor for GreasedRegion, and you can use the GreasedRegion as a reliably-ordered Collection of Coord (among other things). The order GreasedRegion iterates in is somewhat strange, and doesn't, for example, start at the center of an FOV map, but it will be the same every time you create a GreasedRegion with the same FOV map (or the same visible Coords).
This class is not thread-safe. This is generally true for most of SquidLib.
The input resistanceMap is considered the percent of opacity. This resistance is on top of the resistance applied from the light spreading out. You can obtain a resistance map easily with the
generateResistances(char[][])
method, which uses defaults for common chars used in SquidLib, but you may
also want to create a resistance map manually if a given char means something
very different in your game. This is easy enough to do by looping over all the
x,y positions in your char[][] map and running a switch statement on each char,
assigning a double to the same x,y position in a double[][]. The value should
be between 0.0 (unblocked) for things light passes through, 1.0 (blocked) for
things light can't pass at all, and possibly other values if you have
translucent obstacles. There's generateSimpleResistances(char[][])
as
well, which only returns 1.0 (fully blocked) or 0.0 (passable), and 3x3 subcell
variants, which produce a resistance map that is 3 times wider and 3 times
taller than the input map. The subcell variants have especially useful behavior
when using DungeonUtility.hashesToLines(char[][])
to draw a map with
box-drawing characters, since these 3x3 resistance maps will line up blocking
cells to where a box-drawing line is.
The returned light map is considered the percent of light in the cells.
All implementations for FOV here (that is, Ripple FOV and Shadow FOV) provide percentage levels for partially-lit or partially-seen cells. This leads to a straightforward implementation of soft lighting using an FOV result -- just mix the background or floor color of a cell, however you represent it, with a very light color (like pastel yellow), with the percentage of the light color to mix in equal to the percent of light in the FOV map.
All solvers perform bounds checking so solid borders in the map are not required.
For calculating FOV maps, this class provides both instance methods, which attempt to reuse the same 2D array for light stored in the object, and static methods, which take a light 2D array as an argument and edit it in-place. In older versions of SquidLib, constantly allocating and returning 2D double arrays on each call dragged performance down, but both of the new methods should perform well.
Static methods are provided to add together FOV maps in the simple way (disregarding visibility of distant FOV from a given cell), or the more practical way for roguelikes (where a cell needs to be within line-of-sight in the first place for a distant light to illuminate it). The second method relies on an LOS map, which is essentially the same as a very-high-radius FOV map and can be easily obtained with calculateLOSMap().
If you want to iterate through cells that are visible in a double[][] returned by FOV, you can pass that double[][] to the constructor for GreasedRegion, and you can use the GreasedRegion as a reliably-ordered Collection of Coord (among other things). The order GreasedRegion iterates in is somewhat strange, and doesn't, for example, start at the center of an FOV map, but it will be the same every time you create a GreasedRegion with the same FOV map (or the same visible Coords).
This class is not thread-safe. This is generally true for most of SquidLib.
- Author:
- Eben Howard - http://squidpony.com - howard@squidpony.com
- See Also:
- Serialized Form
-
Field Summary
Fields Modifier and Type Field Description protected static Direction[]
ccw
protected static Direction[]
ccw_full
protected double[][]
light
Data allocated in the previous calls to the public API, if any.protected GreasedRegion
nearLight
Data allocated in the previous calls to the public API, if any.static int
RIPPLE
Performs FOV by pushing values outwards from the source location.static int
RIPPLE_LOOSE
Performs FOV by pushing values outwards from the source location.static int
RIPPLE_TIGHT
Performs FOV by pushing values outwards from the source location.static int
RIPPLE_VERY_LOOSE
Performs FOV by pushing values outwards from the source location.static int
SHADOW
Uses Shadow Casting FOV algorithm. -
Constructor Summary
Constructors Constructor Description FOV()
Creates a solver which will use the default SHADOW solver.FOV(int type)
Creates a solver which will use the provided FOV solver type, typically one ofSHADOW
(the default),RIPPLE
,RIPPLE_TIGHT
,RIPPLE_LOOSE
, orRIPPLE_VERY_LOOSE
. -
Method Summary
Modifier and Type Method Description static double[][]
addFOVs(double[][]... maps)
Adds multiple FOV maps together in the simplest way possible; does not check line-of-sight between FOV maps.static double[][]
addFOVs(Iterable<double[][]> maps)
Adds multiple FOV maps together in the simplest way possible; does not check line-of-sight between FOV maps.static double[][]
addFOVsInto(double[][] basis, double[][] addend)
Adds an FOV map to another in the simplest way possible; does not check line-of-sight between FOV maps.static double[][]
addFOVsInto(double[][] basis, double[][]... maps)
Adds multiple FOV maps to basis cell-by-cell, modifying basis; does not check line-of-sight between FOV maps.static double[][]
bouncingLine(double[][] resistanceMap, double[][] light, int startX, int startY, double distance, double angle)
Reuses the existing light 2D array and fills it with a straight-line bouncing path of light that reflects its way through the given resistanceMap from startX, startY until it uses up the given distance.static double[][]
calculateFOV(double[][] resistanceMap, double[][] light, int startx, int starty)
Calculates the Field Of View for the provided map from the given x, y coordinates.double[][]
calculateFOV(double[][] resistanceMap, int startx, int starty)
Calculates the Field Of View for the provided map from the given x, y coordinates.double[][]
calculateFOV(double[][] resistanceMap, int startx, int starty, double radius)
Calculates the Field Of View for the provided map from the given x, y coordinates.double[][]
calculateFOV(double[][] resistanceMap, int startX, int startY, double radius, Radius radiusTechnique)
Calculates the Field Of View for the provided map from the given x, y coordinates.double[][]
calculateFOV(double[][] resistanceMap, int startX, int startY, double radius, Radius radiusTechnique, double angle, double span)
Calculates the Field Of View for the provided map from the given x, y coordinates.double[][]
calculateLOSMap(double[][] resistanceMap, int startX, int startY)
Calculates what cells are visible from (startX,startY) using the given resistanceMap; this can be given to mixVisibleFOVs() to limit extra light sources to those visible from the starting point.static double[][]
generateResistances(char[][] map)
Given a char[][] for the map, produces a double[][] that can be used with most of the methods in FOV, likereuseFOV(double[][], double[][], int, int, double)
.static double[][]
generateResistances3x3(char[][] map)
Given a char[][] for the map that should use box drawing characters (as produced byDungeonUtility.hashesToLines(char[][], boolean)
), produces a double[][] with triple width and triple height that can be used with FOV methods likereuseFOV(double[][], double[][], int, int, double)
in classes that use subcell lighting.static double[][]
generateSimpleResistances(char[][] map)
Given a char[][] for the map, produces a double[][] that can be used with any FOV methods that expect a resistance map (likereuseFOV(double[][], double[][], int, int, double)
), but does not treat any cells as partly transparent, only fully-blocking or fully-permitting light.static double[][]
generateSimpleResistances3x3(char[][] map)
Given a char[][] for the map that should use box drawing characters (as produced byDungeonUtility.hashesToLines(char[][], boolean)
), produces a double[][] with triple width and triple height that can be used with FOV's methods that expect a resistance map (likereuseFOV(double[][], double[][], int, int, double)
) in classes that use subcell lighting.static double[][]
mixVisibleFOVs(double[][] losMap, double[][]... maps)
Adds together multiple FOV maps, but only adds to a position if it is visible in the given LOS map.static double[][]
mixVisibleFOVs(double[][] losMap, Iterable<double[][]> maps)
Adds together multiple FOV maps, but only adds to a position if it is visible in the given LOS map.static double[][]
mixVisibleFOVsInto(double[][] losMap, double[][] basis, double[][]... maps)
Adds together multiple FOV maps, but only adds to a position if it is visible in the given LOS map.static double[][]
reuseFOV(double[][] resistanceMap, double[][] light, int startx, int starty)
Calculates the Field Of View for the provided map from the given x, y coordinates.static double[][]
reuseFOV(double[][] resistanceMap, double[][] light, int startx, int starty, double radius)
Calculates the Field Of View for the provided map from the given x, y coordinates.static double[][]
reuseFOV(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique)
Calculates the Field Of View for the provided map from the given x, y coordinates.static double[][]
reuseFOV(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique, double angle, double span)
Calculates the Field Of View for the provided map from the given x, y coordinates, lighting at the given angle in degrees and covering a span centered on that angle, also in degrees.static double[][]
reuseFOV(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique, double angle, double forward, double sideForward, double side, double sideBack, double back)
Calculates the Field Of View for the provided map from the given x, y coordinates, lighting with the view "pointed at" the givenangle
in degrees, extending to different ranges based on the direction the light is traveling.static double[][]
reuseFOVSymmetrical(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique)
Calculates the Field Of View for the provided map from the given x, y coordinates.static double[][]
reuseLOS(double[][] resistanceMap, double[][] light, int startX, int startY)
Calculates which cells have line of sight from the given x, y coordinates.static double[][]
reuseLOS(double[][] resistanceMap, double[][] light, int startX, int startY, int minX, int minY, int maxX, int maxY)
Calculates which cells have line of sight from the given x, y coordinates.static double[][]
reuseRippleFOV(double[][] resistanceMap, double[][] light, int rippleLooseness, int x, int y, double radius, Radius radiusTechnique)
Like thereuseFOV(double[][], double[][], int, int, double, Radius)
method, but this uses Ripple FOV with a configurable tightness/looseness (between 1, tightest, and 6, loosest).static double[][]
reuseRippleFOV(double[][] resistanceMap, double[][] light, int rippleLooseness, int x, int y, double radius, Radius radiusTechnique, double angle, double span)
Like thereuseFOV(double[][], double[][], int, int, double, Radius, double, double)
method, but this uses Ripple FOV with a configurable tightness/looseness (between 1, tightest, and 6, loosest).
-
Field Details
-
RIPPLE
Performs FOV by pushing values outwards from the source location. It will go around corners a bit. This corresponds to arippleLooseness
of 2 inreuseRippleFOV(double[][], double[][], int, int, int, double, Radius)
.- See Also:
- Constant Field Values
-
RIPPLE_LOOSE
Performs FOV by pushing values outwards from the source location. It will spread around edges like smoke or water, but maintain a tendency to curl towards the start position when going around edges. This corresponds to arippleLooseness
of 3 inreuseRippleFOV(double[][], double[][], int, int, int, double, Radius)
.- See Also:
- Constant Field Values
-
RIPPLE_TIGHT
Performs FOV by pushing values outwards from the source location. It will only go around corners slightly. This corresponds to arippleLooseness
of 1 inreuseRippleFOV(double[][], double[][], int, int, int, double, Radius)
.- See Also:
- Constant Field Values
-
RIPPLE_VERY_LOOSE
Performs FOV by pushing values outwards from the source location. It will go around corners massively. This corresponds to arippleLooseness
of 6 inreuseRippleFOV(double[][], double[][], int, int, int, double, Radius)
.- See Also:
- Constant Field Values
-
SHADOW
Uses Shadow Casting FOV algorithm. Returns a percentage from 1.0 (center of FOV) to 0.0 (outside of FOV).- See Also:
- Constant Field Values
-
light
Data allocated in the previous calls to the public API, if any. Used to save allocations when multiple calls are done on the same instance. -
nearLight
Data allocated in the previous calls to the public API, if any. Used to save allocations when multiple calls are done on the same instance. -
ccw
-
ccw_full
-
-
Constructor Details
-
FOV
public FOV()Creates a solver which will use the default SHADOW solver. -
FOV
Creates a solver which will use the provided FOV solver type, typically one ofSHADOW
(the default),RIPPLE
,RIPPLE_TIGHT
,RIPPLE_LOOSE
, orRIPPLE_VERY_LOOSE
.- Parameters:
type
-
-
-
Method Details
-
calculateFOV
Calculates the Field Of View for the provided map from the given x, y coordinates. Returns a light map where the values represent a percentage of fully lit. The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations based on Euclidean calculations. The light will be treated as having infinite possible radius.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
startx
- the horizontal component of the starting locationstarty
- the vertical component of the starting location- Returns:
- the computed light grid
-
calculateFOV
Calculates the Field Of View for the provided map from the given x, y coordinates. Returns a light map where the values represent a percentage of fully lit. The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations based on Euclidean calculations.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
startx
- the horizontal component of the starting locationstarty
- the vertical component of the starting locationradius
- the distance the light will extend to- Returns:
- the computed light grid
-
calculateFOV
public double[][] calculateFOV(double[][] resistanceMap, int startX, int startY, double radius, Radius radiusTechnique)Calculates the Field Of View for the provided map from the given x, y coordinates. Returns a light map where the values represent a percentage of fully lit. The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are determined by the provided RadiusStrategy.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting locationradius
- the distance the light will extend toradiusTechnique
- provides a means to calculate the radius as desired- Returns:
- the computed light grid
-
calculateFOV
public double[][] calculateFOV(double[][] resistanceMap, int startX, int startY, double radius, Radius radiusTechnique, double angle, double span)Calculates the Field Of View for the provided map from the given x, y coordinates. Returns a light map where the values represent a percentage of fully lit. The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are determined by the provided RadiusStrategy. A conical section of FOV is lit by this method if span is greater than 0.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting locationradius
- the distance the light will extend toradiusTechnique
- provides a means to calculate the radius as desiredangle
- the angle in degrees that will be the center of the FOV cone, 0 points rightspan
- the angle in degrees that measures the full arc contained in the FOV cone- Returns:
- the computed light grid
-
calculateFOV
public static double[][] calculateFOV(double[][] resistanceMap, double[][] light, int startx, int starty)Calculates the Field Of View for the provided map from the given x, y coordinates. Assigns to, and returns, a light map where the values represent a percentage of fully lit. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are always cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations based on Euclidean calculations. The light will be treated as having infinite possible radius.
This static method is equivalent to the static methodreuseFOV(double[][], double[][], int, int)
, but all of the overloads are called reuseFOV(), so this method name is discouraged for new code. Both delegate toreuseFOV(double[][], double[][], int, int, double, Radius)
anyway.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- a non-null 2D double array that will have its contents overwritten, modified, and returnedstartx
- the horizontal component of the starting locationstarty
- the vertical component of the starting location- Returns:
- the computed light grid (the same as
light
)
-
reuseFOV
public static double[][] reuseFOV(double[][] resistanceMap, double[][] light, int startx, int starty)Calculates the Field Of View for the provided map from the given x, y coordinates. Assigns to, and returns, a light map where the values represent a percentage of fully lit. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are always cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations based on Euclidean calculations. The light will be treated as having infinite possible radius.
This static method is equivalent to the static methodcalculateFOV(double[][], double[][], int, int)
, but all of the overloads are called reuseFOV(), so this method name is preferred in new code. Both delegate toreuseFOV(double[][], double[][], int, int, double, Radius)
anyway.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- a non-null 2D double array that will have its contents overwritten, modified, and returnedstartx
- the horizontal component of the starting locationstarty
- the vertical component of the starting location- Returns:
- the computed light grid (the same as
light
)
-
reuseFOV
public static double[][] reuseFOV(double[][] resistanceMap, double[][] light, int startx, int starty, double radius)Calculates the Field Of View for the provided map from the given x, y coordinates. Assigns to, and returns, a light map where the values represent a percentage of fully lit. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are always cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations based on Euclidean calculations.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
startx
- the horizontal component of the starting locationstarty
- the vertical component of the starting locationradius
- the distance the light will extend to- Returns:
- the computed light grid
-
reuseFOV
public static double[][] reuseFOV(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique)Calculates the Field Of View for the provided map from the given x, y coordinates. Assigns to, and returns, a light map where the values represent a percentage of fully lit. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are always cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are determined by the provided RadiusStrategy.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- the grid of cells to assign to; may have existing values, and 0.0 is used to mean "unlit"startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting locationradius
- the distance the light will extend toradiusTechnique
- provides a means to calculate the radius as desired- Returns:
- the computed light grid, which is the same 2D array as the value assigned to
light
-
reuseFOVSymmetrical
public static double[][] reuseFOVSymmetrical(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique)Calculates the Field Of View for the provided map from the given x, y coordinates. Assigns to, and returns, a light map where the values represent a percentage of fully lit. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are always cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are determined by the provided RadiusStrategy.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- the grid of cells to assign to; may have existing values, and 0.0 is used to mean "unlit"startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting locationradius
- the distance the light will extend toradiusTechnique
- provides a means to calculate the radius as desired- Returns:
- the computed light grid, which is the same 2D array as the value assigned to
light
-
reuseLOS
public static double[][] reuseLOS(double[][] resistanceMap, double[][] light, int startX, int startY)Calculates which cells have line of sight from the given x, y coordinates. Assigns to, and returns, a light map where the values are always either 0.0 for "not in line of sight" or 1.0 for "in line of sight," which doesn't mean a cell is actually visible if there's no light in that cell. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are always cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are pretty much irrelevant because the distance doesn't matter, only the presence of a clear line, but this usesRadius.SQUARE
if it matters.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- the grid of cells to assign to; may have existing values, and 0.0 is used to mean "no line"startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting location- Returns:
- the computed light grid, which is the same 2D array as the value assigned to
light
-
reuseLOS
public static double[][] reuseLOS(double[][] resistanceMap, double[][] light, int startX, int startY, int minX, int minY, int maxX, int maxY)Calculates which cells have line of sight from the given x, y coordinates. Assigns to, and returns, a light map where the values are always either 0.0 for "not in line of sight" or 1.0 for "in line of sight," which doesn't mean a cell is actually visible if there's no light in that cell. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are always cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are pretty much irrelevant because the distance doesn't matter, only the presence of a clear line, but this usesRadius.SQUARE
if it matters.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- the grid of cells to assign to; may have existing values, and 0.0 is used to mean "no line"startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting location- Returns:
- the computed light grid, which is the same 2D array as the value assigned to
light
-
reuseFOV
public static double[][] reuseFOV(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique, double angle, double span)Calculates the Field Of View for the provided map from the given x, y coordinates, lighting at the given angle in degrees and covering a span centered on that angle, also in degrees. Assigns to, and returns, a light map where the values represent a percentage of fully lit. Always uses shadowcasting FOV, which allows this method to be static since it doesn't need to keep any state around, and can reuse the state the user gives it via thelight
parameter. The values in light are cleared before this is run, because prior state can make this give incorrect results.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are determined by the provided RadiusStrategy. A conical section of FOV is lit by this method if span is greater than 0.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- the grid of cells to assign to; may have existing values, and 0.0 is used to mean "unlit"startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting locationradius
- the distance the light will extend toradiusTechnique
- provides a means to shape the FOV by changing distance calculation (circle, square, etc.)angle
- the angle in degrees that will be the center of the FOV cone, 0 points rightspan
- the angle in degrees that measures the full arc contained in the FOV cone- Returns:
- the computed light grid
-
reuseRippleFOV
public static double[][] reuseRippleFOV(double[][] resistanceMap, double[][] light, int rippleLooseness, int x, int y, double radius, Radius radiusTechnique)Like thereuseFOV(double[][], double[][], int, int, double, Radius)
method, but this uses Ripple FOV with a configurable tightness/looseness (between 1, tightest, and 6, loosest). Other parameters are similar; you can get a resistance map fromgenerateResistances(char[][])
,light
will be modified and returned (it will be overwritten, but its size should be the same as the resistance map), there's a starting x,y position, a radius in cells, and aRadius
enum constant to choose the distance measurement.- Parameters:
resistanceMap
- probably calculated withgenerateResistances(char[][])
; 1.0 blocks light, 0.0 allows itlight
- will be overwritten! Should be initialized with the same size asresistanceMap
rippleLooseness
- affects spread; between 1 and 6, inclusive; 1 is tightest, 2 is normal, and 6 is loosestx
- starting x position to look fromy
- starting y position to look fromradius
- the distance to extend from the starting x,y positionradiusTechnique
- how to measure distance; typicallyRadius.CIRCLE
.- Returns:
light
, after writing the FOV map into it; 1.0 is fully lit and 0.0 is unseen
-
reuseRippleFOV
public static double[][] reuseRippleFOV(double[][] resistanceMap, double[][] light, int rippleLooseness, int x, int y, double radius, Radius radiusTechnique, double angle, double span)Like thereuseFOV(double[][], double[][], int, int, double, Radius, double, double)
method, but this uses Ripple FOV with a configurable tightness/looseness (between 1, tightest, and 6, loosest). Other parameters are similar; you can get a resistance map fromgenerateResistances(char[][])
,light
will be modified and returned (it will be overwritten, but its size should be the same as the resistance map), there's starting x,y position, a radius in cells, aRadius
enum constant to choose the distance measurement, and the angle/span combination to specify a conical section of FOV (span is the total in degrees, centered on angle).- Parameters:
resistanceMap
- probably calculated withgenerateResistances(char[][])
; 1.0 blocks light, 0.0 allows itlight
- will be overwritten! Should be initialized with the same size asresistanceMap
rippleLooseness
- affects spread; between 1 and 6, inclusive; 1 is tightest, 2 is normal, and 6 is loosestx
- starting x position to look fromy
- starting y position to look fromradius
- the distance to extend from the starting x,y positionradiusTechnique
- how to measure distance; typicallyRadius.CIRCLE
.angle
- the angle to center the conical FOV onspan
- the total span in degrees for the conical FOV to cover- Returns:
light
, after writing the FOV map into it; 1.0 is fully lit and 0.0 is unseen
-
bouncingLine
public static double[][] bouncingLine(double[][] resistanceMap, double[][] light, int startX, int startY, double distance, double angle)Reuses the existing light 2D array and fills it with a straight-line bouncing path of light that reflects its way through the given resistanceMap from startX, startY until it uses up the given distance. The angle the path takes is given in degrees, and the angle used can change as obstacles are hit (reflecting backwards if it hits a corner pointing directly into or away from its path). This can be used something like an LOS method, but because the path can be traveled back over, an array or Queue becomes somewhat more complex, and the decreasing numbers for a straight line that stack may make more sense for how this could be used (especially with visual effects). This currently allows the path to pass through single-cell wall-like obstacles without changing direction, e.g. it passes through pillars, but will bounce if it hits a bigger wall.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- the grid of cells to assign to; may have existing values, and 0.0 is used to mean "unlit"startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting locationdistance
- the distance the light will extend toangle
- in degrees, the angle to start the path traveling in- Returns:
- the given light parameter, after modifications
-
reuseFOV
public static double[][] reuseFOV(double[][] resistanceMap, double[][] light, int startX, int startY, double radius, Radius radiusTechnique, double angle, double forward, double sideForward, double side, double sideBack, double back)Calculates the Field Of View for the provided map from the given x, y coordinates, lighting with the view "pointed at" the givenangle
in degrees, extending to different ranges based on the direction the light is traveling. The direction ranges areforward
,sideForward
,side
,sideBack
, andback
; all are multiplied byradius
. Assigns to, and returns, a light map where the values represent a percentage of fully lit. The values in light are cleared before this is run, because prior state can make this give incorrect results. You can useaddFOVsInto(double[][], double[][]...)
if you want to mix FOV results, which works as an alternative to using the prior light state.
The starting point for the calculation is considered to be at the center of the origin cell. Radius determinations are determined by the provided RadiusStrategy. If all direction ranges are the same, this acts likereuseFOV(double[][], double[][], int, int, double, Radius)
; otherwise may produce conical shapes (potentially more than one, or overlapping ones).- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
light
- the grid of cells to assign to; may have existing values, and 0.0 is used to mean "unlit"startX
- the horizontal component of the starting locationstartY
- the vertical component of the starting locationradius
- the distance the light will extend to (roughly); direction ranges will be multiplied by thisradiusTechnique
- provides a means to shape the FOV by changing distance calculation (circle, square, etc.)angle
- the angle in degrees that will be the center of the FOV cone, 0 points rightforward
- the range to extend when the light is within 22.5 degrees of angle; will be interpolated with sideForwardsideForward
- the range to extend when the light is between 22.5 and 67.5 degrees of angle; will be interpolated with forward or sideside
- the range to extend when the light is between 67.5 and 112.5 degrees of angle; will be interpolated with sideForward or sideBacksideBack
- the range to extend when the light is between 112.5 and 157.5 degrees of angle; will be interpolated with side or backback
- the range to extend when the light is more than 157.5 degrees away from angle; will be interpolated with sideBack- Returns:
- the computed light grid (the same as
light
)
-
addFOVsInto
Adds an FOV map to another in the simplest way possible; does not check line-of-sight between FOV maps. Clamps the highest value for any single position at 1.0. Modifies the basis parameter in-place and makes no allocations; this is different fromaddFOVs(double[][][])
, which creates a new 2D array.- Parameters:
basis
- a 2D double array, which can be empty or returned by calculateFOV() or reuseFOV(); modified!addend
- another 2D double array that will be added into basis; this one will not be modified- Returns:
- the sum of the 2D double arrays passed, using the dimensions of basis if they don't match
-
addFOVs
Adds multiple FOV maps together in the simplest way possible; does not check line-of-sight between FOV maps. Clamps the highest value for any single position at 1.0. Allocates a new 2D double array and returns it.- Parameters:
maps
- an array or vararg of 2D double arrays, each usually returned by calculateFOV()- Returns:
- the sum of all the 2D double arrays passed, using the dimensions of the first if they don't all match
-
addFOVsInto
Adds multiple FOV maps to basis cell-by-cell, modifying basis; does not check line-of-sight between FOV maps. Clamps the highest value for any single position at 1.0. Returns basis without allocating new objects.- Parameters:
basis
- a 2D double array that will be modified by adding values in maps to it and clamping to 1.0 or lessmaps
- an array or vararg of 2D double arrays, each usually returned by calculateFOV()- Returns:
- basis, with all elements in all of maps added to the corresponding cells and clamped
-
addFOVs
Adds multiple FOV maps together in the simplest way possible; does not check line-of-sight between FOV maps. Clamps the highest value for any single position at 1.0. Allocates a new 2D double array and returns it.- Parameters:
maps
- an Iterable of 2D double arrays (most collections implement Iterable), each usually returned by calculateFOV()- Returns:
- the sum of all the 2D double arrays passed, using the dimensions of the first if they don't all match
-
mixVisibleFOVs
Adds together multiple FOV maps, but only adds to a position if it is visible in the given LOS map. Useful if you want distant lighting to be visible only if the player has line-of-sight to a lit cell. Typically the LOS map is calculated byreuseLOS(double[][], double[][], int, int)
, using the same resistance map used to calculate the FOV maps. Clamps the highest value for any single position at 1.0.- Parameters:
losMap
- an LOS map such as one generated byreuseLOS(double[][], double[][], int, int)
maps
- an array or vararg of 2D double arrays, each usually returned by calculateFOV()- Returns:
- the sum of all the 2D double arrays in maps where a cell was visible in losMap
-
mixVisibleFOVsInto
public static double[][] mixVisibleFOVsInto(double[][] losMap, double[][] basis, double[][]... maps)Adds together multiple FOV maps, but only adds to a position if it is visible in the given LOS map. Useful if you want distant lighting to be visible only if the player has line-of-sight to a lit cell. Typically the LOS map is calculated byreuseLOS(double[][], double[][], int, int)
, using the same resistance map used to calculate the FOV maps. Clamps the highest value for any single position at 1.0.- Parameters:
losMap
- an LOS map such as one generated byreuseLOS(double[][], double[][], int, int)
basis
- an existing 2D double array that should have matching width and height to losMap; will be modifiedmaps
- an array or vararg of 2D double arrays, each usually returned by calculateFOV()- Returns:
- the sum of all the 2D double arrays in maps where a cell was visible in losMap
-
mixVisibleFOVs
Adds together multiple FOV maps, but only adds to a position if it is visible in the given LOS map. Useful if you want distant lighting to be visible only if the player has line-of-sight to a lit cell. Typically the LOS map is calculated byreuseLOS(double[][], double[][], int, int)
, using the same resistance map used to calculate the FOV maps. Clamps the highest value for any single position at 1.0.- Parameters:
losMap
- an LOS map such as one generated byreuseLOS(double[][], double[][], int, int)
maps
- an Iterable of 2D double arrays, each usually returned by calculateFOV()- Returns:
- the sum of all the 2D double arrays in maps where a cell was visible in losMap
-
calculateLOSMap
Calculates what cells are visible from (startX,startY) using the given resistanceMap; this can be given to mixVisibleFOVs() to limit extra light sources to those visible from the starting point. Just like calling calculateFOV(), this creates a new double[][]; there doesn't appear to be a way to work with Ripple FOV and avoid needing an empty double[][] every time, since it uses previously-placed light to determine how it should spread.- Parameters:
resistanceMap
- the grid of cells to calculate on; the kind made bygenerateResistances(char[][])
startX
- the center of the LOS map; typically the player's x-positionstartY
- the center of the LOS map; typically the player's y-position- Returns:
- an LOS map with the given starting point
-
generateResistances
Given a char[][] for the map, produces a double[][] that can be used with most of the methods in FOV, likereuseFOV(double[][], double[][], int, int, double)
. It expects any doors to be represented by '+' if closed or '/' if open (which can be caused by callingDungeonUtility.closeDoors(char[][])
), any walls to be '#' or box drawing characters, and it doesn't care what other chars are used (only doors, including open ones, and walls obscure light and thus have a resistance by default).- Parameters:
map
- a dungeon, width by height, with any closed doors as '+' and open doors as '/' as per closeDoors()- Returns:
- a resistance map suitable for use with the FOV class, with clear cells assigned 0.0 and blocked ones 1.0
-
generateResistances3x3
Given a char[][] for the map that should use box drawing characters (as produced byDungeonUtility.hashesToLines(char[][], boolean)
), produces a double[][] with triple width and triple height that can be used with FOV methods likereuseFOV(double[][], double[][], int, int, double)
in classes that use subcell lighting. Importantly, this only considers a "thin line" of wall to be blocking (matching the box drawing character), instead of the whole 3x3 area. This expects any doors to be represented by '+' if closed or '/' if open (which can be caused by callingDungeonUtility.closeDoors(char[][])
), thick vegetation or other concealing obstructions to be '"', any normal walls to be box drawing characters, any cells that block all subcells to be '#', and it doesn't care what other chars are used (only doors, including open ones, vegetation, and walls obscure light and thus have a resistance normally).- Parameters:
map
- a dungeon, width by height, with any closed doors as '+' and open doors as '/' as per closeDoors()- Returns:
- a resistance map suitable for use with the FOV class and subcell lighting, with triple width/height
-
generateSimpleResistances
Given a char[][] for the map, produces a double[][] that can be used with any FOV methods that expect a resistance map (likereuseFOV(double[][], double[][], int, int, double)
), but does not treat any cells as partly transparent, only fully-blocking or fully-permitting light. This is mainly useful if you expect the FOV radius to be very high or (effectively) infinite, since anything less than complete blockage would be passed through by infinite-radius FOV. This expects any doors to be represented by '+' if closed or '/' if open (most door placement defaults to a mix of '+' and '/', so by callingDungeonUtility.closeDoors(char[][])
you can close all doors at the start), and any walls to be '#' or box drawing characters. This will assign 1.0 resistance to walls and closed doors or 0.0 for any other cell.- Parameters:
map
- a dungeon, width by height, with any closed doors as '+' and open doors as '/' as per closeDoors()- Returns:
- a resistance map suitable for use with the FOV class, but with no partially transparent cells
-
generateSimpleResistances3x3
Given a char[][] for the map that should use box drawing characters (as produced byDungeonUtility.hashesToLines(char[][], boolean)
), produces a double[][] with triple width and triple height that can be used with FOV's methods that expect a resistance map (likereuseFOV(double[][], double[][], int, int, double)
) in classes that use subcell lighting. This expects any doors to be represented by '+' if closed or '/' if open (most door placement defaults to a mix of '+' and '/', so by callingDungeonUtility.closeDoors(char[][])
you can close all doors at the start), any walls to be box drawing characters, and any cells that block all subcells within their area to be '#'. This will assig 1.0 resistance to walls and closed doors where a line of the box drawing char would block light, or 0.0 for an other subcell.- Parameters:
map
- a dungeon, width by height, with any closed doors as '+' and open doors as '/' as per closeDoors()- Returns:
- a resistance map suitable for use with the FOV class and subcell lighting, with triple width/height
-