private static void PaintFOVTest(RootConsole console, int x, int y, TCODFov fov) { fov.CalculateFOV(x, y, 3, false, FovAlgorithm.Basic); for (int i = 0; i < 5; ++i) //width { for (int j = 0; j < 5; ++j) //height { if (room[j, i] == '.') { if (fov.CheckTileFOV(i, j)) { console.PutChar(i, j, '.'); } else { console.PutChar(i, j, '~'); } } else { console.PutChar(i, j, '#'); } } } console.PutChar(x, y, '@'); console.Flush(); }
private bool ArePointsConnected(Point firstPoint, Point secondPoint) { //Build tcodmap TCODFov tcodMap = new TCODFov(Width, Height); for (int i = 0; i < Width; i++) { for (int j = 0; j < Height; j++) { tcodMap.SetCell(i, j, !baseMap.mapSquares[i, j].BlocksLight, baseMap.mapSquares[i, j].Walkable); } } //Try to walk the path between the 2 staircases TCODPathFinding path = new TCODPathFinding(tcodMap, 1.0); path.ComputePath(firstPoint.x, firstPoint.y, secondPoint.x, secondPoint.y); //Find the first step. We need to load x and y with the origin of the path int x = upStaircase.x; int y = upStaircase.y; bool obstacleHit = false; //If there's no routeable path if (path.IsPathEmpty()) { obstacleHit = true; } path.Dispose(); tcodMap.Dispose(); return(!obstacleHit); }
/// <summary> /// Recalculate the players FOV. Subsequent accesses to the TCODMap of the player's level will have his FOV /// Note that the maps may get hijacked by other creatures /// </summary> internal void CalculatePlayerFOV() { //Get TCOD to calculate the player's FOV Map currentMap = levels[Player.LocationLevel]; TCODFov tcodFOV = levelTCODMaps[Player.LocationLevel]; tcodFOV.CalculateFOV(Player.LocationMap.x, Player.LocationMap.y, Player.SightRadius); //Set the FOV flags on the map //Process the whole level, which effectively resets out-of-FOV areas for (int i = 0; i < currentMap.width; i++) { for (int j = 0; j < currentMap.height; j++) { MapSquare thisSquare = currentMap.mapSquares[i, j]; thisSquare.InPlayerFOV = tcodFOV.CheckTileFOV(i, j); //Set 'has ever been seen flag' if appropriate if (thisSquare.InPlayerFOV == true) { thisSquare.SeenByPlayer = true; } } } }
/// <summary> /// Calculates the FOV for a creature /// </summary> /// <param name="creature"></param> public TCODFov CalculateCreatureFOV(Creature creature) { Map currentMap = levels[creature.LocationLevel]; TCODFov tcodFOV = levelTCODMaps[creature.LocationLevel]; //Update FOV tcodFOV.CalculateFOV(creature.LocationMap.x, creature.LocationMap.y, creature.SightRadius); return(tcodFOV); }
public void Init() { fov = new TCODFov(5, 5); for (int i = 0; i < 5; ++i) //width { for (int j = 0; j < 5; ++j) //height { fov.SetCell(i, j, room[j, i] == '.', room[j, i] == '.'); } } pathFindingFOV = new TCODPathFinding(fov, 1.0); pathFindingCallback = new TCODPathFinding(5, 5, 1.0, new TCODPathCallback(TCODPathCallback)); }
public void updateMap(int level, PathingMap terrainMap) { TCODFov tcodLevel = new TCODFov(terrainMap.Width, terrainMap.Height); for (int j = 0; j < terrainMap.Width; j++) { for (int k = 0; k < terrainMap.Height; k++) { tcodLevel.SetCell(j, k, true, terrainMap.getCell(j, k) == PathingTerrain.Walkable); } } levelTCODMaps[level] = tcodLevel; //Ignoring closed doors TCODFov tcodLevelNoClosedDoors = new TCODFov(terrainMap.Width, terrainMap.Height); for (int j = 0; j < terrainMap.Width; j++) { for (int k = 0; k < terrainMap.Height; k++) { tcodLevelNoClosedDoors.SetCell(j, k, true, terrainMap.getCell(j, k) == PathingTerrain.Walkable || terrainMap.getCell(j, k) == PathingTerrain.ClosedDoor); } } levelTCODMapsIgnoringClosedDoors[level] = tcodLevelNoClosedDoors; //Ignoring closed doors and locks TCODFov tcodLevelNoClosedDoorsAndLocks = new TCODFov(terrainMap.Width, terrainMap.Height); for (int j = 0; j < terrainMap.Width; j++) { for (int k = 0; k < terrainMap.Height; k++) { tcodLevelNoClosedDoorsAndLocks.SetCell(j, k, true, terrainMap.getCell(j, k) == PathingTerrain.Walkable || terrainMap.getCell(j, k) == PathingTerrain.ClosedDoor || terrainMap.getCell(j, k) == PathingTerrain.ClosedLock); } } levelTCODMapsIgnoringClosedDoorsAndLocks[level] = tcodLevelNoClosedDoorsAndLocks; }
public void DrawFOVDebug(int levelNo) { Map map = Game.Dungeon.Levels[levelNo]; TCODFov fov = Game.Dungeon.FOVs[levelNo]; //Get screen handle RootConsole rootConsole = RootConsole.GetInstance(); //Clear screen rootConsole.Clear(); for (int i = 0; i < map.width; i++) { for (int j = 0; j < map.height; j++) { int screenX = mapTopLeft.x + i; int screenY = mapTopLeft.y + j; bool trans; bool walkable; fov.GetCell(i, j, out trans, out walkable); Color drawColor = inFOVTerrainColor; if (walkable) { drawColor = inFOVTerrainColor; } else { drawColor = inMonsterFOVTerrainColor; } rootConsole.ForegroundColor = drawColor; char screenChar = StringEquivalent.TerrainChars[map.mapSquares[i, j].Terrain]; screenChar = '#'; rootConsole.PutChar(screenX, screenY, screenChar); rootConsole.Flush(); } } }
/// <summary> /// Refresh the TCOD maps used for FOV and pathfinding /// Unoptimised at present /// </summary> internal void RefreshTCODMap(int levelToRefresh) { //Fail if we have been asked for an invalid level if (levelToRefresh < 0 || levelToRefresh > levels.Count) { LogFile.Log.LogEntry("RefreshTCODMap: Level " + levelToRefresh + " does not exist"); return; } Map level = levels[levelToRefresh]; TCODFov tcodLevel = levelTCODMaps[levelToRefresh]; for (int j = 0; j < level.width; j++) { for (int k = 0; k < level.height; k++) { tcodLevel.SetCell(j, k, !level.mapSquares[j, k].BlocksLight, level.mapSquares[j, k].Walkable); } } }
public void updateFovMap(int level, FovMap fovMap) { TCODFov tcodLevel = new TCODFov(fovMap.Width, fovMap.Height); for (int j = 0; j < fovMap.Width; j++) { for (int k = 0; k < fovMap.Height; k++) { if (fovMap.getCell(j, k) != FOVTerrain.Blocking) { tcodLevel.SetCell(j, k, true, false); } else { tcodLevel.SetCell(j, k, false, false); } } } levelTCODMaps[level] = tcodLevel; levelTCODMapSizes[level] = new WidthHeight(fovMap.Width, fovMap.Height); }
/// <summary> /// Run the Simple AI actions /// </summary> public override void ProcessTurn() { //If in pursuit state, continue to pursue enemy until it is dead (or creature itself is killed) [no FOV used after initial target selected] //If in randomWalk state, look for new enemies in FOV. //Closest enemy becomes new target //If no targets, move randomly Random rand = Game.Random; if (AIState == SimpleAIStates.Pursuit) { //Pursuit state, continue chasing and attacking target //Is target yet living? if (currentTarget.Alive == false) { //If not, go to non-chase state AIState = SimpleAIStates.RandomWalk; } //Is target on another level (i.e. has escaped down the stairs) else if (currentTarget.LocationLevel != this.LocationLevel) { AIState = SimpleAIStates.RandomWalk; } else { //Otherwise continue to chase ChaseCreature(currentTarget); } } if (AIState == SimpleAIStates.RandomWalk) { //RandomWalk state //Search an area of sightRadius on either side for creatures and check they are in the FOV Map currentMap = Game.Dungeon.Levels[LocationLevel]; //Get the FOV from Dungeon (this also updates the map creature FOV state) TCODFov currentFOV = Game.Dungeon.CalculateCreatureFOV(this); //currentFOV.CalculateFOV(LocationMap.x, LocationMap.y, SightRadius); //Check for other creatures within this creature's FOV int xl = LocationMap.x - SightRadius; int xr = LocationMap.x + SightRadius; int yt = LocationMap.y - SightRadius; int yb = LocationMap.y + SightRadius; //If sight is infinite, check all the map if (SightRadius == 0) { xl = 0; xr = currentMap.width; yt = 0; yb = currentMap.height; } if (xl < 0) { xl = 0; } if (xr >= currentMap.width) { xr = currentMap.width - 1; } if (yt < 0) { yt = 0; } if (yb >= currentMap.height) { yb = currentMap.height - 1; } //List will contain monsters & player List <Creature> creaturesInFOV = new List <Creature>(); foreach (Monster monster in Game.Dungeon.Monsters) { //Same monster if (monster == this) { continue; } //Not on the same level if (monster.LocationLevel != this.LocationLevel) { continue; } //Not in FOV if (!currentFOV.CheckTileFOV(monster.LocationMap.x, monster.LocationMap.y)) { continue; } //Otherwise add to list of possible targets creaturesInFOV.Add(monster); LogFile.Log.LogEntryDebug(this.Representation + " spots " + monster.Representation, LogDebugLevel.Medium); } //Check PC if (Game.Dungeon.Player.LocationLevel == this.LocationLevel) { if (currentFOV.CheckTileFOV(Game.Dungeon.Player.LocationMap.x, Game.Dungeon.Player.LocationMap.y)) { creaturesInFOV.Add(Game.Dungeon.Player); LogFile.Log.LogEntryDebug(this.Representation + " spots " + Game.Dungeon.Player.Representation, LogDebugLevel.Medium); } } //If there are possible targets, find the closest and chase it //Otherwise continue to move randomly if (creaturesInFOV.Count > 0) { //Find the closest creature Creature closestCreature = null; double closestDistance = Double.MaxValue; //a long way foreach (Creature creature in creaturesInFOV) { double distanceSq = Math.Pow(creature.LocationMap.x - this.LocationMap.x, 2) + Math.Pow(creature.LocationMap.y - this.LocationMap.y, 2); double distance = Math.Sqrt(distanceSq); if (distance < closestDistance) { closestDistance = distance; closestCreature = creature; } } //Start chasing this creature LogFile.Log.LogEntryDebug(this.Representation + " chases " + closestCreature.Representation, LogDebugLevel.Medium); ChaseCreature(closestCreature); } else { //Move randomly. If we walk into something attack it, but it does not become a new target int direction = rand.Next(9); int moveX = 0; int moveY = 0; moveX = direction / 3 - 1; moveY = direction % 3 - 1; //If we're not moving quit at this point, otherwise the target square will be the one we're in if (moveX == 0 && moveY == 0) { return; } //Check this is a valid move bool validMove = false; Point newLocation = new Point(LocationMap.x + moveX, LocationMap.y + moveY); validMove = Game.Dungeon.MapSquareCanBeEntered(LocationLevel, newLocation); //Give up if this is not a valid move if (!validMove) { return; } //Check if the square is occupied by a PC or monster SquareContents contents = Game.Dungeon.MapSquareContents(LocationLevel, newLocation); bool okToMoveIntoSquare = false; if (contents.empty) { okToMoveIntoSquare = true; } if (contents.player != null) { //Attack the player CombatResults result = AttackPlayer(contents.player); if (result == CombatResults.DefenderDied) { //Bad news for the player here! okToMoveIntoSquare = true; } } if (contents.monster != null) { //Attack the monster CombatResults result = AttackMonster(contents.monster); if (result == CombatResults.DefenderDied) { okToMoveIntoSquare = true; } } //Move if allowed if (okToMoveIntoSquare) { LocationMap = newLocation; } } } }
public static void TestTCODFovTest() { int x = 1; int y = 1; RootConsole.Width = 80; RootConsole.Height = 50; RootConsole.WindowTitle = "FOV Tester"; RootConsole.Fullscreen = false; using (RootConsole console = RootConsole.GetInstance()) { console.Clear(); using (TCODFov fov = new TCODFov(5, 5)) { for (int i = 0; i < 5; ++i) //width { for (int j = 0; j < 5; ++j) //height { fov.SetCell(i, j, room[j, i] == '.', room[j, i] == '.'); } } KeyPress key; do { PaintFOVTest(console, x, y, fov); key = Keyboard.WaitForKeyPress(false); switch (key.KeyCode) { case KeyCode.TCODK_UP: if (room[y - 1, x] == '.') { y--; } break; case KeyCode.TCODK_DOWN: if (room[y + 1, x] == '.') { y++; } break; case KeyCode.TCODK_LEFT: if (room[y, x - 1] == '.') { x--; } break; case KeyCode.TCODK_RIGHT: if (room[y, x + 1] == '.') { x++; } break; } }while (key.Character != 'q' && !console.IsWindowClosed()); } } }
/// <summary> /// Displays the creature FOV on the map. Note that this clobbers the FOV map /// </summary> /// <param name="creature"></param> public void ShowCreatureFOVOnMap(Creature creature) { //Only do this if the creature is on a visible level if (creature.LocationLevel != Player.LocationLevel) { return; } Map currentMap = levels[creature.LocationLevel]; TCODFov tcodFOV = levelTCODMaps[creature.LocationLevel]; //Calculate FOV tcodFOV.CalculateFOV(creature.LocationMap.x, creature.LocationMap.y, creature.SightRadius); //Only check sightRadius around the creature int xl = creature.LocationMap.x - creature.SightRadius; int xr = creature.LocationMap.x + creature.SightRadius; int yt = creature.LocationMap.y - creature.SightRadius; int yb = creature.LocationMap.y + creature.SightRadius; //If sight is infinite, check all the map if (creature.SightRadius == 0) { xl = 0; xr = currentMap.width; yt = 0; yb = currentMap.height; } if (xl < 0) { xl = 0; } if (xr >= currentMap.width) { xr = currentMap.width - 1; } if (yt < 0) { yt = 0; } if (yb >= currentMap.height) { yb = currentMap.height - 1; } for (int i = xl; i <= xr; i++) { for (int j = yt; j <= yb; j++) { MapSquare thisSquare = currentMap.mapSquares[i, j]; bool inFOV = tcodFOV.CheckTileFOV(i, j); if (inFOV) { thisSquare.InMonsterFOV = true; } } } }