public void AddParticles(Vector2 pos, int count)
        {
            Particles.Clear();

            CurrentAliveParticleCount += count;

            for (int i = 0; i < count; i++)
            {
                Particle p = new Particle();

                // first, call PickRandomDirection to figure out which way the particle
                // will be moving. velocity and acceleration's values will come from this.
                Vector2 direction = Utilitys.PickRandomDirection();

                // pick some random values for our particle
                float velocity      = Utilitys.RandomBetween(MinInitialSpeed, MaxInitialSpeed);
                float acceleration  = Utilitys.RandomBetween(MinAcceleration, MaxAcceleration);
                float lifetime      = Utilitys.RandomBetween(MinLifeSpan, MaxLifeSpan);
                float scale         = Utilitys.RandomBetween(MinScale, MaxScale);
                float rotationSpeed = Utilitys.RandomBetween(MinRotationSpeed, MaxRotationSpeed);

                // then initialize it with those random values. initialize will save those,
                // and make sure it is marked as active.
                p.Initialize(pos, velocity * direction, acceleration * direction, lifetime, scale, rotationSpeed);

                freeParticles.Enqueue(p);
                Particles.Add(p);
            }
        }
        public override void Initialize()
        {
            base.Initialize();

            Particles     = new List <Particle>(MaxParticles);
            freeParticles = new Queue <Particle>(MaxParticles);

            for (int i = 0; i < MinParticles; i++)
            {
                Particle part = new Particle();
                part.Color   = ParticleColor;
                part.Texture = Texture;

                // first, call PickRandomDirection to figure out which way the particle
                // will be moving. velocity and acceleration's values will come from this.
                Vector2 direction = Utilitys.PickRandomDirection();

                // pick some random values for our particle
                float velocity      = Utilitys.RandomBetween(MinInitialSpeed, MaxInitialSpeed);
                float acceleration  = Utilitys.RandomBetween(MinAcceleration, MaxAcceleration);
                float lifeSpan      = Utilitys.RandomBetween(MinLifeSpan, MaxLifeSpan);
                float scale         = Utilitys.RandomBetween(MinScale, MaxScale);
                float rotationSpeed = Utilitys.RandomBetween(MinRotationSpeed, MaxRotationSpeed);

                // then initialize it with those random values. initialize will save those,
                // and make sure it is marked as active.
                part.Initialize(Position, velocity * direction, acceleration * direction, lifeSpan, scale, rotationSpeed);

                // Enqueue it in our free particles queue
                freeParticles.Enqueue(part);

                // Load it to our particles collection
                Particles.Add(part);

                if (OnParticleSpawningEvent != null)
                {
                    OnParticleSpawningEvent.Invoke(part);
                }
            }

            // Debug Bounding Box Renderer
            BoundingBoxRenderer = new BoundingBoxRenderer(Game);
            BoundingBoxRenderer.Initialize();
        }
        public override void Update(GameTime gameTime)
        {
            if (!Enabled)
            {
                return;
            }

            // Allow for a delayed start time (fireworks for instance or random flames)
            if (currentElapsedTime > DelayedStartTime)
            {
                // Show our particles
                Visible = true;

                // calculate dt, the change in the since the last frame. the particle updates will use this value.
                float dt = (float)gameTime.ElapsedGameTime.TotalSeconds * 0.33f;

                #region Pathing Nodes

                if (AttachedPathingNode != null && AttachedPathingNode.Nodes.Count > 0)
                {
                    //Effects = AttachedPathingNode.Nodes[CurrentPathNodeIndex].SpriteEffect;

                    // Update our draw order to be the same as the current node we are on
                    if (AttachedPathingNode.UseNodesDrawOrder)
                    {
                        DrawOrder = AttachedPathingNode.Nodes[CurrentPathNodeIndex].DrawOrder;
                    }

                    if (CurrentPathNodeIndex <= (AttachedPathingNode.Nodes.Count - 1))
                    {
                        if (AttachedPathingNode.IsTraveling)
                        {
                            // Lerp to our next node
                            CurrentPathLerpPosition += (AttachedPathingNode.Nodes[CurrentPathNodeIndex].TravelSpeed * dt);
                        }

                        if (CurrentPathLerpPosition >= 1)
                        {
                            if (IsLerpingBackToFirstNode)
                            {
                                CurrentPathNodeIndex--;
                                CurrentPathLerpPosition = 0;
                            }
                            else
                            {
                                if (CurrentPathNodeIndex < (AttachedPathingNode.Nodes.Count - 1))
                                {
                                    if (AttachedPathingNode.Nodes[CurrentPathNodeIndex].RespawnDelay > TimeSpan.Zero)
                                    {
                                        if (AttachedPathingNode.Nodes[CurrentPathNodeIndex].NodeElapsedTime >
                                            AttachedPathingNode.Nodes[CurrentPathNodeIndex].RespawnDelay)
                                        {
                                            // purge the last node elapsed time
                                            AttachedPathingNode.Nodes[CurrentPathNodeIndex].NodeElapsedTime = TimeSpan.Zero;

                                            AttachedPathingNode.IsTraveling = true;

                                            CurrentPathNodeIndex++;
                                            CurrentPathLerpPosition = 0;
                                        }
                                        else
                                        {
                                            AttachedPathingNode.IsTraveling = false;
                                            CurrentPathLerpPosition         = 1;
                                            AttachedPathingNode.Nodes[CurrentPathNodeIndex].NodeElapsedTime += gameTime.ElapsedGameTime;
                                        }
                                    }
                                    else
                                    {
                                        CurrentPathNodeIndex++;
                                        CurrentPathLerpPosition = 0;
                                    }
                                }
                            }
                        }

                        // Check to see we are on the last node in the chain
                        if (CurrentPathNodeIndex == (AttachedPathingNode.Nodes.Count - 1) && !IsLerpingBackToFirstNode && AttachedPathingNode.IsTraveling)
                        {
                            CurrentPathLerpPosition = 0;

                            // we want to respawn back to the first so reset everything
                            switch (AttachedPathingNode.LedgeTavelAlgo)
                            {
                            case LedgeTravelAlgo.RespawnAtFirstNode:
                                CurrentPathNodeIndex = 0;
                                break;

                            case LedgeTravelAlgo.LerpToFirstNode:
                                IsLerpingBackToFirstNode = true;
                                break;

                            case LedgeTravelAlgo.StopAtLastNode:
                                AttachedPathingNode.IsTraveling = false;
                                break;
                            }
                        }
                        else if (CurrentPathNodeIndex == 0 && IsLerpingBackToFirstNode)
                        {
                            IsLerpingBackToFirstNode = false;
                            CurrentPathLerpPosition  = 0;
                        }
                        else
                        {
                            // Continue to move along the path
                            if (IsLerpingBackToFirstNode)
                            {
                                // Lerping Rotation Calculation ** value1 + (value2 - value1) * amount **
                                float n1 = AttachedPathingNode.Nodes[CurrentPathNodeIndex - 1].Rotation;
                                float n2 = AttachedPathingNode.Nodes[CurrentPathNodeIndex].Rotation;
                                Rotation = n1 + (n2 - n1) * CurrentPathLerpPosition;

                                // Moving Back towards the last node
                                Position = Vector2.Lerp(AttachedPathingNode.Nodes[CurrentPathNodeIndex].Position,
                                                        AttachedPathingNode.Nodes[CurrentPathNodeIndex - 1].Position,
                                                        CurrentPathLerpPosition);

                                // Scaling
                                Scale = Vector2.Lerp(AttachedPathingNode.Nodes[CurrentPathNodeIndex].Scale,
                                                     AttachedPathingNode.Nodes[CurrentPathNodeIndex - 1].Scale, CurrentPathLerpPosition);
                            }
                            else
                            {
                                if ((CurrentPathNodeIndex + 1) <= (AttachedPathingNode.Nodes.Count - 1))
                                {
                                    // Lerping Rotation Calculation ** value1 + (value2 - value1) * amount **
                                    float n1 = AttachedPathingNode.Nodes[CurrentPathNodeIndex].Rotation;
                                    float n2 = AttachedPathingNode.Nodes[CurrentPathNodeIndex + 1].Rotation;
                                    Rotation = n1 + (n2 - n1) * CurrentPathLerpPosition;


                                    // Moving
                                    Position = Vector2.Lerp(AttachedPathingNode.Nodes[CurrentPathNodeIndex].Position,
                                                            AttachedPathingNode.Nodes[CurrentPathNodeIndex + 1].Position,
                                                            CurrentPathLerpPosition);

                                    // Scaling
                                    Scale = Vector2.Lerp(AttachedPathingNode.Nodes[CurrentPathNodeIndex].Scale,
                                                         AttachedPathingNode.Nodes[CurrentPathNodeIndex + 1].Scale, CurrentPathLerpPosition);
                                }
                            }
                        }
                    }
                }

                #endregion

                #region Forces

                // apply force objects
                foreach (Vector2 force in ForceObjects)
                {
                    foreach (Particle p in Particles)
                    {
                        p.Position += force;
                    }
                }

                #endregion

                if (Origin == Vector2.Zero && Texture != null)
                {
                    Origin = new Vector2((float)Texture.Width / 2, (float)Texture.Height / 2);
                }

                // go through all of the particles...
                foreach (Particle p in Particles)
                {
                    p.Update(dt);

                    if (!p.Active)
                    {
                        if (!RespawnParticles)
                        {
                            CurrentAliveParticleCount--;

                            if (CurrentAliveParticleCount < 0)
                            {
                                CurrentAliveParticleCount = 0;
                            }

                            continue;
                        }

                        Particle part = freeParticles.Dequeue();
                        part.Color   = ParticleColor;
                        part.Texture = Texture;

                        // first, call PickRandomDirection to figure out which way the particle
                        // will be moving. velocity and acceleration's values will come from this.
                        Vector2 direction = Utilitys.PickRandomDirection();

                        // pick some random values for our particle
                        float velocity      = Utilitys.RandomBetween(MinInitialSpeed, MaxInitialSpeed);
                        float acceleration  = Utilitys.RandomBetween(MinAcceleration, MaxAcceleration);
                        float lifetime      = Utilitys.RandomBetween(MinLifeSpan, MaxLifeSpan);
                        float scale         = Utilitys.RandomBetween(MinScale, MaxScale);
                        float rotationSpeed = Utilitys.RandomBetween(MinRotationSpeed, MaxRotationSpeed);

                        // Init our particle with new values
                        part.Initialize(Position, velocity * direction, acceleration * direction, lifetime, scale, rotationSpeed);

                        CurrentAliveParticleCount++;

                        freeParticles.Enqueue(part);

                        if (OnParticleSpawningEvent != null)
                        {
                            OnParticleSpawningEvent.Invoke(part);
                        }
                    }
                }

                if (ShowBoundingBox && Texture != null && Enabled)
                {
                    // Update our Bounding Box around our picker
                    Vector3[] points = new Vector3[2];
                    points[0] = new Vector3((Position.X + CameraOffsetX) - (Texture.Width * MaxScale) / 2,
                                            Position.Y + CameraOffsetY - (Texture.Height * MaxScale) / 2, -1);

                    points[1] = new Vector3((Position.X + CameraOffsetX) + (Texture.Width * MaxScale) / 2,
                                            (Position.Y + CameraOffsetY) + (Texture.Height * MaxScale) / 2, -1);

                    BoundingBox = BoundingBox.CreateFromPoints(points);

                    // Update the Bounding Box Renderer
                    BoundingBoxRenderer.ShowBoundingBox = ShowBoundingBox;
                    BoundingBoxRenderer.BoundingBox     = BoundingBox;

                    BoundingBoxRenderer.Update(gameTime);
                }

                base.Update(gameTime);
            }
            else
            {
                // Make sure we hide it
                Visible = false;

                // Increase our elapsed run time
                currentElapsedTime += gameTime.ElapsedGameTime;
            }
        }