Esempio n. 1
0
        /// <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);
        }