/// <summary> /// Updates the <see cref="ParticleEmitter"/> and all <see cref="Particle"/>s it has created. /// </summary> /// <param name="currentTime">The current time.</param>> internal void Update(TickCount currentTime) { var forceEmit = false; // Get the elapsed time // On the first update, just assume 33 ms have elapsed int elapsedTime; if (_lastUpdateTime == TickCount.MinValue) { // This is the very first update forceEmit = true; _nextReleaseTime = currentTime; elapsedTime = 33; } else { // Not the first update elapsedTime = (int)Math.Min(MaxDeltaTime, currentTime - _lastUpdateTime); } _lastUpdateTime = currentTime; // Update the emitter modifiers EmitterModifiers.ProcessEmitter(this, elapsedTime); // Check if the sprite is loaded if (Sprite == null || Sprite.GrhData == null) { EmitterModifiers.RestoreEmitter(this); return; } // Update the current time on the modifiers ParticleModifiers.UpdateCurrentTime(currentTime); // Update the sprite Sprite.Update(currentTime); // Check to spawn more particles if (forceEmit || (RemainingLife != 0 && ReleaseAmount.Max > 0 && ReleaseRate.Max > 0)) { // Do not allow the releasing catch-up time to exceed the _maxDeltaTime if (_nextReleaseTime < currentTime - MaxDeltaTime) { _nextReleaseTime = currentTime - MaxDeltaTime; } // Keep calculating the releases until we catch up to the current time var amountToRelease = 0; while (_nextReleaseTime <= currentTime) { amountToRelease += ReleaseAmount.GetNext(); _nextReleaseTime += ReleaseRate.GetNext(); } // Release the particles, if there are any if (amountToRelease > 0) { ReleaseParticles(currentTime, amountToRelease); } } else { // Set the next release time to now so that if the emitter starts releasing, it won't release a ton // as it catches back up _nextReleaseTime = currentTime - MaxDeltaTime; } // Update the particles var hasUpdateModifiers = ParticleModifiers.HasUpdateModifiers; var i = 0; Vector2 minParticlePosition = Vector2.Zero; Vector2 maxParticlePosition = Vector2.Zero; Vector2 spriteSize = Sprite.Size; while (i <= _lastAliveIndex) { var particle = _particles[i]; // Check if the particle has expired if (particle.LifeEnd <= currentTime) { // We do NOT increment because once we expire the particle, this slot will become in use by // another particle, so we will have to update at this index again ExpireParticle(i); continue; } // Process the particle with the modifiers if (hasUpdateModifiers) { ParticleModifiers.ProcessUpdatedParticle(this, particle, elapsedTime); } // Update the particle particle.Update(elapsedTime); // Update the min/max origin offsets Vector2 posMin = particle.Position; Vector2 particleSize; Vector2.Multiply(ref spriteSize, particle.Scale, out particleSize); Vector2 posMax; Vector2.Add(ref posMin, ref particleSize, out posMax); if (posMin.X < minParticlePosition.X) { minParticlePosition.X = posMin.X; } if (posMin.Y < minParticlePosition.Y) { minParticlePosition.Y = posMin.Y; } if (posMax.X > maxParticlePosition.X) { maxParticlePosition.X = posMax.X; } if (posMax.Y > maxParticlePosition.Y) { maxParticlePosition.Y = posMax.Y; } ++i; } _minParticlePosition = minParticlePosition; _maxParticlePosition = maxParticlePosition; EmitterModifiers.RestoreEmitter(this); }