public AreaViewWindow(int width, int height, Action <string> showMessageCallback) : base(Config.Instance.Get <int>("MapWidth"), Config.Instance.Get <int>("MapHeight")) { this.showMessageCallback = showMessageCallback; this.TextSurface.RenderArea = new Rectangle(0, 0, width, height); var player = new Player(); var playerEntity = this.CreateGameObject("Player", player); this.CreateGameObject("StairsDown", '>', Color.White); SadConsole.Engine.ActiveConsole = this; // Keyboard setup SadConsole.Engine.Keyboard.RepeatDelay = 0.07f; SadConsole.Engine.Keyboard.InitialRepeatDelay = 0.1f; this.GenerateAndDisplayMap(); var currentFieldOfView = new RogueSharp.FieldOfView(this.currentMap.GetIMap()); var fovTiles = currentFieldOfView.ComputeFov(playerEntity.Position.X, playerEntity.Position.Y, Config.Instance.Get <int>("PlayerLightRadius"), true); this.MarkCurrentFovAsVisible(fovTiles); var creatures = this.objects.Where(s => s.Data is Monster || s.Data is Player).Select(e => e.Data as IHasAgility); this.turnCalculator = new TurnCalculator(creatures); }
public Vision(GameObject host, int radius) : base("Vision", host) { this.radius = radius; this.currentMap = this.Host.Location.Map; this.fov = new RogueSharp.FieldOfView(this.currentMap); var origin = this.Host.Location.Point; this.fov.ComputeFov(origin.X, origin.Y, this.radius, true); }
private void GenerateMap() { // Create the map. RogueSharp.MapCreation.IMapCreationStrategy <RogueSharp.Map> mapCreationStrategy = new RogueSharp.MapCreation.RandomRoomsMapCreationStrategy <RogueSharp.Map>(Width, Height, 100, 15, 4); rogueMap = RogueSharp.Map.Create(mapCreationStrategy); rogueFOV = new RogueSharp.FieldOfView(rogueMap); // Create the local cache of the map data. mapData = new MapObjects.MapObjectBase[Width, Height]; // Loop through the map information generated by RogueSharp and create out cached visuals of that data. foreach (var cell in rogueMap.GetAllCells()) { if (cell.IsWalkable) { // Our local information about each map square. mapData[cell.X, cell.Y] = new MapObjects.Floor(); // Copy the appearance we've defined for Floor or Wall or whatever to the actual console data that is being rendered. mapData[cell.X, cell.Y].RenderToCell(this[cell.X, cell.Y], false, false); } else { rogueMap.SetCellProperties(cell.X, cell.Y, false, false); mapData[cell.X, cell.Y] = new MapObjects.Wall(); mapData[cell.X, cell.Y].RenderToCell(this[cell.X, cell.Y], false, false); // A wall blocks LOS rogueMap.SetCellProperties(cell.X, cell.Y, false, cell.IsWalkable); } } RogueSharp.Random.IRandom random = new RogueSharp.Random.DotNetRandom(); // Position the player somewhere on a walkable square. while (true) { int x = random.Next(Width - 1); int y = random.Next(Height - 1); if (rogueMap.IsWalkable(x, y)) { Player.Position = new Point(x, y); // Center the view area. TextSurface.RenderArea = new Rectangle(Player.Position.X - (TextSurface.RenderArea.Width / 2), Player.Position.Y - (TextSurface.RenderArea.Height / 2), TextSurface.RenderArea.Width, TextSurface.RenderArea.Height); Player.RenderOffset = this.Position - TextSurface.RenderArea.Location; break; } } }
public override void Update(GameTime deltatime) { base.Update(deltatime); var map = this.Host.Location.Map; if (map != this.currentMap) { this.currentMap = map; this.fov = new RogueSharp.FieldOfView(this.currentMap); } var origin = this.Host.Location.Point; this.fov.ComputeFov(origin.X, origin.Y, this.radius, true); }
private void MovePlayerBy(Point amount, KeyboardInfo info = null) { var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); var currentFieldOfView = new RogueSharp.FieldOfView(this.currentMap.GetIMap()); var playerView = this.objects.Single(g => g.Name == "Player"); var fovTiles = currentFieldOfView.ComputeFov(playerView.Position.X, playerView.Position.Y, Config.Instance.Get <int>("PlayerLightRadius"), true); this.MarkCurrentFovAsDiscovered(fovTiles); foreach (var obj in this.objects) { obj.IsVisible = false; } // Undo monster vision tile effect foreach (var monsterView in this.objects.Where(o => o.Data is Monster)) { var data = monsterView.Data as Monster; var monsterFov = currentFieldOfView.ComputeFov(data.X, data.Y, data.VisionSize, true); // If we can see them, they're discovered foreach (var cell in monsterFov) { if (this.discoveredTiles.ContainsKey($"{cell.X}, {cell.Y}")) { this[cell.X, cell.Y].ApplyEffect(DiscoveredEffect); } else { this[cell.X, cell.Y].ApplyEffect(HiddenEffect); } } } // Get the position the player will be at Point newPosition = playerView.Position + amount; // Is there a block there? if (currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Any(e => e is Pushable)) { // Is there an empty space behind it? var behindBlock = newPosition + amount; if (currentMap.IsWalkable(behindBlock.X, behindBlock.Y)) { // Push it (update data) var obj = currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Single(e => e is Pushable); obj.Move(behindBlock.X, behindBlock.Y); // Push it (move view object) this.objects.Single(g => g.Data == obj).Move(behindBlock.X, behindBlock.Y); this.CheckIfBlockPuzzleIsComplete(); } } // Check to see if the position is within the map and walkable if (new Rectangle(0, 0, Width, Height).Contains(newPosition) && currentMap.IsWalkable(newPosition.X, newPosition.Y)) { // Pull a block along if specified if (info.KeysDown.Contains(AsciiKey.Get(Keys.Space))) { // Are you holding space? Did you move in a direction (eg. left) and there's a push block on the other side (eg. right)? // If so, and if the target block position is walkable, pull it along. But this only works if you're pulling // in the direction you're moving (eg. standing on top and pulling a block upward), NOT standing beside a block // and pulling it upward or standing above a block and pulling to the left/right var currentBlockPos = playerView.Position + new Point(amount.X * -1, amount.Y * -1); if (currentMap.GetObjectsAt(currentBlockPos.X, currentBlockPos.Y).Any(e => e is Pullable)) { // Given constraints above, target position is current player position var obj = currentMap.GetObjectsAt(currentBlockPos.X, currentBlockPos.Y).Single(e => e is Pullable); obj.Move(playerView.Position.X, playerView.Position.Y); this.objects.Single(g => g.Data == obj).Move(playerView.Position.X, playerView.Position.Y); this.CheckIfBlockPuzzleIsComplete(); } } // Move the player playerView.Position += amount; playerView.Data.Move(playerView.Position.X, playerView.Position.Y); CenterViewToPlayer(); } var key = this.currentMap.GetObjectsAt(playerView.Position.X, playerView.Position.Y).Where(s => s is Key).SingleOrDefault(); if (key != null) { // Not sure why two keys are spawned here var keys = this.objects.Where(s => s.Data == key).ToList(); foreach (var k in keys) { this.objects.Remove(k); this.currentMap.Remove(key); } (this.objects.Single(o => o.Data is Player).Data as Player).Keys += 1; this.showMessageCallback("Got a key."); } // Door there, and we have a key? Unlock it! if ((playerView.Data as Player).Keys > 0 && this.currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Any(o => o is LockedDoor)) { var doorData = this.currentMap.GetObjectsAt(newPosition.X, newPosition.Y).Where(o => o is LockedDoor).ToList(); var doors = this.objects.Where(o => doorData.Contains(o.Data)).ToList(); // Why, why WHY are there multiple copies? foreach (var door in doors) { this.objects.Remove(door); this.currentMap.Remove(door.Data); } showMessageCallback("You unlock the door."); (playerView.Data as Player).Keys -= 1; } fovTiles = currentFieldOfView.ComputeFov(playerView.Position.X, playerView.Position.Y, Config.Instance.Get <int>("PlayerLightRadius"), true); this.MarkCurrentFovAsVisible(fovTiles); // Monsters turn. Also, draw their field-of-view. Keep queuing turns until it's the player's turn again. var monstersToMove = new List <IHasAgility>(); IHasAgility next = null; while (next != playerView.Data) { if (next != null) { monstersToMove.Add(next); } next = turnCalculator.NextTurn(); } while (monstersToMove.Any()) { var m = monstersToMove[0]; monstersToMove.RemoveAt(0); var monsterView = this.objects.Single(o => o.Data is Monster && o.Data == m); var data = monsterView.Data as Monster; var hurtPlayer = data.MoveWithAi(playerView.Data as Player); if (hurtPlayer) { if ((playerView.Data as Player).IsDead) { showMessageCallback("The monster hits you! You die ..."); this.gameOver = true; } else { showMessageCallback("Monster hits you!"); } } else { monsterView.Position = new Point(data.X, data.Y); bool sawPlayer = false; var monsterFov = currentFieldOfView.ComputeFov(data.X, data.Y, data.VisionSize, true); foreach (var cell in monsterFov) { if (fovTiles.Any(f => f.X == data.X && f.Y == data.Y)) { this[cell.X, cell.Y].ApplyEffect(MonsterVisionEffect); if (playerView.Position.X == cell.X && playerView.Position.Y == cell.Y) { data.HuntPlayer(); monsterView.RenderCells.First().ActualForeground = new Color(255, 0, 0); sawPlayer = true; } } else { if (this.discoveredTiles.ContainsKey($"{data.X}, {data.Y}")) { this[cell.X, cell.Y].ApplyEffect(DiscoveredEffect); } else { this[cell.X, cell.Y].ApplyEffect(HiddenEffect); } } } if (!sawPlayer && monsterView.RenderCells.First().ActualForeground.R == 255) { monsterView.RenderCells.First().ActualForeground = new Color(data.Colour.R, data.Colour.G, data.Colour.B); } } } stopwatch.Stop(); var elapsed = stopwatch.Elapsed.TotalSeconds; Console.WriteLine($"Moving took {elapsed}s"); }