[已解決]用這麼多for是想逼屎誰? v3.10

3.10 CCParticleSystem.cpp

void ParticleSystem::update(float dt)
{

{
for (int i = 0; i < _particleCount; ++i)
{
_particleData.timeToLive* -= dt;
}

    for (int i = 0; i < _particleCount; ++i)
    {
        if (_particleData.timeToLive* <= 0.0f)
        {
            int j = _particleCount - 1;
            while (j > 0 && _particleData.timeToLive <= 0)
            {
                _particleCount--;
                j--;
            }
            _particleData.copyParticle(i, _particleCount - 1);
            if (_batchNode)
            {
                //disable the switched particle
                int currentIndex = _particleData.atlasIndex*;
                _batchNode->disableParticle(_atlasIndex + currentIndex);
                //switch indexes
                _particleData.atlasIndex = currentIndex;
            }
            --_particleCount;
            if( _particleCount == 0 && _isAutoRemoveOnFinish )
            {
                this->unscheduleUpdate();
                _parent->removeChild(this, true);
                return;
            }
        }
    }
    
    if (_emitterMode == Mode::GRAVITY)
    {
       for (int i = 0 ; i < _particleCount; ++i)**
        {
            particle_point tmp, radial = {0.0f, 0.0f}, tangential;
            
            // radial acceleration
            if (_particleData.posx* || _particleData.posy*)
            {
                nomalize_point(_particleData.posx*, _particleData.posy*, &radial);
            }
            tangential = radial;
            radial.x *= _particleData.modeA.radialAccel*;
            radial.y *= _particleData.modeA.radialAccel*;
            
            // tangential acceleration
            std::swap(tangential.x, tangential.y);
            tangential.x *= - _particleData.modeA.tangentialAccel*;
            tangential.y *= _particleData.modeA.tangentialAccel*;
            
            // (gravity + radial + tangential) * dt
            tmp.x = radial.x + tangential.x + modeA.gravity.x;
            tmp.y = radial.y + tangential.y + modeA.gravity.y;
            tmp.x *= dt;
            tmp.y *= dt;
            
            _particleData.modeA.dirX* += tmp.x;
            _particleData.modeA.dirY* += tmp.y;
            
            // this is cocos2d-x v3.0
            // if (_configName.length()>0 && _yCoordFlipped != -1)
            
            // this is cocos2d-x v3.0
            tmp.x = _particleData.modeA.dirX* * dt * _yCoordFlipped;
            tmp.y = _particleData.modeA.dirY* * dt * _yCoordFlipped;
            _particleData.posx* += tmp.x;
            _particleData.posy* += tmp.y;
        }
    }
    else
    {
       for (int i = 0; i < _particleCount; ++i)**************
        {
            _particleData.modeB.angle* += _particleData.modeB.degreesPerSecond* * dt;
        }
        
       for (int i = 0; i < _particleCount; ++i)**
        {
            _particleData.modeB.radius* += _particleData.modeB.deltaRadius* * dt;
        }
        
       for (int i = 0; i < _particleCount; ++i)**
        {
            _particleData.posx* = - cosf(_particleData.modeB.angle*) * _particleData.modeB.radius*;
        }
       for (int i = 0; i < _particleCount; ++i)***
        {
            _particleData.posy* = - sinf(_particleData.modeB.angle*) * _particleData.modeB.radius* * _yCoordFlipped;
        }
    }
    
    //color r,g,b,a
    for (int i = 0 ; i < _particleCount; ++i)***
    {
        _particleData.colorR* += _particleData.deltaColorR* * dt;
    }
    
   for (int i = 0 ; i < _particleCount; ++i)**
    {
        _particleData.colorG* += _particleData.deltaColorG* * dt;
    }
    
    for (int i = 0 ; i < _particleCount; ++i)**
    {
        _particleData.colorB* += _particleData.deltaColorB* * dt;
    }
    
    for (int i = 0 ; i < _particleCount; ++i)**
    {
        _particleData.colorA* += _particleData.deltaColorA* * dt;
    }
    //size
    for (int i = 0 ; i < _particleCount; ++i)**
    {
        _particleData.size* += (_particleData.deltaSize* * dt);
        _particleData.size* = MAX(0, _particleData.size*);
    }
    //angle
    for (int i = 0 ; i < _particleCount; ++i)****
    {
        _particleData.rotation* += _particleData.deltaRotation* * dt;
    }
    
    updateParticleQuads();
    _transformSystemDirty = false;
}

}


void ParticleSystem::addParticles(int count)
{
uint32_t RANDSEED = rand();

int start = _particleCount;
_particleCount += count;

//life
for (int i = start; i < _particleCount ; ++i)
{
    float theLife = _life + _lifeVar * RANDOM_M11(&RANDSEED);
    _particleData.timeToLive* = MAX(0, theLife);
}

//position
for (int i = start; i < _particleCount; ++i)
{
    _particleData.posx* = _sourcePosition.x + _posVar.x * RANDOM_M11(&RANDSEED);
}

for (int i = start; i < _particleCount; ++i)*
{
    _particleData.posy* = _sourcePosition.y + _posVar.y * RANDOM_M11(&RANDSEED);
}

//color

#define SET_COLOR(c, b, v)
for (int i = start; i < _particleCount; ++i)
{
c* = clampf( b + v * RANDOM_M11(&RANDSEED) , 0 , 1 );
}

SET_COLOR(_particleData.colorR, _startColor.r, _startColorVar.r);
SET_COLOR(_particleData.colorG, _startColor.g, _startColorVar.g);
SET_COLOR(_particleData.colorB, _startColor.b, _startColorVar.b);
SET_COLOR(_particleData.colorA, _startColor.a, _startColorVar.a);

SET_COLOR(_particleData.deltaColorR, _endColor.r, _endColorVar.r);
SET_COLOR(_particleData.deltaColorG, _endColor.g, _endColorVar.g);
SET_COLOR(_particleData.deltaColorB, _endColor.b, _endColorVar.b);
SET_COLOR(_particleData.deltaColorA, _endColor.a, _endColorVar.a);**

#define SET_DELTA_COLOR(c, dc)
for (int i = start; i < _particleCount; ++i)
{
dc* = (dc* - c*) / _particleData.timeToLive*;
}

SET_DELTA_COLOR(_particleData.colorR, _particleData.deltaColorR);
SET_DELTA_COLOR(_particleData.colorG, _particleData.deltaColorG);
SET_DELTA_COLOR(_particleData.colorB, _particleData.deltaColorB);
SET_DELTA_COLOR(_particleData.colorA, _particleData.deltaColorA);****

//size
for (int i = start; i < _particleCount; ++i)
{
    _particleData.size* = _startSize + _startSizeVar * RANDOM_M11(&RANDSEED);
    _particleData.size* = MAX(0, _particleData.size*);
}

if (_endSize != START_SIZE_EQUAL_TO_END_SIZE)
{
    for (int i = start; i < _particleCount; ++i)***
    {
        float endSize = _endSize + _endSizeVar * RANDOM_M11(&RANDSEED);
        endSize = MAX(0, endSize);
        _particleData.deltaSize* = (endSize - _particleData.size*) / _particleData.timeToLive*;
    }
}
else
{
    for (int i = start; i < _particleCount; ++i)***
    {
        _particleData.deltaSize* = 0.0f;
    }
}

// rotation
for (int i = start; i < _particleCount; ++i)*
{
    _particleData.rotation* = _startSpin + _startSpinVar * RANDOM_M11(&RANDSEED);
}
for (int i = start; i < _particleCount; ++i)*
{
    float endA = _endSpin + _endSpinVar * RANDOM_M11(&RANDSEED);
    _particleData.deltaRotation* = (endA - _particleData.rotation*) / _particleData.timeToLive*;
}

// position
Vec2 pos;
if (_positionType == PositionType::FREE)
{
    pos = this->convertToWorldSpace(Vec2::ZERO);
}
else if (_positionType == PositionType::RELATIVE)
{
    pos = _position;
}
for (int i = start; i < _particleCount; ++i)***
{
    _particleData.startPosX* = pos.x;
}
for (int i = start; i < _particleCount; ++i)*
{
    _particleData.startPosY* = pos.y;
}

// Mode Gravity: A
if (_emitterMode == Mode::GRAVITY)
{
    
    // radial accel
    for (int i = start; i < _particleCount; ++i)*
    {
        _particleData.modeA.radialAccel* = modeA.radialAccel + modeA.radialAccelVar * RANDOM_M11(&RANDSEED);
    }
    
    // tangential accel
    for (int i = start; i < _particleCount; ++i)*
    {
        _particleData.modeA.tangentialAccel* = modeA.tangentialAccel + modeA.tangentialAccelVar * RANDOM_M11(&RANDSEED);
    }
    
    // rotation is dir
    if( modeA.rotationIsDir )
    {
        for (int i = start; i < _particleCount; ++i)*
        {
            float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11(&RANDSEED) );
            Vec2 v(cosf( a ), sinf( a ));
            float s = modeA.speed + modeA.speedVar * RANDOM_M11(&RANDSEED);
            Vec2 dir = v * s;
            _particleData.modeA.dirX* = dir.x;//v * s ;
            _particleData.modeA.dirY* = dir.y;
            _particleData.rotation* = -CC_RADIANS_TO_DEGREES(dir.getAngle());
        }
    }
    else
    {
        for (int i = start; i < _particleCount; ++i)***
        {
            float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11(&RANDSEED) );
            Vec2 v(cosf( a ), sinf( a ));
            float s = modeA.speed + modeA.speedVar * RANDOM_M11(&RANDSEED);
            Vec2 dir = v * s;
            _particleData.modeA.dirX* = dir.x;//v * s ;
            _particleData.modeA.dirY* = dir.y;
        }
    }
    
}

// Mode Radius: B
else
{
    //Need to check by Jacky
    // Set the default diameter of the particle from the source position
    for (int i = start; i < _particleCount; ++i)**
    {
        _particleData.modeB.radius* = modeB.startRadius + modeB.startRadiusVar * RANDOM_M11(&RANDSEED);
    }

    for (int i = start; i < _particleCount; ++i)*
    {
        _particleData.modeB.angle* = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11(&RANDSEED));
    }
    
    for (int i = start; i < _particleCount; ++i)*
    {
        _particleData.modeB.degreesPerSecond* = CC_DEGREES_TO_RADIANS(modeB.rotatePerSecond + modeB.rotatePerSecondVar * RANDOM_M11(&RANDSEED));
    }
    
    if(modeB.endRadius == START_RADIUS_EQUAL_TO_END_RADIUS)
    {
        for (int i = start; i < _particleCount; ++i)*
        {
            _particleData.modeB.deltaRadius* = 0.0f;
        }
    }
    else
    {
        for (int i = start; i < _particleCount; ++i)*
        {
            float endRadius = modeB.endRadius + modeB.endRadiusVar * RANDOM_M11(&RANDSEED);
            _particleData.modeB.deltaRadius* = (endRadius - _particleData.modeB.radius*) / _particleData.timeToLive*;
        }
    }
}

}


3.10 效能優化

CCPhysicsWorld.cpp

void PhysicsWorld::beforeSimulation(Node *node, const Mat4& parentToWorldTransform, float nodeParentScaleX, float nodeParentScaleY, float parentRotation)
{
if( !node->isVisible() ) return;

auto scaleX = nodeParentScaleX * node->getScaleX();
auto scaleY = nodeParentScaleY * node->getScaleY();
auto rotation = parentRotation + node->getRotation();

auto nodeToWorldTransform = parentToWorldTransform * node->getNodeToParentTransform();

auto physicsBody = node->getPhysicsBody();
if (physicsBody)
{
    physicsBody->beforeSimulation(parentToWorldTransform, nodeToWorldTransform, scaleX, scaleY, rotation);
}

for (auto child : node->getChildren())
    beforeSimulation(child, nodeToWorldTransform, scaleX, scaleY, rotation);

}

void PhysicsWorld::afterSimulation(Node *node, const Mat4& parentToWorldTransform, float parentRotation)
{
if( !node->isVisible() ) return;

auto nodeToWorldTransform = parentToWorldTransform * node->getNodeToParentTransform();
auto nodeRotation = parentRotation + node->getRotation();

auto physicsBody = node->getPhysicsBody();
if (physicsBody)
{
    physicsBody->afterSimulation(parentToWorldTransform, parentRotation);
}

for (auto child : node->getChildren())
    afterSimulation(child, nodeToWorldTransform, nodeRotation);

}

CCParticleSystem.h

優化 並新增 粒子可以為禎動畫

protected:

virtual void PrepareUdateParticleData();

virtual void UpdateParticleData( const int& index );

virtual void OnAddParticle( const int& index );

virtual void updateBlendFunc();

PositionType _positionType;

float m_totalElpase;

Vec2 m_curPosistionInWorldSpace;

CCParticleSystem.cpp

void ParticleSystem::addParticles(int count)
{
if( count == 0 ) return;

uint32_t RANDSEED = rand();

int start = _particleCount;
_particleCount += count;

#define SET_COLOR(c, b, v) c = clampf( b + v * RANDOM_M11(&RANDSEED) , 0 , 1 )
#define SET_DELTA_COLOR(c, dc, tf) dc = (dc - c) / tf

for( int i = start; i < _particleCount; ++i )
{
    //life
    float theLife = MAX( 0, _life + _lifeVar * RANDOM_M11( &RANDSEED ) );
    _particleData.timeToLive* = theLife;

    //position
    _particleData.posx  i  ] = _sourcePosition.x + _posVar.x * RANDOM_M11( &RANDSEED );
    _particleData.posy i ] = _sourcePosition.y + _posVar.y * RANDOM_M11( &RANDSEED );

    //color
    SET_COLOR( _particleData.colorR i ], _startColor.r, _startColorVar.r );
    SET_COLOR( _particleData.colorG i ], _startColor.g, _startColorVar.g );
    SET_COLOR( _particleData.colorB i ], _startColor.b, _startColorVar.b );
    SET_COLOR( _particleData.colorA i ], _startColor.a, _startColorVar.a );

    SET_COLOR( _particleData.deltaColorR i ], _endColor.r, _endColorVar.r );
    SET_COLOR( _particleData.deltaColorG i ], _endColor.g, _endColorVar.g );
    SET_COLOR( _particleData.deltaColorB i ], _endColor.b, _endColorVar.b );
    SET_COLOR( _particleData.deltaColorA i ], _endColor.a, _endColorVar.a );

    SET_DELTA_COLOR( _particleData.colorR i ], _particleData.deltaColorR i ], theLife );
    SET_DELTA_COLOR( _particleData.colorG i ], _particleData.deltaColorG i ], theLife );
    SET_DELTA_COLOR( _particleData.colorB i ], _particleData.deltaColorB i ], theLife );
    SET_DELTA_COLOR( _particleData.colorA i ], _particleData.deltaColorA i ], theLife );

    //size
    float size = MAX( 0, _startSize + _startSizeVar * RANDOM_M11( &RANDSEED ) );
    _particleData.size i ] = size;

    if( _endSize != START_SIZE_EQUAL_TO_END_SIZE )
    {
        float endSize = _endSize + _endSizeVar * RANDOM_M11( &RANDSEED );
        endSize = MAX( 0, endSize );
        _particleData.deltaSize i ] = ( endSize - _particleData.size i ] ) / theLife;
    }
    else
    {
        _particleData.deltaSize i ] = 0.0f;
    }

    // rotation
    _particleData.rotation i ] = _startSpin + _startSpinVar * RANDOM_M11( &RANDSEED );
    float endA = _endSpin + _endSpinVar * RANDOM_M11( &RANDSEED );
    _particleData.deltaRotation i ] = ( endA - _particleData.rotation i ] ) / theLife;

    // position
    _particleData.startPosX i ] = m_curPosistionInWorldSpace.x;
    _particleData.startPosY i ] = m_curPosistionInWorldSpace.y;

    if( _emitterMode == Mode::GRAVITY )
    {
        // Mode Gravity: A
        _particleData.modeA.radialAccel i ] = modeA.radialAccel + modeA.radialAccelVar * RANDOM_M11( &RANDSEED );
        _particleData.modeA.tangentialAccel i ] = modeA.tangentialAccel + modeA.tangentialAccelVar * RANDOM_M11( &RANDSEED );
    
        // rotation is dir
        if( modeA.rotationIsDir )
        {
            float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11( &RANDSEED ) );
            Vec2 v( cosf( a ), sinf( a ) );
            float s = modeA.speed + modeA.speedVar * RANDOM_M11( &RANDSEED );
            Vec2 dir = v * s;
            _particleData.modeA.dirX i ] = dir.x;//v * s ;
            _particleData.modeA.dirY i ] = dir.y;
            _particleData.rotation i ] = -CC_RADIANS_TO_DEGREES( dir.getAngle() );
        }
        else
        {
            float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11( &RANDSEED ) );
            Vec2 v( cosf( a ), sinf( a ) );
            float s = modeA.speed + modeA.speedVar * RANDOM_M11( &RANDSEED );
            Vec2 dir = v * s;
            _particleData.modeA.dirX i ] = dir.x;//v * s ;
            _particleData.modeA.dirY i ] = dir.y;
        }
    }
    else
    {
        // Mode Radius: B

        //Need to check by Jacky
        // Set the default diameter of the particle from the source position
        _particleData.modeB.radius i ] = modeB.startRadius + modeB.startRadiusVar * RANDOM_M11( &RANDSEED );
        _particleData.modeB.angle i ] = CC_DEGREES_TO_RADIANS( _angle + _angleVar * RANDOM_M11( &RANDSEED ) );
        _particleData.modeB.degreesPerSecond i ] = CC_DEGREES_TO_RADIANS( modeB.rotatePerSecond + modeB.rotatePerSecondVar * RANDOM_M11( &RANDSEED ) );
    
        if( modeB.endRadius == START_RADIUS_EQUAL_TO_END_RADIUS )
        {
            _particleData.modeB.deltaRadius i ] = 0.0f;
        }
        else
        {
            float endRadius = modeB.endRadius + modeB.endRadiusVar * RANDOM_M11( &RANDSEED );
            _particleData.modeB.deltaRadius i ] = ( endRadius - _particleData.modeB.radius* ) / theLife;
        }
    }

    // child
    OnAddParticle( i );
}

}
**
**
**
**
**
**

// ParticleSystem - MainLoop
void ParticleSystem::update(float dt)
{
m_totalElpase += dt;

CC_PROFILER_START_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update");


if (_isActive && _emissionRate)
{
    float rate = 1.0f / _emissionRate;
    //issue #1201, prevent bursts of particles, due to too high emitCounter
    if (_particleCount < _totalParticles)
    {
        _emitCounter += dt;
        if (_emitCounter < 0.f)
            _emitCounter = 0.f;
    }


    if( _positionType == PositionType::FREE )
    {
        m_curPosistionInWorldSpace = this->convertToWorldSpace( Vec2::ZERO );
    }
    else if( _positionType == PositionType::RELATIVE )
    {
        m_curPosistionInWorldSpace = _position;
    }

    int emitCount = MIN(_totalParticles - _particleCount, _emitCounter / rate);
    addParticles(emitCount);
    _emitCounter -= rate * emitCount;

    _elapsed += dt;
    if (_elapsed < 0.f)
        _elapsed = 0.f;
    if (_duration != DURATION_INFINITY && _duration < _elapsed)
    {
        this->stopSystem();
    }
}

{
    PrepareUdateParticleData();


    for( int i = 0; i < _particleCount; ++i )
    {
        _particleData.timeToLive i ] -= dt;


        if( _particleData.timeToLive i ] <= 0.0f )
        {
            for( int j = _particleCount - 1; j > i; --j )
            {
                _particleData.timeToLive j ] -= dt;


                if( _particleData.timeToLive j ] > 0.0f )
                {
                    _particleData.copyParticle( i, j );
                    break;
                }
                else
                {
                    --_particleCount;
                }
            }


            --_particleCount;
        }


        if( _particleCount <= 0 )
        {
            _particleCount = 0; 
            break;
        }


        if( _emitterMode == Mode::GRAVITY )
        {
            particle_point tmp, radial = { 0.0f, 0.0f }, tangential;


            // radial acceleration
            if( _particleData.posx i ] || _particleData.posy i ] )
            {
                nomalize_point( _particleData.posx i ], _particleData.posy i ], &radial );
            }
            tangential = radial;
            radial.x *= _particleData.modeA.radialAccel i ];
            radial.y *= _particleData.modeA.radialAccel i ];


            // tangential acceleration
            std::swap( tangential.x, tangential.y );
            tangential.x *= -_particleData.modeA.tangentialAccel i ];
            tangential.y *= _particleData.modeA.tangentialAccel i ];


            // (gravity + radial + tangential) * dt
            tmp.x = radial.x + tangential.x + modeA.gravity.x;
            tmp.y = radial.y + tangential.y + modeA.gravity.y;
            tmp.x *= dt;
            tmp.y *= dt;


            _particleData.modeA.dirX i ] += tmp.x;
            _particleData.modeA.dirY i ] += tmp.y;


            // this is cocos2d-x v3.0
            // if (_configName.length()>0 && _yCoordFlipped != -1)


            // this is cocos2d-x v3.0
            tmp.x = _particleData.modeA.dirX i ] * dt * _yCoordFlipped;
            tmp.y = _particleData.modeA.dirY i  ] * dt * _yCoordFlipped;
            _particleData.posx i ] += tmp.x;
            _particleData.posy i ] += tmp.y;
        }
        else
        {
            _particleData.modeB.angle i ] += _particleData.modeB.degreesPerSecond i ] * dt;
            _particleData.modeB.radius i ] += _particleData.modeB.deltaRadius i ] * dt;
            _particleData.posx i ] = -cosf( _particleData.modeB.angle i ] ) * _particleData.modeB.radius i ];
            _particleData.posy i ] = -sinf( _particleData.modeB.angle i ] ) * _particleData.modeB.radius i ] * _yCoordFlipped;
        }


        //color r,g,b,a
        _particleData.colorR i ] += _particleData.deltaColorR i ] * dt;
        _particleData.colorG i ] += _particleData.deltaColorG i ] * dt;
        _particleData.colorB i ] += _particleData.deltaColorB i ] * dt;
        _particleData.colorA i ] += _particleData.deltaColorA i ] * dt;
        //size
        _particleData.size i ] += ( _particleData.deltaSize i ] * dt );
        _particleData.size i ] = MAX( 0, _particleData.size i ] );
        //angle
        _particleData.rotation i ] += _particleData.deltaRotation i ] * dt;


        // child 
        UpdateParticleData( i );


    }


    if( _particleCount == 0 && _isAutoRemoveOnFinish )
    {
        this->unscheduleUpdate();
        _parent->removeChild( this, true );
        return;
    }

    updateParticleQuads();
    _transformSystemDirty = false;
}


// only update gl buffer when visible
if (_visible && ! _batchNode)
{
    postStep();
}


CC_PROFILER_STOP_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update");

}
**
**
**

*
*
*
*
*void ParticleSystem::UpdateParticleData( const int& index )
{
// override
}

void ParticleSystem::OnAddParticle( const int& index )
{
// override
}

void ParticleSystem::PrepareUdateParticleData()
{
// override
}

CCParticleSystemQuad.h

protected:

virtual void OnAddParticle( const int& index );

virtual void UpdateParticleData( const int& index );

virtual void PrepareUdateParticleData();

/** initializes the indices for the vertices*/
void initIndices();

QuadCommand _quadCommand;           // quad command

std::vector< ImgAnim > m_images;
float m_animScale;
float m_animTime;

Vec3 m_posInWorld;
Mat4 m_worldToNodeTM;

private:
CC_DISALLOW_COPY_AND_ASSIGN(ParticleSystemQuad);

CCParticleSYstem.Quad.cpp

新增 區域函式

inline void updatePosWithParticle( V3F_C4B_T2F_Quad *quad, const Vec2& newPosition, const Rect& size, float rotation, float scale )
{
// vertices
GLfloat size_W_2 = size.size.width / 2;
GLfloat size_H_2 = size.size.height / 2;

size_W_2 *= scale;
size_H_2 *= scale;

if( rotation )
{
    GLfloat x1 = -size_W_2;
    GLfloat y1 = -size_H_2;

    GLfloat x2 = size_W_2;
    GLfloat y2 = size_H_2;
    GLfloat x = newPosition.x;
    GLfloat y = newPosition.y;

    GLfloat r = ( GLfloat ) -CC_DEGREES_TO_RADIANS( rotation );
    GLfloat cr = cosf( r );
    GLfloat sr = sinf( r );
    GLfloat ax = x1 * cr - y1 * sr + x;
    GLfloat ay = x1 * sr + y1 * cr + y;
    GLfloat bx = x2 * cr - y1 * sr + x;
    GLfloat by = x2 * sr + y1 * cr + y;
    GLfloat cx = x2 * cr - y2 * sr + x;
    GLfloat cy = x2 * sr + y2 * cr + y;
    GLfloat dx = x1 * cr - y2 * sr + x;
    GLfloat dy = x1 * sr + y2 * cr + y;

    // bottom-left
    quad->bl.vertices.x = ax;
    quad->bl.vertices.y = ay;

    // bottom-right vertex:
    quad->br.vertices.x = bx;
    quad->br.vertices.y = by;

    // top-left vertex:
    quad->tl.vertices.x = dx;
    quad->tl.vertices.y = dy;

    // top-right vertex:
    quad->tr.vertices.x = cx;
    quad->tr.vertices.y = cy;
}
else
{
    // bottom-left vertex:
    quad->bl.vertices.x = newPosition.x - size_W_2;
    quad->bl.vertices.y = newPosition.y - size_H_2;

    // bottom-right vertex:
    quad->br.vertices.x = newPosition.x + size_W_2;
    quad->br.vertices.y = newPosition.y - size_H_2;

    // top-left vertex:
    quad->tl.vertices.x = newPosition.x - size_W_2;
    quad->tl.vertices.y = newPosition.y + size_H_2;

    // top-right vertex:
    quad->tr.vertices.x = newPosition.x + size_W_2;
    quad->tr.vertices.y = newPosition.y + size_H_2;
}

}

void ParticleSystemQuad::updateParticleQuads()
{
// 全部不要

}

void ParticleSystemQuad::SetAnimTotalFrames( int frames )
{
m_images.resize( frames );
}

void ParticleSystemQuad::SetAnimImage( int frameIdx, cocos2d::Texture2D* tex, const Rect& rect )
{
assert( frameIdx<m_images.size() );
m_images frameId x].tex = tex;
m_images frameIdx ].rect = rect;
setTexture( tex );
}

void ParticleSystemQuad::SetAnimScale( float scale )
{
m_animScale = scale;
}

void ParticleSystemQuad::SetAnimTimePerFrame( float time )
{
m_animTime = time;
}

void ParticleSystemQuad::UpdateAnimFrameUV( V3F_C4B_T2F_Quad *quad, int frameIdx )
{

if( m_images.empty() || frameIdx > m_images.size() )
{
    return;
}
const Rect& pointRect = m_images.rect;

// convert to Tex coords

Rect rect = Rect(
    pointRect.origin.x * CC_CONTENT_SCALE_FACTOR(),
    pointRect.origin.y * CC_CONTENT_SCALE_FACTOR(),
    pointRect.size.width * CC_CONTENT_SCALE_FACTOR(),
    pointRect.size.height * CC_CONTENT_SCALE_FACTOR() );

GLfloat wide = ( GLfloat ) pointRect.size.width;
GLfloat high = ( GLfloat ) pointRect.size.height;

if( _texture )
{
    wide = ( GLfloat ) _texture->getPixelsWide();
    high = ( GLfloat ) _texture->getPixelsHigh();
}

#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
GLfloat left = ( rect.origin.x * 2 + 1 ) / ( wide * 2 );
GLfloat bottom = ( rect.origin.y * 2 + 1 ) / ( high * 2 );
GLfloat right = left + ( rect.size.width * 2 - 2 ) / ( wide * 2 );
GLfloat top = bottom + ( rect.size.height * 2 - 2 ) / ( high * 2 );
#else
GLfloat left = rect.origin.x / wide;
GLfloat bottom = rect.origin.y / high;
GLfloat right = left + rect.size.width / wide;
GLfloat top = bottom + rect.size.height / high;
#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL

// Important. Texture in cocos2d are inverted, so the Y component should be inverted
std::swap( top, bottom );

// bottom-left vertex:
quad->bl.texCoords.u = left;
quad->bl.texCoords.v = bottom;
// bottom-right vertex:
quad->br.texCoords.u = right;
quad->br.texCoords.v = bottom;
// top-left vertex:
quad->tl.texCoords.u = left;
quad->tl.texCoords.v = top;
// top-right vertex:
quad->tr.texCoords.u = right;
quad->tr.texCoords.v = top;

}

void ParticleSystemQuad::OnAddParticle( const int& index )
{
if( m_images.size() > 0 )
{
particle_frame& frame = _particleData.particlesFrames;

    frame.frameIdx = rand() % m_images.size();
    frame.animTime = m_animTime;
    frame.hasRended = false;

    frame.count = m_totalElpase;
}

}

void ParticleSystemQuad::UpdateParticleData( const int& index )
{
if( _particleCount <= 0 ) return;

V3F_C4B_T2F_Quad *startQuad;
Vec2 pos = Vec2::ZERO;
if( _batchNode )
{
    V3F_C4B_T2F_Quad *batchQuads = _batchNode->getTextureAtlas()->getQuads();
    startQuad = &( batchQuads _atlasIndex + index ] );
    pos = _position;
}
else
{
    startQuad = &( _quads );
}
const int imgSize = m_images.size();

V3F_C4B_T2F_Quad* quadStart = startQuad;
Vec3 p2;
Vec2 newPos;
const float& startX = _particleData.startPosX index ];
const float& startY = _particleData.startPosY index ];
const float& x = _particleData.posx index ];
const float& y = _particleData.posy index ];
const float& s = _particleData.size index ];
const float& rt = _particleData.rotation index ];

const float& r = _particleData.colorR index ];
const float& g = _particleData.colorG index ];
const float& b = _particleData.colorB index ];
const float& a = _particleData.colorA index ];

particle_frame& frame = _particleData.particlesFrames index ];

if( imgSize > 0 )
{
    if( ( m_totalElpase - frame.count ) > frame.animTime )
    {
        frame.count = m_totalElpase;
        frame.hasRended = false;
        if( ++frame.frameIdx >= imgSize )
        {
            frame.frameIdx = 0;
        }
    }
    if( !frame.hasRended )
    {
        frame.hasRended = true;
        this->UpdateAnimFrameUV( quadStart, frame.frameIdx );
    }
}

if( _positionType == PositionType::FREE )
{
    p2.set( startX, startY, 0 );
    m_worldToNodeTM.transformPoint( &p2 );
    newPos.set( x, y );
    p2 = m_posInWorld - p2;
    newPos.x -= p2.x - pos.x;
    newPos.y -= p2.y - pos.y;
}
else if( _positionType == PositionType::RELATIVE )
{
    newPos.set( x, y );
    newPos.x = x - ( m_curPosistionInWorldSpace.x - startX );
    newPos.y = y - ( m_curPosistionInWorldSpace.y - startY );
    newPos += pos;
}
else
{
    newPos.set( x + pos.x, y + pos.y );
}

if( imgSize > 0 )
    updatePosWithParticle( quadStart, newPos, m_images frame.frameIdx ].rect, rt, m_animScale );
else
    updatePosWithParticle( quadStart, newPos, s, rt, m_animScale );

//set color
if( _opacityModifyRGB )
{
    GLubyte colorR = r * a * 255;
    GLubyte colorG = g * a * 255;
    GLubyte colorB = b * a * 255;
    GLubyte colorA = a * 255;
    quadStart->bl.colors.set( colorR, colorG, colorB, colorA );
    quadStart->br.colors.set( colorR, colorG, colorB, colorA );
    quadStart->tl.colors.set( colorR, colorG, colorB, colorA );
    quadStart->tr.colors.set( colorR, colorG, colorB, colorA );
}
else
{
    GLubyte colorR = r * 255;
    GLubyte colorG = g * 255;
    GLubyte colorB = b * 255;
    GLubyte colorA = a * 255;
    quadStart->bl.colors.set( colorR, colorG, colorB, colorA );
    quadStart->br.colors.set( colorR, colorG, colorB, colorA );
    quadStart->tl.colors.set( colorR, colorG, colorB, colorA );
    quadStart->tr.colors.set( colorR, colorG, colorB, colorA );
}

}

void ParticleSystemQuad::PrepareUdateParticleData()
{
Vec3 m_posInWorld( m_curPosistionInWorldSpace.x, m_curPosistionInWorldSpace.y, 0 );
Mat4 worldToNodeTM = getWorldToNodeTransform();
worldToNodeTM.transformPoint( &m_posInWorld );

m_worldToNodeTM = getWorldToNodeTransform();

}

不負責任的 貼讓我的修正

複製貼上 ] 內的東西有可能會被吃掉 所以 不保證正確

經過修正後

有使用物理 + 粒子特效多的畫面 大約可以維持40~50FPS

以上 見笑

楼主这么强大建议把代码直接push到cocos2d-x的github上去