public static PointArray <bool> ScanToArray(Point source, Func <Point, bool> condition, SourceOption sourceOption = SourceOption.AlwaysIncludeSource) { PointArray <bool> result = new PointArray <bool>(GameUniverse.MapWidth, GameUniverse.MapHeight); foreach (Point p in Scan(source, condition, sourceOption)) { result[p] = true; } return(result); }
public DungeonMap(GameUniverse g) : base(g) { CurrentDepthSeed = MapRNG.GetNext(); Func <Point, bool> isInBounds = p => p.X >= 0 && p.X < Width && p.Y >= 0 && p.Y < Height; Creatures = new Grid <Creature, Point>(isInBounds); Tiles = new PointArray <TileType>(Width, Height); Features = new FeatureMap(Width, Height); Traps = new Dictionary <Point, Trap>(); Items = new Grid <Item, Point>(isInBounds); NeverInLineOfSight = new PointArray <bool>(Width, Height); Light = new LightMap(g); DirectionPlayerExited = new PointArray <Dir8>(Width, Height); //todo, more here? Seen = new PointArray <bool>(Width, Height); }
public static bool HasLOS(this Point source, Point destination, PointArray <TileType> map) //todo, move this, to use NeverInLOS from DungeonMap { if (TileDefinition.IsOpaque(map[destination])) { Point[] neighbors = GetNeighborsBetween(destination, source); for (int i = 0; i < neighbors.Length; ++i) { if (TileDefinition.IsOpaque(map[neighbors[i]])) { continue; } if (CheckReciprocalBresenhamLineOfSight(source, neighbors[i], map)) { return(true); } } return(false); } else { return(CheckReciprocalBresenhamLineOfSight(source, destination, map)); } }
public static bool CheckReciprocalBresenhamLineOfSight(this Point source, Point destination, PointArray <TileType> map) //todo, what to do with map? { int x1 = source.X; int y1 = source.Y; int x2 = destination.X; int y2 = destination.Y; int dx = Math.Abs(x2 - x1); int dy = Math.Abs(y2 - y1); int incrementX = x1 == x2? 0 : x1 < x2? 1 : -1; int incrementY = y1 == y2? 0 : y1 < y2? 1 : -1; if (dx <= 1 && dy <= 1) { return(true); // Automatically pass the check for anything in the same or adjacent cells. } // Next, handle simple cases that don't need Bresenham at all. These cases correspond to straight lines in the 8 directions: if (dx == 0 || dy == 0 || (y1 + x1 == y2 + x2) || (y1 - x1 == y2 - x2)) // (if slope is undefined, 0, -1, or 1) { do { x1 += incrementX; // Increment first, so that the opacity of 'source' is ignored. y1 += incrementY; if (TileDefinition.IsOpaque(map[x1, y1])) { return(false); } } while(x1 != x2 || y1 != y2); return(true); } // If it wasn't a simple case, move on to reciprocal Bresenham: bool xMajor = (dx > dy); int er = 0; // error accumulator bool blockedA = false; // These 2 are used to track whether each of the 2 possible paths per line is blocked or not. bool blockedB = false; // (The result is equivalent to calculating 2 regular Bresenham lines, source->dest and dest->source.) if (xMajor) { do { x1 += incrementX; er += dy; if (er << 1 > dx) { y1 += incrementY; er -= dx; } if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedB || er << 1 != dx) { return(false); } blockedA = true; } if (er << 1 == dx) // This is the part that makes this reciprocal, by checking both options while crossing a corner. { y1 += incrementY; // Increment Y, then check the new position: if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedA || er << 1 != dx) { return(false); } blockedB = true; } er -= dx; } } while(x1 != x2); } else // Y-major { do { y1 += incrementY; er += dx; if (er << 1 > dy) { x1 += incrementX; er -= dy; } if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedB || er << 1 != dy) { return(false); } blockedA = true; } if (er << 1 == dy) { x1 += incrementX; if (TileDefinition.IsOpaque(map[x1, y1])) { if (blockedA || er << 1 != dy) { return(false); } blockedB = true; } er -= dy; } } while(y1 != y2); } return(true); }
public LightMap(GameUniverse g) : base(g) { lightSources = new MultiValueDictionary <Point, int>(); tempRemovedLights = new MultiValueDictionary <Point, int>(); cellBrightness = new PointArray <int>(Width, Height); }