/// <summary> /// Releases one or more particles. /// </summary> /// <param name="currentTime">The current time.</param> /// <param name="amount">The number of particles to release.</param> void ReleaseParticles(TickCount currentTime, int amount) { // Find how many we can actually release var lastIndex = Math.Min(Budget - 1, _lastAliveIndex + amount); // Ensure our particles array is large enough to fit the new particles. // When we resize the array, we use the "next power of two" sizing concept to reduce the // memory fragmentation (.NET internally does the same with most collections). To speed things up, // we just find the next power of two instead of looping until we have a large enough value. if (_particles.Length - 1 < lastIndex) { var newSize = BitOps.NextPowerOf2(lastIndex + 1); Debug.Assert(BitOps.IsPowerOf2(newSize), "If this assert fails, something is probably wrong with BitOps.NextPowerOf2() or BitOps.IsPowerOf2()."); Debug.Assert(newSize >= lastIndex + 1); Array.Resize(ref _particles, newSize); } // Start releasing the particles var hasReleaseModifiers = ParticleModifiers.HasReleaseModifiers; for (var i = _lastAliveIndex + 1; i <= lastIndex; i++) { var particle = _particles[i]; if (particle == null) { particle = Particle.Create(); _particles[i] = particle; } // Set up the particle particle.Momentum = Vector2.Zero; particle.LifeStart = currentTime; particle.LifeEnd = (TickCount)(currentTime + ParticleLife.GetNext()); particle.Rotation = ReleaseRotation.GetNext(); particle.Scale = ReleaseScale.GetNext(); ReleaseColor.GetNext(ref particle.Color); // Get the offset and force Vector2 offset; Vector2 force; GenerateParticleOffsetAndForce(particle, out offset, out force); // Set the position Vector2.Add(ref _origin, ref offset, out particle.Position); // Set the velocity Vector2.Multiply(ref force, ReleaseSpeed.GetNext(), out particle.Velocity); if (hasReleaseModifiers) { ParticleModifiers.ProcessReleasedParticle(this, particle); } } // Increase the index of the last active particle _lastAliveIndex = lastIndex; }