private bool UpdateParticle(ref CCParticle p, float dt)
        {
            // life
            p.timeToLive -= dt;

            if (p.timeToLive > 0)
            {
                // Mode A: gravity, direction, tangential accel & radial accel
                if (m_nEmitterMode == CCEmitterMode.Gravity)
                {
                    float radial_x = 0;
                    float radial_y = 0;

                    float tmp_x, tmp_y;
                    float tangential_x, tangential_y;

                    float x = p.pos.X;
                    float y = p.pos.Y;

                    if (x != 0 || y != 0)
                    {
                        float l = 1.0f / (float)Math.Sqrt(x * x + y * y);

                        radial_x = x * l;
                        radial_y = y * l;
                    }
                    tangential_x = radial_x;
                    tangential_y = radial_y;

                    //radial = CCPoint.ccpMult(radial, p.modeA.radialAccel);
                    radial_x *= p.modeA.radialAccel;
                    radial_y *= p.modeA.radialAccel;


                    // tangential acceleration
                    float newy = tangential_x;
                    tangential_x = -tangential_y;
                    tangential_y = newy;
                    //tangential = CCPoint.ccpMult(tangential, p.modeA.tangentialAccel);
                    tangential_x *= p.modeA.tangentialAccel;
                    tangential_y *= p.modeA.tangentialAccel;

                    // (gravity + radial + tangential) * dt
                    //tmp = CCPoint.ccpAdd(CCPoint.ccpAdd(radial, tangential), modeA.gravity);
                    //tmp = CCPoint.ccpMult(tmp, dt);
                    //p.modeA.dir = CCPoint.ccpAdd(p.modeA.dir, tmp);
                    //tmp = CCPoint.ccpMult(p.modeA.dir, dt);
                    //p.pos = CCPoint.ccpAdd(p.pos, tmp);

                    tmp_x = (radial_x + tangential_x + modeA.gravity.X) * dt;
                    tmp_y = (radial_y + tangential_y + modeA.gravity.Y) * dt;

                    p.modeA.dir.X += tmp_x;
                    p.modeA.dir.Y += tmp_y;

                    p.pos.X += p.modeA.dir.X * dt;
                    p.pos.Y += p.modeA.dir.Y * dt;
                }

                // Mode B: radius movement
                else
                {
                    // Update the angle and radius of the particle.
                    p.modeB.angle  += p.modeB.degreesPerSecond * dt;
                    p.modeB.radius += p.modeB.deltaRadius * dt;

                    p.pos.X = -CCMathHelper.Cos(p.modeB.angle) * p.modeB.radius;
                    p.pos.Y = -CCMathHelper.Sin(p.modeB.angle) * p.modeB.radius;
                }

                // color
                p.color.R += (p.deltaColor.R * dt);
                p.color.G += (p.deltaColor.G * dt);
                p.color.B += (p.deltaColor.B * dt);
                p.color.A += (p.deltaColor.A * dt);

                // size
                p.size += (p.deltaSize * dt);
                if (p.size < 0)
                {
                    p.size = 0;
                }

                // angle
                p.rotation += (p.deltaRotation * dt);

                return(true);
            }
            return(false);
        }
        private void UpdateQuad(ref CCV3F_C4B_T2F_Quad quad, ref CCParticle particle)
        {
            CCPoint newPosition;

            if (m_ePositionType == CCPositionType.Free || m_ePositionType == CCPositionType.Relative)
            {
                newPosition.X = particle.pos.X - (s_currentPosition.X - particle.startPos.X);
                newPosition.Y = particle.pos.Y - (s_currentPosition.Y - particle.startPos.Y);
            }
            else
            {
                newPosition = particle.pos;
            }

            // translate newPos to correct position, since matrix transform isn't performed in batchnode
            // don't update the particle with the new position information, it will interfere with the radius and tangential calculations
            if (m_pBatchNode != null)
            {
                newPosition.X += m_obPosition.X;
                newPosition.Y += m_obPosition.Y;
            }

            CCColor4B color;

            if (m_bOpacityModifyRGB)
            {
                color.R = (byte)(particle.color.R * particle.color.A * 255);
                color.G = (byte)(particle.color.G * particle.color.A * 255);
                color.B = (byte)(particle.color.B * particle.color.A * 255);
                color.A = (byte)(particle.color.A * 255);
            }
            else
            {
                color.R = (byte)(particle.color.R * 255);
                color.G = (byte)(particle.color.G * 255);
                color.B = (byte)(particle.color.B * 255);
                color.A = (byte)(particle.color.A * 255);
            }

            quad.BottomLeft.Colors  = color;
            quad.BottomRight.Colors = color;
            quad.TopLeft.Colors     = color;
            quad.TopRight.Colors    = color;

            // vertices
            float size_2 = particle.size / 2;

            if (particle.rotation != 0.0)
            {
                float x1 = -size_2;
                float y1 = -size_2;

                float x2 = size_2;
                float y2 = size_2;
                float x  = newPosition.X;
                float y  = newPosition.Y;

                float r  = -CCMathHelper.ToRadians(particle.rotation);
                float cr = CCMathHelper.Cos(r);
                float sr = CCMathHelper.Sin(r);
                float ax = x1 * cr - y1 * sr + x;
                float ay = x1 * sr + y1 * cr + y;
                float bx = x2 * cr - y1 * sr + x;
                float by = x2 * sr + y1 * cr + y;
                float cx = x2 * cr - y2 * sr + x;
                float cy = x2 * sr + y2 * cr + y;
                float dx = x1 * cr - y2 * sr + x;
                float dy = x1 * sr + y2 * cr + y;

                // bottom-left
                quad.BottomLeft.Vertices.X = ax;
                quad.BottomLeft.Vertices.Y = ay;

                // bottom-right vertex:
                quad.BottomRight.Vertices.X = bx;
                quad.BottomRight.Vertices.Y = by;

                // top-left vertex:
                quad.TopLeft.Vertices.X = dx;
                quad.TopLeft.Vertices.Y = dy;

                // top-right vertex:
                quad.TopRight.Vertices.X = cx;
                quad.TopRight.Vertices.Y = cy;
            }
            else
            {
                // bottom-left vertex:
                quad.BottomLeft.Vertices.X = newPosition.X - size_2;
                quad.BottomLeft.Vertices.Y = newPosition.Y - size_2;

                // bottom-right vertex:
                quad.BottomRight.Vertices.X = newPosition.X + size_2;
                quad.BottomRight.Vertices.Y = newPosition.Y - size_2;

                // top-left vertex:
                quad.TopLeft.Vertices.X = newPosition.X - size_2;
                quad.TopLeft.Vertices.Y = newPosition.Y + size_2;

                // top-right vertex:
                quad.TopRight.Vertices.X = newPosition.X + size_2;
                quad.TopRight.Vertices.Y = newPosition.Y + size_2;
            }
        }
        private void InitParticle(ref CCParticle particle)
        {
            // timeToLive
            // no negative life. prevent division by 0
            particle.timeToLive = Math.Max(0, m_fLife + m_fLifeVar * CCRandom.Float_Minus1_1());

            // position
            particle.pos.X = m_tSourcePosition.X + m_tPosVar.X * CCRandom.Float_Minus1_1();
            particle.pos.Y = m_tSourcePosition.Y + m_tPosVar.Y * CCRandom.Float_Minus1_1();

            // Color
            CCColor4F start;

            start.R = MathHelper.Clamp(m_tStartColor.R + m_tStartColorVar.R * CCRandom.Float_Minus1_1(), 0, 1);
            start.G = MathHelper.Clamp(m_tStartColor.G + m_tStartColorVar.G * CCRandom.Float_Minus1_1(), 0, 1);
            start.B = MathHelper.Clamp(m_tStartColor.B + m_tStartColorVar.B * CCRandom.Float_Minus1_1(), 0, 1);
            start.A = MathHelper.Clamp(m_tStartColor.A + m_tStartColorVar.A * CCRandom.Float_Minus1_1(), 0, 1);

            CCColor4F end;

            end.R = MathHelper.Clamp(m_tEndColor.R + m_tEndColorVar.R * CCRandom.Float_Minus1_1(), 0, 1);
            end.G = MathHelper.Clamp(m_tEndColor.G + m_tEndColorVar.G * CCRandom.Float_Minus1_1(), 0, 1);
            end.B = MathHelper.Clamp(m_tEndColor.B + m_tEndColorVar.B * CCRandom.Float_Minus1_1(), 0, 1);
            end.A = MathHelper.Clamp(m_tEndColor.A + m_tEndColorVar.A * CCRandom.Float_Minus1_1(), 0, 1);

            particle.color        = start;
            particle.deltaColor.R = (end.R - start.R) / particle.timeToLive;
            particle.deltaColor.G = (end.G - start.G) / particle.timeToLive;
            particle.deltaColor.B = (end.B - start.B) / particle.timeToLive;
            particle.deltaColor.A = (end.A - start.A) / particle.timeToLive;

            // size
            float startS = m_fStartSize + m_fStartSizeVar * CCRandom.Float_Minus1_1();

            startS = Math.Max(0, startS); // No negative value

            particle.size = startS;

            if (m_fEndSize == kCCParticleStartSizeEqualToEndSize)
            {
                particle.deltaSize = 0;
            }
            else
            {
                float endS = m_fEndSize + m_fEndSizeVar * CCRandom.Float_Minus1_1();
                endS = Math.Max(0, endS); // No negative values
                particle.deltaSize = (endS - startS) / particle.timeToLive;
            }

            // rotation
            float startA = m_fStartSpin + m_fStartSpinVar * CCRandom.Float_Minus1_1();
            float endA   = m_fEndSpin + m_fEndSpinVar * CCRandom.Float_Minus1_1();

            particle.rotation      = startA;
            particle.deltaRotation = (endA - startA) / particle.timeToLive;

            // position
            if (m_ePositionType == CCPositionType.Free)
            {
                particle.startPos = ConvertToWorldSpace(CCPoint.Zero);
            }
            else if (m_ePositionType == CCPositionType.Relative)
            {
                particle.startPos = m_obPosition;
            }

            // direction
            float a = MathHelper.ToRadians(m_fAngle + m_fAngleVar * CCRandom.Float_Minus1_1());

            // Mode Gravity: A
            if (m_nEmitterMode == CCEmitterMode.Gravity)
            {
                var v = new CCPoint(CCMathHelper.Cos(a), CCMathHelper.Sin(a));

                float s = modeA.speed + modeA.speedVar * CCRandom.Float_Minus1_1();

                // direction
                particle.modeA.dir = v * s;

                // radial accel
                particle.modeA.radialAccel = modeA.radialAccel + modeA.radialAccelVar * CCRandom.Float_Minus1_1();


                // tangential accel
                particle.modeA.tangentialAccel = modeA.tangentialAccel + modeA.tangentialAccelVar * CCRandom.Float_Minus1_1();

                // rotation is dir
                if (modeA.rotationIsDir)
                {
                    particle.rotation = -MathHelper.ToDegrees(CCPoint.ToAngle(particle.modeA.dir));
                }
            }

            // Mode Radius: B
            else
            {
                // Set the default diameter of the particle from the source position
                float startRadius = modeB.startRadius + modeB.startRadiusVar * CCRandom.Float_Minus1_1();
                float endRadius   = modeB.endRadius + modeB.endRadiusVar * CCRandom.Float_Minus1_1();

                particle.modeB.radius = startRadius;

                if (modeB.endRadius == kCCParticleStartRadiusEqualToEndRadius)
                {
                    particle.modeB.deltaRadius = 0;
                }
                else
                {
                    particle.modeB.deltaRadius = (endRadius - startRadius) / particle.timeToLive;
                }

                particle.modeB.angle            = a;
                particle.modeB.degreesPerSecond =
                    MathHelper.ToRadians(modeB.rotatePerSecond + modeB.rotatePerSecondVar * CCRandom.Float_Minus1_1());
            }
        }