/// <summary>
        /// InitializeParticle randomizes some properties for a particle, then
        /// calls initialize on it. It can be overriden by subclasses if they 
        /// want to modify the way particles are created. For example, 
        /// SmokePlumeParticleSystem overrides this function make all particles
        /// accelerate to the right, simulating wind.
        /// </summary>
        /// <param name="p">the particle to initialize</param>
        /// <param name="where">the position on the screen that the particle should be
        /// </param>
        /// <param name="velocity">The base velocity that the particle should have</param>
        private void InitializeParticle(Particle p, Vector2 where, Vector2 velocity)
        {
            // Adjust the input velocity based on how much
            // this particle system wants to be affected by it.
            velocity *= settings.EmitterVelocitySensitivity;

            // Adjust the velocity based on our random values
            Vector2 direction = PickRandomDirection();
            float speed = ParticleHelpers.RandomBetween(settings.MinInitialSpeed, settings.MaxInitialSpeed);
            velocity += direction * speed;

            // pick some random values for our particle
            float lifetime =
                ParticleHelpers.RandomBetween(settings.MinLifetime, settings.MaxLifetime);
            float scale =
                ParticleHelpers.RandomBetween(settings.MinSize, settings.MaxSize);
            float rotationSpeed =
                ParticleHelpers.RandomBetween(settings.MinRotationSpeed, settings.MaxRotationSpeed);

            // our settings angles are in degrees, so we must convert to radians
            rotationSpeed = MathHelper.ToRadians(rotationSpeed);

            // figure out our acceleration base on our AccelerationMode
            Vector2 acceleration = Vector2.Zero;
            switch (settings.AccelerationMode)
            {
                case AccelerationMode.Scalar:
                    // randomly pick our acceleration using our direction and
                    // the MinAcceleration/MaxAcceleration values
                    float accelerationScale = ParticleHelpers.RandomBetween(
                        settings.MinAccelerationScale, settings.MaxAccelerationScale);
                    acceleration = direction * accelerationScale;
                    break;
                case AccelerationMode.EndVelocity:
                    // Compute our acceleration based on our ending velocity from the settings.
                    // We'll use the equation vt = v0 + (a0 * t). (If you're not familar with
                    // this, it's one of the basic kinematics equations for constant
                    // acceleration, and basically says:
                    // velocity at time t = initial velocity + acceleration * t)
                    // We're solving for a0 by substituting t for our lifetime, v0 for our
                    // velocity, and vt as velocity * settings.EndVelocity.
                    acceleration = (velocity * (settings.EndVelocity - 1)) / lifetime;
                    break;
                case AccelerationMode.Vector:
                    acceleration = new Vector2(
                        ParticleHelpers.RandomBetween(settings.MinAccelerationVector.X, settings.MaxAccelerationVector.X),
                        ParticleHelpers.RandomBetween(settings.MinAccelerationVector.Y, settings.MaxAccelerationVector.Y));
                    break;
                default:
                    break;
            }

            // then initialize it with those random values. initialize will save those,
            // and make sure it is marked as active.
            p.Initialize(
                where,
                velocity,
                acceleration,
                lifetime,
                scale,
                rotationSpeed);
        }
        /// <summary>
        /// AddParticles's job is to add an effect somewhere on the screen. If there 
        /// aren't enough particles in the freeParticles queue, it will use as many as 
        /// it can. This means that if there not enough particles available, calling
        /// AddParticles will have no effect.
        /// </summary>
        /// <param name="where">Where the particle effect should be created</param>
        /// <param name="velocity">A base velocity for all particles. This is weighted 
        /// by the EmitterVelocitySensitivity specified in the settings for the 
        /// particle system.</param>
        public void AddParticles(Vector2 where, Vector2 velocity)
        {
            // the number of particles we want for this effect is a random number
            // somewhere between the two constants specified by the settings.
            int numParticles =
                ParticleHelpers.Random.Next(settings.MinNumParticles, settings.MaxNumParticles);

            // create that many particles, if you can.
            for (int i = 0; i < numParticles; i++)
            {
                // if we're out of free particles, we allocate another ten particles
                // which should keep us going.
                if (freeParticles.Count == 0)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        Particle newParticle = new Particle();
                        particles.Add(newParticle);
                        freeParticles.Enqueue(newParticle);
                    }
                }

                // grab a particle from the freeParticles queue, and Initialize it.
                Particle p = freeParticles.Dequeue();
                InitializeParticle(p, where, velocity);
            }
        }