public void LaunchNuclearBomb(PlayerShip ship)
        {
            NBombWasUsedThisWave = true;

            for (int i = 0; i < Entities.Count; i++)
            {
                BaseEnemy e = Entities[i] as BaseEnemy;
                if (e != null)
                {
                    if (e.Location.Y + e.AABB.Height > 0)
                    {
                        e.TakeDamage(999, ship.Owner);
                    }
                }
            }
            ABH.Reset();
        }
        public void Visit(PlayerShip pShip)
        {
            if (Location.X < Engine.Instance.Width / 2)
            {
                VelocityX = -1.5f;
            }
            else
            {
                VelocityX = 1.5f;
            }

            VelocityY = 9f;

            Engine.Instance.ActiveState = new Shop(pShip.Owner);
            Shop.IsFirstVisit           = false;
            IsGoingHome = true;
        }
        void PickupWeapon(PlayerShip pShip, eEnemyGunType gunType)
        {
            BaseGun wpn = pShip.GetGun(gunType);

            if (wpn != null)
            {
                if (wpn.CanUpgradeTier)
                {
                    wpn.UpgradeTier();
                    pShip.UpdateAquiredGuns(); // This is needed to set the background box from green to purple.
                }
                else
                {
                    pShip.Heal(DOUBLE_PICKUP_HEAL_AMOUNT);
                }
            }
            else
            {
                pShip.AddGun(gunType);
            }
        }
        void HandleCollision()
        {
            #region Pickups
            foreach (PlayerShip pShip in PlayerShips)
            {
                for (int i = 0; i < Pickups.Count; i++)
                {
                    if (pShip.AABB.Intersects(new Rectangle(Pickups[i].Location.Xi(), Pickups[i].Location.Yi(), 32, 32)))
                    {
                        switch (Pickups[i].PickupType)
                        {
                        case ePickupType.HP:
                            pShip.Heal(65);
                            break;

                        case ePickupType.Boom1:
                            PickupWeapon(pShip, eEnemyGunType.Boom1Enemy);
                            break;

                        case ePickupType.Aim:
                            PickupWeapon(pShip, eEnemyGunType.AutoAim);
                            break;

                        case ePickupType.Missile:
                            PickupWeapon(pShip, eEnemyGunType.Missile);
                            break;

                        case ePickupType.Speed:
                            if (!pShip.UpgradeSpeed())
                            {
                                pShip.Heal(DOUBLE_PICKUP_HEAL_AMOUNT);
                            }
                            break;

                        case ePickupType.Shield:
                            if (!pShip.UpgradeShield())
                            {
                                pShip.Heal(DOUBLE_PICKUP_HEAL_AMOUNT);
                            }
                            pShip.Shield.CurrentHP += 7;
                            break;

                        case ePickupType.DualMissile:
                            PickupWeapon(pShip, eEnemyGunType.DualMissile45);
                            break;

                        case ePickupType.ShieldRegen:
                            if (!pShip.UpgradeShieldRegen())
                            {
                                pShip.Heal(DOUBLE_PICKUP_HEAL_AMOUNT);
                            }
                            break;

                        default:
                            throw new NotImplementedException();
                        }

                        Pickups[i].IsDisposed = true;
                        pShip.Owner.Score    += (int)((5 + WaveNr) * Level.Instance.ScoreModifier);
                    }
                }
            }
            #endregion

            #region Scrapstation
            if (ActiveScrapStation != null && !ActiveScrapStation.IsGoingHome)
            {
                if (PlayerShips[0].AABB.Intersects(ActiveScrapStation.AABB))
                {
                    foreach (Rectangle2 rect in PlayerShips[0].CollisionRects)
                    {
                        foreach (Rectangle2 rect2 in ActiveScrapStation.CollisionRects)
                        {
                            if (rect.Absolute.Intersects(rect2.Absolute))
                            {
                                ActiveScrapStation.Visit(PlayerShips[0]);
                                return;
                            }
                        }
                    }
                }
            }
            #endregion

            #region Other Collisions
            // A note about the 'is' operator performance: http://stackoverflow.com/questions/686412/c-is-operator-performance
            for (int y = 0; y < BroadPhase.GRID_CNT; y++)
            {
                for (int x = 0; x < BroadPhase.GRID_CNT; x++)
                {
                    if (BroadPhase.Instance.Blocks[x, y].Entities.Count > 0)
                    {
                        for (int i = 0; i < BroadPhase.Instance.Blocks[x, y].Entities.Count; i++)
                        {
                            PlayerShip pShip = BroadPhase.Instance.Blocks[x, y].Entities[i] as PlayerShip;
                            if (pShip != null)
                            {
                                for (int j = 0; j < BroadPhase.Instance.Blocks[x, y].Entities.Count; j++)
                                {
                                    // Player <--> enemy projectile
                                    BaseProjectile p = BroadPhase.Instance.Blocks[x, y].Entities[j] as BaseProjectile;
                                    if (p != null)
                                    {
                                        if (p.Owner == null && !p.IsDisposed && pShip.AABB.Intersects(BroadPhase.Instance.Blocks[x, y].Entities[j].AABB))
                                        {
                                            foreach (Rectangle2 rect in pShip.CollisionRects)
                                            {
                                                if (p.AABB.Intersects(rect.Absolute))
                                                {
                                                    pShip.TakeDamage(p.Damage);
                                                    p.IsDisposed = true;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                    // Player <--> enemy collision
                                    else
                                    {
                                        BaseEnemy e = BroadPhase.Instance.Blocks[x, y].Entities[j] as BaseEnemy;
                                        if (e != null)
                                        {
                                            if (!e.IsDisposed && pShip.AABB.Intersects(e.AABB))
                                            {
                                                foreach (Rectangle2 rect in pShip.CollisionRects)
                                                {
                                                    if (e.AABB.Intersects(rect.Absolute))
                                                    {
                                                        pShip.TakeDamage(e.CollisionDamage);
                                                        pShip.Owner.Kills++;
                                                        e.Die();
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            // enemy <--> player projectile
                            else if (BroadPhase.Instance.Blocks[x, y].Entities[i] is BaseEnemy)
                            {
                                BaseEnemy e = (BaseEnemy)BroadPhase.Instance.Blocks[x, y].Entities[i];

                                for (int j = 0; j < BroadPhase.Instance.Blocks[x, y].Entities.Count; j++)
                                {
                                    BaseProjectile p = BroadPhase.Instance.Blocks[x, y].Entities[j] as BaseProjectile;
                                    if (p != null)
                                    {
                                        if (p.Owner != null && e.AABB.Intersects(p.AABB) && !p.IsDisposed)
                                        {
                                            e.TakeDamage(p.Damage, p.Owner);
                                            p.IsDisposed = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            #endregion
        }
        public Level(int startingWave, int dropRateModifier, int waveDelayInMS, int area, float scoreModifier, string music, ePlaneType planeType, string shipName)
        {
            // Music
            Music = music;
            MP3MusicMgr.Instance.PlayMusic(music);

            ScoreModifier           = scoreModifier;
            WaveNr                  = startingWave;
            ItemEnemy.LastWaveSpawn = WaveNr;
            DropRateModifier        = dropRateModifier;
            SpawnDelayTimer         = new SimpleTimer(waveDelayInMS);
            ScrollBG                = new ScrollBG("bg0" + area.ToString());
            Shop.IsFirstVisit       = true;
            if (area == 3 || area == 4)
            {
                MG1.MGDrawColor = Color.DarkRed;
                MG2.MGDrawColor = Color.DarkBlue;
            }
            else
            {
                MG1.MGDrawColor = MG2.MGDrawColor = Color.White;
            }
            WaveNrSB = new StringBuilder(startingWave.ToString(), 2);

            BroadPhase.Instance = new BroadPhase(128);
            BroadPhase.Instance.Init();

            Level.Instance = this;
            #region Generic Pools
            MGPool            = new Pool <MG1>(25, true, g => !g.IsDisposed, () => MG1.PoolConstructor());
            MG2Pool           = new Pool <MG2>(1, true, g => !g.IsDisposed, () => MG2.PoolConstructor());
            AutoAimPool       = new Pool <AutoAim>(100, true, g => !g.IsDisposed, () => AutoAim.PoolConstructor());
            BoomPool          = new Pool <Boom1>(100, true, g => !g.IsDisposed, () => Boom1.PoolConstructor());
            MissilePool       = new Pool <Missile>(80, true, g => !g.IsDisposed, () => Missile.PoolConstructor());
            DualMissile45Pool = new Pool <DualMissile45>(80, true, g => !g.IsDisposed, () => DualMissile45.PoolConstructor());
            // Enemies
            StraightEnemyPool = new Pool <StraightEnemy>(200, true, e => !e.IsDisposed, () => StraightEnemy.PoolConstructor());
            SuiciderEnemyPool = new Pool <SuiciderEnemy>(60, true, e => !e.IsDisposed, () => SuiciderEnemy.PoolConstructor());
            ItemEnemyPool     = new Pool <ItemEnemy>(10, true, e => !e.IsDisposed, () => ItemEnemy.PoolConstructor());
            ZigZagEnemyPool   = new Pool <ZigZagEnemy>(130, true, e => !e.IsDisposed, () => ZigZagEnemy.PoolConstructor());
            BombardEnemyPool  = new Pool <BombardEnemy>(60, true, e => !e.IsDisposed, () => BombardEnemy.PoolConstructor());
            Dual45EnemyPool   = new Pool <Dual45Enemy>(60, true, e => !e.IsDisposed, () => Dual45Enemy.PoolConstructor());
            SideEnemyPool     = new Pool <SideEnemy>(10, true, e => !e.IsDisposed, () => SideEnemy.PoolConstructor());
            // Explosions
            ExplosionPool = new Pool <Visual>(100, true, v => !v.IsDisposed, () => Visual.PoolConstructor());
            // Scrap station
            ScrapStationPool = new Pool <ScrapStation>(2, true, s => !s.IsDisposed, () => ScrapStation.PoolConstructor());
            #endregion

            Players.Add(new Player());

            // Projectile pool
            for (int i = 0; i < PROJECTILE_POOL_MAX; i++)
            {
                ProjectilePool.Add(new BaseProjectile());
            }

            // Pickup pool
            for (int i = 0; i < PICKUP_MAX; i++)
            {
                PickupPool.Add(new Pickup());
            }

            // Increase the spawn delay every 5 waves
            int spawnDelayIncs = WaveNr / 5;
            for (int i = 0; i < spawnDelayIncs; i++)
            {
                SpawnDelayTimer.TimeInMS += SPAWN_DELAY_INCREASE;
            }

            // Add starting resources
            for (int i = 1; i <= startingWave; i++)
            {
                if (i < 5)
                {
                    for (int j = 0; j < Players.Count; j++)
                    {
                        Players[j].Score += 150;
                    }
                }
                else
                {
                    for (int j = 0; j < Players.Count; j++)
                    {
                        Players[j].Score += 500;
                    }
                }
                // Limit score to ~15000
                if (Players[0].Score >= 15000)
                {
                    break;
                }
            }

            // Spawn scrap station if starting wave # >=20
            if (startingWave >= 20)
            {
                SpawnScrapStation();
            }

            #region Player
            PlayerShip ps = new PlayerShip(PlayerIndex.One, new Vector2(500, 400), Players[0]);
            ps.SetPlaneType(planeType, shipName);

            // Bonus speed & shield regen
            int bonusSpeedUpgrades = startingWave / 10;
            for (int i = 0; i < bonusSpeedUpgrades; i++)
            {
                ps.UpgradeSpeed();
                ps.UpgradeShieldRegen();
            }
            // Add mg
            MG1 mg = MGPool.New();
            mg.Initialize(new Vector2(5, ps.Height - 20), new Vector2(ps.Width - 5 - 8, ps.Height - 20), ps.Owner);
            ps.Guns.Add(mg);

            Entities.Add(ps);
            PlayerShips.Add(ps);
            #endregion

            // Pause
            PauseLocation = Common.CenterString(PausedFont, PAUSE_TEXT, Engine.Instance.Width, Engine.Instance.Height);

            // Collect Garbage
            System.GC.Collect();
        }