private static AliensState ResolveAlienCollisions(AliensState aliensState, List <Tuple <int, int> > alienRocketCollisions)
 {
     if (alienRocketCollisions.Count != 0)
     {
         List <Vector2i> remainingPositions = aliensState.RelativePositions.Where((position, index) => !alienRocketCollisions.Exists(collision => index == collision.Item1)).ToList();
         return(new AliensState(aliensState.TopLeft, remainingPositions));
     }
     else
     {
         return(aliensState);
     }
 }
        public static WorldState CreateNewWorldState(int width, int height, int maxRockets, int aliensWidth, int aliensHeight, int initialLives)
        {
            GameConfigState     gameConfigState     = new GameConfigState(width, height, maxRockets, aliensWidth, aliensHeight);
            PlayerState         playerState         = new PlayerState(width / 2);
            AliensState         aliensState         = CreateNewAliensState(width, height, aliensWidth, aliensHeight);
            AliensMovementState aliensMovementState = new AliensMovementState(AliensMovementState.MovementDirection.Right);
            RocketsState        rocketsState        = new RocketsState(new List <Vector2i>());
            BombsState          bombsState          = new BombsState(new List <Vector2i>());
            GameProgressState   gameProgressState   = new GameProgressState(0, initialLives, false);
            WorldState          worldState          = new WorldState(gameConfigState, playerState, aliensState, aliensMovementState, rocketsState, bombsState, gameProgressState);

            return(worldState);
        }
        public static void TickAliensFiring(AliensState aliensState, out AliensFiringInput newAliensFiringInput)
        {
            Random r = new Random();

            if (r.Next(10) == 0)
            {
                List <int> bottomRow = aliensState.GetBottomRow();
                newAliensFiringInput = new AliensFiringInput(true, bottomRow[r.Next(bottomRow.Count)]);
            }
            else
            {
                newAliensFiringInput = new AliensFiringInput(false, 0);
            }
        }
        public WorldState(GameConfigState gameConfigState, PlayerState playerState, AliensState aliensState, AliensMovementState aliensMovementState,
                          RocketsState rocketsState, BombsState bombsState, GameProgressState gameProgressState)
        {
            GameConfigState = gameConfigState;
            PlayerState     = playerState;
            AliensState     = aliensState;

            AliensMovementState = aliensMovementState;

            RocketsState = rocketsState;

            BombsState = bombsState;

            GameProgressState = gameProgressState;
        }
        private static List <Tuple <int, int> > FindAlienRocketCollisions(AliensState aliensState, RocketsState rocketsState)
        {
            List <Tuple <int, int> > collisions = new List <Tuple <int, int> >();

            for (int rocketIndex = 0; rocketIndex < rocketsState.Positions.Count; rocketIndex++)
            {
                Vector2i rocketPosition = rocketsState.Positions[rocketIndex];
                int      alienIndex     = aliensState.RelativePositions.FindIndex(alienRelativePosition => (alienRelativePosition + aliensState.TopLeft) == rocketPosition);
                if (alienIndex != -1)
                {
                    collisions.Add(new Tuple <int, int>(alienIndex, rocketIndex));
                }
            }

            return(collisions);
        }
        private static AliensState CreateNewAliensState(int width, int height, int aliensWidth, int aliensHeight)
        {
            Vector2i        topLeft   = new Vector2i((width - aliensWidth) / 2, 0);
            List <Vector2i> positions = new List <Vector2i>();

            for (int y = 0; y < aliensHeight; y++)
            {
                for (int x = 0; x < aliensWidth; x++)
                {
                    positions.Add(new Vector2i(x, y));
                }
            }

            AliensState aliensState = new AliensState(topLeft, positions);

            return(aliensState);
        }
        public static void TickAliens(GameConfigState gameConfigState, AliensState aliensState, AliensMovementState aliensMovementState,
                                      out AliensState newAliensState, out AliensMovementState newAliensMovementState, out AliensFiringInput newAliensFiringInput)
        {
            Vector2i topLeft, bottomRight;

            aliensState.GetAbsoluteBoundingBox(out topLeft, out bottomRight);
            AliensMovementState.MovementDirection nextMovementDirection = ChooseNewAliensMovementDirection(gameConfigState, aliensMovementState, topLeft, bottomRight);

            Dictionary <AliensMovementState.MovementDirection, Vector2i> movementDirectionToDelta =
                new Dictionary <AliensMovementState.MovementDirection, Vector2i>
            {
                { AliensMovementState.MovementDirection.Left, new Vector2i(-1, 0) },
                { AliensMovementState.MovementDirection.Right, new Vector2i(1, 0) },
                { AliensMovementState.MovementDirection.Down, new Vector2i(0, 1) },
            };

            Vector2i movementDelta = movementDirectionToDelta[nextMovementDirection];

            newAliensState         = new AliensState(aliensState.TopLeft + movementDelta, aliensState.RelativePositions);
            newAliensMovementState = new AliensMovementState(nextMovementDirection);

            TickAliensFiring(aliensState, out newAliensFiringInput);
        }
        public static WorldState Tick(WorldState worldState, PlayerInput playerInput)
        {
            PlayerState newPlayerState = TickPlayer(worldState.GameConfigState, worldState.PlayerState, playerInput);

            AliensState         newAliensState;
            AliensMovementState newAliensMovementState;
            AliensFiringInput   newAliensFiringInput;

            bool createNewAliens = (worldState.AliensState.RelativePositions.Count == 0);

            if (createNewAliens)
            {
                newAliensState = CreateNewAliensState(worldState.GameConfigState.Width, worldState.GameConfigState.Height,
                                                      worldState.GameConfigState.AliensWidth, worldState.GameConfigState.AliensHeight);
                newAliensMovementState = new AliensMovementState(AliensMovementState.MovementDirection.Right);
                newAliensFiringInput   = new AliensFiringInput(false, 0);
            }
            else
            {
                TickAliens(worldState.GameConfigState, worldState.AliensState, worldState.AliensMovementState, out newAliensState, out newAliensMovementState, out newAliensFiringInput);
            }

            RocketsState newRocketsState = TickRockets(worldState.GameConfigState, worldState.RocketsState, worldState.PlayerState, playerInput);

            BombsState newBombsState = TickBombs(worldState.GameConfigState, worldState.BombsState, worldState.PlayerState, worldState.AliensState, newAliensFiringInput);

            List <Tuple <int, int> > alienRocketCollisions = FindAlienRocketCollisions(newAliensState, newRocketsState);
            List <int> playerBombCollisions = FindPlayerBombCollisions(worldState.GameConfigState, newBombsState, newPlayerState);

            AliensState  newAliensState2  = ResolveAlienCollisions(newAliensState, alienRocketCollisions);
            RocketsState newRocketsState2 = ResolveRocketCollisions(newRocketsState, alienRocketCollisions);

            GameProgressState newGameProgressState = TickGameProgress(worldState.GameConfigState, worldState.GameProgressState, newAliensState2, alienRocketCollisions.Count, playerBombCollisions.Count != 0);

            return(new WorldState(worldState.GameConfigState, newPlayerState, newAliensState2, newAliensMovementState, newRocketsState2, newBombsState, newGameProgressState));
        }
        public static GameProgressState TickGameProgress(GameConfigState gameConfigState, GameProgressState gameProgressState, AliensState aliensState, int aliensKilled, bool playerCollidedWithBomb)
        {
            Vector2i topLeft, bottomRight;

            aliensState.GetAbsoluteBoundingBox(out topLeft, out bottomRight);

            int  newScore    = gameProgressState.Score + aliensKilled;
            int  newLives    = Math.Max(gameProgressState.Lives - (playerCollidedWithBomb ? 1 : 0), 0);
            bool newGameOver = gameProgressState.GameOver || (newLives == 0 || (bottomRight.Y >= gameConfigState.Height));

            return(new GameProgressState(newScore, newLives, newGameOver));
        }
        public static BombsState TickBombs(GameConfigState gameConfigState, BombsState bombsState, PlayerState playerState, AliensState aliensState, AliensFiringInput aliensFiringInput)
        {
            List <Vector2i> newPositions = bombsState.Positions.Select(position => position + new Vector2i(0, 1)).Where(position => position.Y < gameConfigState.Height).ToList();

            if (aliensFiringInput.Fire)
            {
                newPositions.Add(aliensState.TopLeft + aliensState.RelativePositions[aliensFiringInput.AlienIndex]);
            }
            return(new BombsState(newPositions));
        }