void Spawn()
        {
            if (SpawnDelayTimer.IsDone || IsFirstSpawn)
            {
                // Increase the spawn delay every 5 waves
                if (WaveNr % 5 == 0)
                {
                    SpawnDelayTimer.TimeInMS += SPAWN_DELAY_INCREASE;
                }
                // Reset the spawn delay timer
                SpawnDelayTimer.Reset();

                if (WaveNr < 60 && !IsFirstSpawn)
                {
                    WaveNr++;
                    WaveNrSB.Remove(0, WaveNrSB.Length);
                    WaveNrSB.Append(WaveNr);
                    SpawnClearBonus();
                    NBombWasUsedThisWave = false;
                }
                IsFirstSpawn = false;

                #region Clean Gun and Enemy Pools
                CleanGunPools();
                StraightEnemyPool.CleanUp();
                SuiciderEnemyPool.CleanUp();
                ZigZagEnemyPool.CleanUp();
                ItemEnemyPool.CleanUp();
                DualMissile45Pool.CleanUp();
                BombardEnemyPool.CleanUp();
                #endregion

                #region Interest
                bool InterestWasReturned = false;
                foreach (Player p in Players)
                {
                    for (int i = 0; i < p.Interests.Count; i++)
                    {
                        p.Interests[i]--;
                        if (p.Interests[i] == 0)
                        {
                            p.Score += (int)(10000 * Maths.RandomNr(115, 130) / (float)100);
                            p.Interests.RemoveAt(i);
                            i--;
                            InterestWasReturned = true;
                        }
                    }
                }
                if (InterestWasReturned)
                {
                    Engine.Instance.Audio.PlaySound(AudioConstants.CoinDrop);
                }
                #endregion

                int spawnNr = Maths.RandomNr(1, 7 + WaveNr / 2);
                // Regular
                if (WaveNr <= 5 && spawnNr < 5)
                {
                    spawnNr = 5;
                }
                for (int i = 0; i < spawnNr; i++)
                {
                    StraightEnemy se = StraightEnemyPool.New();
                    se.Initialize(new Vector2(Maths.RandomNr(0, Engine.Instance.Width - 64), Maths.RandomNr(-512, -57)));
                    Entities.Add(se);
                }

                // Scrapstation
                if (ActiveScrapStation == null && WaveNr >= 12 && (Maths.Chance(10) || (ItemEnemy.LastWaveSpawn <= (WaveNr - 10))))
                {
                    SpawnScrapStation();
                }

                // Side
                if (WaveNr >= 10)
                {
                    spawnNr = Maths.RandomNr(0, (WaveNr / 10) + 1);
                    for (int i = 0; i < spawnNr; i++)
                    {
                        SideEnemy se = SideEnemyPool.New();
                        se.Initialize();
                        Entities.Add(se);
                    }
                }

                // Suicide
                if (WaveNr >= 20)
                {
                    spawnNr = Maths.RandomNr(0, (WaveNr / 3) - 5);
                    if (spawnNr > 7)
                    {
                        spawnNr = 7;
                    }
                    for (int i = 0; i < spawnNr; i++)
                    {
                        SuiciderEnemy se = SuiciderEnemyPool.New();
                        se.Initialize(new Vector2(Maths.RandomNr(0, Engine.Instance.Width - 35), Maths.RandomNr(-512, -64)));
                        Entities.Add(se);
                    }
                }

                // Bombard
                if (WaveNr / 3 > 5)
                {
                    spawnNr = Maths.RandomNr(0, (WaveNr / 3) - 5);
                    for (int i = 0; i < spawnNr; i++)
                    {
                        BombardEnemy be = BombardEnemyPool.New();
                        be.Initialize(new Vector2(Maths.RandomNr(0, Engine.Instance.Width - 60), Maths.RandomNr(-512, -64)));
                        Entities.Add(be);
                    }
                }

                // 45/M45 Missile
                if (WaveNr / 2 > 3)
                {
                    spawnNr = Maths.RandomNr(0, -3 + WaveNr / 2);
                    for (int i = 0; i < spawnNr; i++)
                    {
                        Dual45Enemy de45 = Dual45EnemyPool.New();
                        de45.Initialize(new Vector2(Maths.RandomNr(0, Engine.Instance.Width - 43), Maths.RandomNr(-512, -64)));
                        Entities.Add(de45);
                    }
                }

                // Item enemy
                for (int i = 0; i < 3; i++)
                {
                    if (Maths.Chance(5))
                    {
                        ItemEnemy.LastWaveSpawn = WaveNr;
                        ItemEnemy ie = ItemEnemyPool.New();
                        ie.Initialize(new Vector2(Maths.RandomNr(0, Engine.Instance.Width - 48), Maths.RandomNr(-512, -112)));
                        Entities.Add(ie);
                    }
                }

                // Zigzag
                if (WaveNr / 2 > 3)
                {
                    spawnNr = Maths.RandomNr(0, -3 + WaveNr / 2);
                    for (int i = 0; i < spawnNr; i++)
                    {
                        ZigZagEnemy zze = ZigZagEnemyPool.New();
                        zze.Initialize(new Vector2(Maths.RandomNr(0, Engine.Instance.Width - 57), Maths.RandomNr(-256, -64)));
                        Entities.Add(zze);
                    }
                }
            }
        }
        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();
        }