private void FillcharacterBuffersWithWorld(Screen screen, ConsoleCamera camera, GameSettings settings,
                                                   IWorldProvider world)
        {
            int camX = camera.getPosition().X;
            int camY = camera.getPosition().Y;

            if (angle > 360)
            {
                angle = 0;
            }

            angle += step;

            for (int x = camX; x < settings.GetWidthZoomed() + camX; x++)
            {
                for (int y = camY; y < settings.GetHeightZoomed() + camY; y++)
                {
                    Point screenPoint = camera.PointToScreen(x, y);
                    if (screen.ScreenBuffer[screenPoint.Y, screenPoint.X].isVisible)
                    {
                        Tile tileToDraw = world.GetTile(x, y);
                        GetTerrainTile(screen, TerrainLibrary.Terrains[tileToDraw.Terrain], screenPoint);
                    }
                    else
                    {
                        screen.ScreenBuffer[screenPoint.Y, screenPoint.X].Char            = ' ';
                        screen.ScreenBuffer[screenPoint.Y, screenPoint.X].BackGroundColor = new Color();
                    }
                }
            }
        }
        public static Entity CreateViewport(GameSettings settings)
        {
            Entity        viewport = new Entity();
            ConsoleCamera camera   = new ConsoleCamera(new Point(0, 0));
            Screen        screen   = new Screen(settings.GetWidthZoomed(), settings.GetHeightZoomed());

            viewport.AddComponent(camera);
            viewport.AddComponent(screen);
            return(viewport);
        }
        private void MoveCamera(NamelessGame game, ConsoleCamera camera)
        {
            Position playerPosition = game.FollowedByCameraEntity
                                      .GetComponentOfType <Position>();

            Point p = camera.getPosition();

            p.X = (playerPosition.Point.X - game.GetSettings().GetWidthZoomed() / 2);
            p.Y = (playerPosition.Point.Y - game.GetSettings().GetHeightZoomed() / 2);
            camera.setPosition(p);
        }
        public override void Update(long gameTime, NamelessGame game)
        {
            this.gameTime = gameTime;

            game.GraphicsDevice.BlendState        = BlendState.AlphaBlend;
            game.GraphicsDevice.SamplerStates[0]  = sampler;
            game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            //todo move to constructor or some other place better suited for initialization
            if (tileAtlas == null)
            {
                InitializeTexture(game);
            }

            IEntity        worldEntity   = game.TimelineEntity;
            IWorldProvider worldProvider = null;

            if (worldEntity != null)
            {
                worldProvider = worldEntity.GetComponentOfType <TimeLine>().CurrentTimelineLayer.Chunks;
            }

            var entity = game.CameraEntity;

            ConsoleCamera camera    = entity.GetComponentOfType <ConsoleCamera>();
            Screen        screen    = entity.GetComponentOfType <Screen>();
            Commander     commander = game.Commander;

            screen = UpdateZoom(game, commander, entity, screen, out bool zoomUpdate);

            if (foregroundModel == null || zoomUpdate)
            {
                foregroundModel = new TileModel(screen.Height, screen.Width);
            }

            if (backgroundModel == null || zoomUpdate)
            {
                backgroundModel = new TileModel(screen.Height, screen.Width);
            }


            if (camera != null && screen != null && worldProvider != null)
            {
                MoveCamera(game, camera);
                FillcharacterBufferVisibility(game, screen, camera, game.GetSettings(), worldProvider);
                FillcharacterBuffersWithWorld(screen, camera, game.GetSettings(), worldProvider);
                FillcharacterBuffersWithTileObjects(screen, camera, game.GetSettings(), game, worldProvider);
                FillcharacterBuffersWithWorldObjects(screen, camera, game.GetSettings(), game);
                RenderScreen(game, screen, game.GetSettings());
            }
        }
        private void FillcharacterBufferVisibility(NamelessGame game, Screen screen, ConsoleCamera camera,
                                                   GameSettings settings, IWorldProvider world)
        {
            int         camX           = camera.getPosition().X;
            int         camY           = camera.getPosition().Y;
            Position    playerPosition = game.PlayerEntity.GetComponentOfType <Position>();
            BoundingBox b = new BoundingBox(camera.getPosition(),
                                            new Point(settings.GetWidthZoomed() + camX, settings.GetHeightZoomed() + camY));

            for (int x = 0; x < settings.GetWidthZoomed(); x++)
            {
                for (int y = 0; y < settings.GetHeightZoomed(); y++)
                {
                    screen.ScreenBuffer[x, y].isVisible = false;
                }
            }

            //return;

            if (fov == null)
            {
                {
                    fov = new PermissiveVisibility((x, y) => { return(!world.GetTile(x, y).GetBlocksVision(game)); },
                                                   (x, y) =>
                    {
                        Stopwatch s           = Stopwatch.StartNew();
                        var lambdaLocalScreen = game.CameraEntity.GetComponentOfType <Screen>();
                        s.Stop();
                        s.ToString();

                        Point screenPoint = camera.PointToScreen(x, y);
                        if (screenPoint.X >= 0 && screenPoint.X < settings.GetWidthZoomed() && screenPoint.Y >= 0 &&
                            screenPoint.Y < settings.GetHeightZoomed())
                        {
                            lambdaLocalScreen.ScreenBuffer[screenPoint.X, screenPoint.Y].isVisible = true;
                        }
                    }, (x, y) =>
                    {
                        if (Math.Abs(x) > 60 || Math.Abs(y) > 60)
                        {
                            return(10000);
                        }
                        //   return (int)((x*x) + (y*y));
                        return(Math.Abs(x) + Math.Abs(y));
                    }
                                                   );
                }
            }
            fov.Compute(playerPosition.Point, 60);
        }
        public override void Update(long gameTime, NamelessGame game)
        {
            this.gameTime = gameTime;

            //todo move to constructor or some other place better suited for initialization
            if (tileAtlas == null)
            {
                InitializeTexture(game);
                _spriteBatch = new SpriteBatch(game.GraphicsDevice);
            }


            Commander commander = game.Commander;


            var           entity = game.CameraEntity;
            ConsoleCamera camera = entity.GetComponentOfType <ConsoleCamera>();
            Screen        screen = entity.GetComponentOfType <Screen>();

            screen = UpdateZoom(game, commander, entity, screen);

            _spriteBatch.Begin(SpriteSortMode.Deferred, null, null, DepthStencilState.None);


            IEntity        worldEntity   = game.TimelineEntity;
            IWorldProvider worldProvider = null;

            if (worldEntity != null)
            {
                worldProvider = worldEntity.GetComponentOfType <TimeLine>().CurrentTimelineLayer.Chunks;
            }


            if (camera != null && screen != null && worldProvider != null)
            {
                MoveCamera(game, camera);
                FillcharacterBufferVisibility(game, screen, camera, game.GetSettings(), worldProvider);
                FillcharacterBuffersWithWorld(screen, camera, game.GetSettings(), worldProvider);
                FillcharacterBuffersWithTileObjects(screen, camera, game.GetSettings(), game, worldProvider);
                FillcharacterBuffersWithWorldObjects(screen, camera, game.GetSettings(), game);
                RenderScreen(game, screen, game.GetSettings());
            }
            _spriteBatch.End();
        }
        private void FillcharacterBuffersWithTileObjects(Screen screen, ConsoleCamera camera, GameSettings settings,
                                                         NamelessGame game, IWorldProvider world)
        {
            int camX = camera.getPosition().X;
            int camY = camera.getPosition().Y;

            if (angle > 360)
            {
                angle = 0;
            }

            angle += step;

            for (int x = camX; x < settings.GetWidthZoomed() + camX; x++)
            {
                for (int y = camY; y < settings.GetHeightZoomed() + camY; y++)
                {
                    Point screenPoint = camera.PointToScreen(x, y);
                    if (screen.ScreenBuffer[screenPoint.Y, screenPoint.X].isVisible)
                    {
                        Tile tileToDraw = world.GetTile(x, y);

                        foreach (var entity in tileToDraw.GetEntities())
                        {
                            var furniture = entity.GetComponentOfType <Furniture>();
                            var drawable  = entity.GetComponentOfType <Drawable>();
                            if (furniture != null && drawable != null)
                            {
                                screen.ScreenBuffer[screenPoint.Y, screenPoint.X].Char      = drawable.Representation;
                                screen.ScreenBuffer[screenPoint.Y, screenPoint.X].CharColor = drawable.CharColor;
                            }
                        }
                    }
                }
            }
        }
        private void FillcharacterBufferVisibility(NamelessGame game, Screen screen, ConsoleCamera camera,
                                                   GameSettings settings, IWorldProvider world)
        {
            int         camX           = camera.getPosition().X;
            int         camY           = camera.getPosition().Y;
            Position    playerPosition = game.PlayerEntity.GetComponentOfType <Position>();
            BoundingBox b = new BoundingBox(camera.getPosition(),
                                            new Point(settings.GetWidthZoomed() + camX, settings.GetHeightZoomed() + camY));

            for (int x = 0; x < settings.GetWidthZoomed(); x++)
            {
                for (int y = 0; y < settings.GetHeightZoomed(); y++)
                {
                    screen.ScreenBuffer[y, x].isVisible = true;
                }
            }

            return;

            if (fov == null)
            {
                fov = new PermissiveVisibility((x, y) => { return(!world.GetTile(x, y).GetBlocksVision(game)); },
                                               (x, y) =>
                {
                    Point screenPoint = camera.PointToScreen(x, y);
                    if (screenPoint.X >= 0 && screenPoint.X < settings.GetWidth() && screenPoint.Y >= 0 &&
                        screenPoint.Y < settings.GetHeight())
                    {
                        screen.ScreenBuffer[screenPoint.X, screenPoint.Y].isVisible = true;
                    }
                }, (x, y) => { return(Math.Abs(x) + Math.Abs(y)); }
                                               );
            }

            fov.Compute(playerPosition.Point, 60);
        }
        public override void Update(long gameTime, NamelessGame namelessGame)
        {
            ConsoleCamera camera       = namelessGame.CameraEntity?.GetComponentOfType <ConsoleCamera>();
            TimeLine      timeline     = namelessGame.TimelineEntity?.GetComponentOfType <TimeLine>();
            var           tilePosition = camera.GetMouseTilePosition(namelessGame);
            var           settings     = namelessGame.WorldSettings;

            if (tilePosition.X >= 0 && tilePosition.X < settings.WorldBoardWidth && tilePosition.Y >= 0 && tilePosition.Y < settings.WorldBoardHeight)
            {
                var tile = timeline.CurrentTimelineLayer.WorldTiles[tilePosition.X, tilePosition.Y];

                switch (UiFactory.WorldBoardScreen.Mode)
                {
                case WorldBoardScreenAction.ArtifactMode:
                {
                    if (tile.Artifact != null)
                    {
                        UiFactory.WorldBoardScreen.DescriptionLog.Text = (tile.Artifact.Name);
                    }
                }
                break;

                case WorldBoardScreenAction.PoliticalMode:
                {
                    if (tile.Owner != null)
                    {
                        if (tile.Settlement != null)
                        {
                            UiFactory.WorldBoardScreen.DescriptionLog.Text = $"{tile.Owner.Name}, {tile.Settlement.Name} city";
                        }
                        else
                        {
                            UiFactory.WorldBoardScreen.DescriptionLog.Text = $"{tile.Owner.Name}";
                        }
                    }
                }
                break;

                case WorldBoardScreenAction.RegionsMode:
                {
                    if (tile.Continent != null)
                    {
                        UiFactory.WorldBoardScreen.DescriptionLog.Text = $"{tile.Continent.Name} continent";
                    }
                    if (tile.LandmarkRegion != null)
                    {
                        UiFactory.WorldBoardScreen.DescriptionLog.Text = $"{tile.LandmarkRegion.Name} region";
                    }
                }
                break;

                default:
                    UiFactory.WorldBoardScreen.DescriptionLog.Text = "";
                    break;
                }
            }

            foreach (var worldBoardScreenAction in UiFactory.WorldBoardScreen.SimpleActions)
            {
                switch (worldBoardScreenAction)
                {
                case WorldBoardScreenAction.ReturnToGame:

                    namelessGame.ContextToSwitch = ContextFactory.GetIngameContext(namelessGame);
                    break;

                case WorldBoardScreenAction.RegionsMode:
                {
                    _mapRenderSystem.Mode = WorldBoardRenderingSystemMode.Regions;
                }
                break;

                case WorldBoardScreenAction.PoliticalMode:
                {
                    _mapRenderSystem.Mode = WorldBoardRenderingSystemMode.Political;
                }
                break;

                case WorldBoardScreenAction.TerrainMode:
                {
                    _mapRenderSystem.Mode = WorldBoardRenderingSystemMode.Terrain;
                }
                break;

                case WorldBoardScreenAction.ArtifactMode:
                {
                    _mapRenderSystem.Mode = WorldBoardRenderingSystemMode.Terrain;
                }

                break;

                case WorldBoardScreenAction.LocalMap:
                {
                    _mapRenderSystem.LocalMapRendering = true;
                }

                break;

                case WorldBoardScreenAction.WorldMap:
                {
                    _mapRenderSystem.LocalMapRendering = false;
                }

                break;

                default:
                    break;
                }
            }
            UiFactory.WorldBoardScreen.SimpleActions.Clear();
        }
        private void FillcharacterBuffersWithWorldObjects(Screen screen, ConsoleCamera camera, GameSettings settings,
                                                          NamelessGame game)
        {
            List <IEntity> characters = new List <IEntity>();

            foreach (IEntity entity in RegisteredEntities)
            {
                Drawable drawable = entity.GetComponentOfType <Drawable>();

                var character = entity.GetComponentOfType <Character>();
                if (character != null)
                {
                    characters.Add(entity);
                    continue;
                }

                Position position = entity.GetComponentOfType <Position>();

                LineToPlayer lineToPlayer = entity.GetComponentOfType <LineToPlayer>();
                if (drawable.Visible)
                {
                    Point screenPoint = camera.PointToScreen(position.Point.X, position.Point.Y);
                    int   x           = screenPoint.X;
                    int   y           = screenPoint.Y;
                    if (x >= 0 && x < settings.GetWidth() && y >= 0 && y < settings.GetHeight())
                    {
                        if (screen.ScreenBuffer[screenPoint.Y, screenPoint.X].isVisible)
                        {
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].Char      = drawable.Representation;
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].CharColor = drawable.CharColor;
                        }
                        else
                        {
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].Char            = ' ';
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].CharColor       = new Color();
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].BackGroundColor = new Color();
                        }
                    }
                }


                if (lineToPlayer != null)
                {
                    if (drawable.Visible)
                    {
                        Position playerPosition =
                            game.PlayerEntity.GetComponentOfType <Position>();
                        List <Point> line = PointUtil.getLine(playerPosition.Point, position.Point);
                        for (int i = 1; i < line.Count - 1; i++)
                        {
                            Point p           = line[i];
                            Point screenPoint = camera.PointToScreen(p.X, p.Y);
                            int   x           = screenPoint.X;
                            int   y           = screenPoint.Y;
                            if (x >= 0 && x < settings.GetWidth() && y >= 0 && y < settings.GetHeight())
                            {
                                screen.ScreenBuffer[screenPoint.Y, screenPoint.X].Char      = 'x';
                                screen.ScreenBuffer[screenPoint.Y, screenPoint.X].CharColor = drawable.CharColor;
                            }
                        }
                    }
                }
            }

            foreach (IEntity entity in characters)
            {
                Drawable drawable = entity.GetComponentOfType <Drawable>();

                if (drawable == null)
                {
                    continue;
                }

                Position position = entity.GetComponentOfType <Position>();
                if (drawable.Visible)
                {
                    Point screenPoint = camera.PointToScreen(position.Point.X, position.Point.Y);
                    int   x           = screenPoint.X;
                    int   y           = screenPoint.Y;
                    if (x >= 0 && x < settings.GetWidthZoomed() && y >= 0 && y < settings.GetHeightZoomed())
                    {
                        if (screen.ScreenBuffer[screenPoint.Y, screenPoint.X].isVisible)
                        {
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].Char      = drawable.Representation;
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].CharColor = drawable.CharColor;
                        }
                        else
                        {
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].Char            = ' ';
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].CharColor       = new Color();
                            screen.ScreenBuffer[screenPoint.Y, screenPoint.X].BackGroundColor = new Color();
                        }
                    }
                }
            }
        }