/// <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; }
/// <summary> /// When overridden in the derived class, handles processing the <paramref name="particle"/> when /// it is updated. Only valid if <see cref="ParticleModifier.ProcessOnUpdate"/> is set. /// </summary> /// <param name="emitter">The <see cref="ParticleEmitter"/> that the <paramref name="particle"/> /// came from.</param> /// <param name="particle">The <see cref="Particle"/> to process.</param> /// <param name="elapsedTime">The amount of time that has elapsed since the <paramref name="emitter"/> /// was last updated.</param> protected override void HandleProcessUpdated(ParticleEmitter emitter, Particle particle, int elapsedTime) { var agePercent = particle.GetAgePercent(CurrentTime); if (AllBitsSet()) { particle.Color = ReleaseColor.Lerp(UltimateColor, agePercent); } else { byte r, g, b, a; if (ModifyRed) { r = (byte)MathHelper.Lerp(ReleaseColor.R, UltimateColor.R, agePercent); } else { r = particle.Color.R; } if (ModifyGreen) { g = (byte)MathHelper.Lerp(ReleaseColor.G, UltimateColor.G, agePercent); } else { g = particle.Color.G; } if (ModifyBlue) { b = (byte)MathHelper.Lerp(ReleaseColor.B, UltimateColor.B, agePercent); } else { b = particle.Color.B; } if (ModifyAlpha) { a = (byte)MathHelper.Lerp(ReleaseColor.A, UltimateColor.A, agePercent); } else { a = particle.Color.A; } particle.Color = new Color(r, g, b, a); } }