package Roguelike.Pathfinding; import Roguelike.Global; import Roguelike.Global.Passability; import Roguelike.Tiles.GameTile; import Roguelike.Tiles.Point; import Roguelike.Util.EnumBitflag; import com.badlogic.gdx.utils.Array; public final class ShadowCastCache { private final EnumBitflag<Passability> LightPassability; public ShadowCastCache( EnumBitflag<Passability> LightPassability ) { this.LightPassability = LightPassability; } public ShadowCastCache() { LightPassability = new EnumBitflag<Passability>( Passability.LIGHT ); } public ShadowCastCache copy() { ShadowCastCache cache = new ShadowCastCache( LightPassability ); cache.lastrange = lastrange; cache.lastx = lastx; cache.lasty = lasty; for ( Point p : opaqueTiles ) { cache.opaqueTiles.add( p.copy() ); } for ( Point p : shadowCastOutput ) { cache.shadowCastOutput.add( p.copy() ); } return cache; } private int lastrange; private int lastx; private int lasty; private Array<Point> opaqueTiles = new Array<Point>(); private Array<Point> clearTiles = new Array<Point>(); private Array<Point> shadowCastOutput = new Array<Point>(); public Array<Point> getCurrentShadowCast() { return shadowCastOutput; } public Array<Point> getShadowCast( GameTile[][] grid, int x, int y, int range, Object caster ) { return getShadowCast( grid, x, y, range, caster, false ); } public Array<Point> getShadowCast( GameTile[][] grid, int x, int y, int range, Object caster, boolean allowOutOfBounds ) { boolean recalculate = false; if ( x != lastx || y != lasty ) { recalculate = true; } else if ( range != lastrange ) { recalculate = true; } else { for ( Point pos : opaqueTiles ) { GameTile tile = grid[pos.x][pos.y]; if ( tile.getPassable( LightPassability, caster ) ) { recalculate = true; // something has moved break; } } if ( !recalculate ) { for ( Point pos : clearTiles ) { GameTile tile = grid[pos.x][pos.y]; if ( !tile.getPassable( LightPassability, caster ) ) { recalculate = true; // something has moved break; } } } } if ( recalculate ) { Global.PointPool.freeAll( shadowCastOutput ); shadowCastOutput.clear(); ShadowCaster shadow = new ShadowCaster( grid, range ); shadow.allowOutOfBounds = allowOutOfBounds; shadow.ComputeFOV( x, y, shadowCastOutput ); // build list of clear/opaque opaqueTiles.clear(); clearTiles.clear(); for ( Point pos : shadowCastOutput ) { if ( pos.x < 0 || pos.y < 0 || pos.x >= grid.length || pos.y >= grid[0].length ) { continue; } GameTile tile = grid[pos.x][pos.y]; if ( !tile.getPassable( LightPassability, caster ) ) { opaqueTiles.add( pos ); } else { clearTiles.add( pos ); } } lastx = x; lasty = y; lastrange = range; } return shadowCastOutput; } }