示例#1
0
        // Redraws only what fits on-screen, thus being a "camera" of sorts
        // Redraws ENTIRE MAP, then global-to-local redraws the camera part on screen
        private void RedrawEverything(TimeSpan delta)
        {
            backBuffer.Fill(Color.Black, Color.Black, ' ');

            for (var y = 0; y < this.dungeon.Height; y++)
            {
                for (var x = 0; x < this.dungeon.Width; x++)
                {
                    if (this.dungeon.CurrentFloor.IsInPlayerFov(x, y))
                    {
                        backBuffer.SetGlyph(x, y, '.', Palette.DarkPurple, Palette.DarkPurple);
                    }
                    else if (this.dungeon.CurrentFloor.IsSeen(x, y))
                    {
                        backBuffer.SetGlyph(x, y, '.', Palette.BlackAlmost, Palette.BlackAlmost);
                    }
                }
            }

            foreach (var residue in this.dungeon.CurrentFloor.PlasmaResidue)
            {
                if (this.dungeon.CurrentFloor.IsInPlayerFov(residue.X, residue.Y))
                {
                    backBuffer.SetGlyph(residue.X, residue.Y, residue.Character, residue.Color, Palette.LightRed);
                }
            }

            foreach (var wall in dungeon.CurrentFloor.Walls)
            {
                var x = wall.X;
                var y = wall.Y;

                if (this.dungeon.CurrentFloor.IsInPlayerFov(x, y))
                {
                    backBuffer.SetGlyph(wall.X, wall.Y, wall.Character, wall.Color);
                }
                else if (this.dungeon.CurrentFloor.IsSeen(x, y))
                {
                    backBuffer.SetGlyph(wall.X, wall.Y, wall.Character, Palette.Grey);
                }
            }

            foreach (var chasm in this.dungeon.CurrentFloor.Chasms)
            {
                if (this.dungeon.CurrentFloor.IsInPlayerFov(chasm.X, chasm.Y))
                {
                    backBuffer.SetGlyph(chasm.X, chasm.Y, chasm.Character, chasm.Color, Palette.DarkMutedBrown);
                }
                else if (this.dungeon.CurrentFloor.IsSeen(chasm.X, chasm.Y))
                {
                    backBuffer.SetGlyph(chasm.X, chasm.Y, chasm.Character, Palette.Grey);
                }
            }

            foreach (var door in this.dungeon.CurrentFloor.Doors)
            {
                var x = door.X;
                var y = door.Y;

                if (this.dungeon.CurrentFloor.IsInPlayerFov(x, y))
                {
                    backBuffer.SetGlyph(x, y, door.Character, door.Color);
                }
                else if (this.dungeon.CurrentFloor.IsSeen(x, y))
                {
                    backBuffer.SetGlyph(x, y, door.Character, Palette.Grey);
                }
            }

            foreach (var wave in this.dungeon.CurrentFloor.GravityWaves)
            {
                if (this.dungeon.CurrentFloor.IsInPlayerFov(wave.X, wave.Y))
                {
                    backBuffer.SetGlyph(wave.X, wave.Y, wave.Character, wave.Color);
                }
            }

            var elapsedSeconds  = this.gameTime.TotalMilliseconds;
            var stairsCharIndex = (int)Math.Floor(elapsedSeconds / RotatePlasmaDriveColorEveryMilliseconds) % 3;
            var stairsColour    = StairsColours[stairsCharIndex];

            if (this.dungeon.CurrentFloor.StairsDownLocation != GoRogue.Coord.NONE)
            {
                int stairsX = this.dungeon.CurrentFloor.StairsDownLocation.X;
                int stairsY = this.dungeon.CurrentFloor.StairsDownLocation.Y;

                if (this.dungeon.CurrentFloor.IsInPlayerFov(stairsX, stairsY) || this.dungeon.CurrentFloor.IsSeen(stairsX, stairsY))
                {
                    backBuffer.SetGlyph(stairsX, stairsY, stairsCharIndex, this.dungeon.CurrentFloor.IsInPlayerFov(stairsX, stairsY) ? stairsColour : Palette.Grey);
                }
            }

            if (this.dungeon.CurrentFloorNum > 0 && this.dungeon.CurrentFloor.StairsUpLocation != GoRogue.Coord.NONE)
            {
                int stairsX = this.dungeon.CurrentFloor.StairsUpLocation.X;
                int stairsY = this.dungeon.CurrentFloor.StairsUpLocation.Y;

                if (this.dungeon.CurrentFloor.IsInPlayerFov(stairsX, stairsY) || this.dungeon.CurrentFloor.IsSeen(stairsX, stairsY))
                {
                    backBuffer.SetGlyph(stairsX, stairsY, stairsCharIndex, this.dungeon.CurrentFloor.IsInPlayerFov(stairsX, stairsY) ? stairsColour : Palette.Grey);
                }
            }

            var weaponPickUp = this.dungeon.CurrentFloor.WeaponPickUp;

            // Weapons are always visible. This adds tension/arrow-of-play. You need them to
            // get through obstacles on later floors. #notabug
            if (weaponPickUp != null)
            {
                var colours     = Options.CurrentPalette.WeaponColours;
                var colourIndex = (int)Math.Floor(elapsedSeconds / RotateWeaponColorEveryMilliseconds) % colours.Count;
                backBuffer.SetGlyph(weaponPickUp.X, weaponPickUp.Y, weaponPickUp.Character, colours[colourIndex]);
            }

            var dataCube = this.dungeon.CurrentFloor.DataCube;

            if (dataCube != null)
            {
                var colours     = Options.CurrentPalette.DataCubeColours;
                var colourIndex = (int)Math.Floor(elapsedSeconds / RotatePowerUpColorEveryMilliseconds) % colours.Count;
                backBuffer.SetGlyph(dataCube.X, dataCube.Y, dataCube.Character, colours[colourIndex]);
            }

            // B1 has power-ups under the fake wall, so we draw power-ups first.
            foreach (var powerUp in this.dungeon.CurrentFloor.PowerUps)
            {
                if (this.dungeon.CurrentFloor.IsInPlayerFov(powerUp.X, powerUp.Y))
                {
                    var colours     = Options.CurrentPalette.PowerUpColours;
                    var colourIndex = (int)Math.Floor(elapsedSeconds / RotatePowerUpColorEveryMilliseconds) % colours.Count;
                    backBuffer.SetGlyph(powerUp.X, powerUp.Y, powerUp.Character, colours[colourIndex]);
                }
            }

            foreach (var monster in this.dungeon.CurrentFloor.Monsters)
            {
                if (this.dungeon.CurrentFloor.IsInPlayerFov(monster.X, monster.Y))
                {
                    var character = monster.Character;
                    var colour    = monster is Ameer ? monster.Color : Entity.MonsterColours[monster.Name];

                    backBuffer.SetGlyph(monster.X, monster.Y, character, colour);
                }
            }

            // Drawn over monsters because THEY HIDE IN FAKE WALLS. Sometimes.
            foreach (var wall in dungeon.CurrentFloor.FakeWalls)
            {
                var x = wall.X;
                var y = wall.Y;

                if (this.dungeon.CurrentFloor.IsInPlayerFov(x, y))
                {
                    backBuffer.SetGlyph(wall.X, wall.Y, wall.Character, FakeWall.Colour);
                }
                else if (this.dungeon.CurrentFloor.IsSeen(x, y))
                {
                    backBuffer.SetGlyph(wall.X, wall.Y, wall.Character, Palette.Grey);
                }
            }

            var shipCore = this.dungeon.CurrentFloor.ShipCore;

            if (shipCore != null)
            {
                var colourIndex = (int)Math.Floor(elapsedSeconds / RotatePlasmaDriveColorEveryMilliseconds) % ShipCore.Colours.Length;
                backBuffer.SetGlyph(shipCore.X, shipCore.Y, shipCore.Character, ShipCore.Colours[colourIndex]);
            }

            foreach (var plasma in this.dungeon.CurrentFloor.QuantumPlasma)
            {
                // Doesn't care about LOS. You're dead if you get cornered.
                backBuffer.SetGlyph(plasma.X, plasma.Y, plasma.Character, plasma.Color);
            }

            backBuffer.SetGlyph(this.dungeon.Player.X, this.dungeon.Player.Y, this.dungeon.Player.Character, this.dungeon.Player.Color);

            foreach (var effect in this.dungeon.CurrentFloor.EffectEntities)
            {
                if (this.dungeon.CurrentFloor.IsInPlayerFov(effect.X, effect.Y))
                {
                    backBuffer.SetGlyph(effect.X, effect.Y, effect.Character, effect.Color);
                }
            }

            // Keeps rendering from going out-of-bounds
            var cameraStartX = Math.Max(0, dungeon.CurrentFloor.Player.X - (ScreenTilesWidth / 2));
            var cameraStartY = Math.Max(0, dungeon.CurrentFloor.Player.Y - (ScreenTilesHeight / 2));
            var cameraStopX  = Math.Min(cameraStartX + ScreenTilesWidth, dungeon.Width);
            var cameraStopY  = Math.Min(cameraStartY + ScreenTilesHeight, dungeon.Height);

            // https://twitter.com/nightblade99/status/1180203280946864129
            // What if the user is in the bottom-right corner of the map?
            // camera start will be correct, but stop will be the max, meaning we're just rendering a tiny block.
            // Nah, bro. Instead, offset start X/Y backward until we're rendering a full screen.
            var dx = ScreenTilesWidth - (cameraStopX - cameraStartX);
            var dy = ScreenTilesHeight - (cameraStopY - cameraStartY);

            // dx/dy are only positive in the bottom-right quadrant
            cameraStartX -= dx;
            cameraStartY -= dy;

            for (var y = cameraStartY; y < cameraStopY; y++)
            {
                for (var x = cameraStartX; x < cameraStopX; x++)
                {
                    // Global to local
                    this.SetGlyph(x - cameraStartX, y - cameraStartY, this.backBuffer.GetGlyph(x, y), backBuffer.GetForeground(x, y), backBuffer.GetBackground(x, y));
                }
            }

            this.DrawMessageConsole();
            this.DrawSubMenu(delta);
        }