/// <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); } }