// ParticleSystem - MainLoop
void CCParticleSystem::update(ccTime dt)
{
	if( m_bIsActive && m_fEmissionRate )
	{
		float rate = 1.0f / m_fEmissionRate;
		m_fEmitCounter += dt;
		while( m_nParticleCount < m_nTotalParticles && m_fEmitCounter > rate ) 
		{
			this->addParticle();
			m_fEmitCounter -= rate;
		}

		m_fElapsed += dt;
		if(m_fDuration != -1 && m_fDuration < m_fElapsed)
		{
			this->stopSystem();
		}
	}

	m_nParticleIdx = 0;


#if CC_ENABLE_PROFILERS
	/// @todo CCProfilingBeginTimingBlock(_profilingTimer);
#endif


	CGPoint currentPosition = CGPointZero;
	if( m_ePositionType == kCCPositionTypeFree )
	{
		currentPosition = this->convertToWorldSpace(CGPointZero);
        currentPosition.x *= CC_CONTENT_SCALE_FACTOR();
        currentPosition.y *= CC_CONTENT_SCALE_FACTOR();
	}
    else if ( m_ePositionType == kCCPositionTypeRelative )
    {
        currentPosition = m_tPosition;
        currentPosition.x *= CC_CONTENT_SCALE_FACTOR();
        currentPosition.y *= CC_CONTENT_SCALE_FACTOR();
    }

	while( m_nParticleIdx < m_nParticleCount )
	{
		tCCParticle *p = &m_pParticles[m_nParticleIdx];

		// life
		p->timeToLive -= dt;

		if( p->timeToLive > 0 ) 
		{
			// Mode A: gravity, direction, tangential accel & radial accel
			if( m_nEmitterMode == kCCParticleModeGravity ) 
			{
				CGPoint tmp, radial, tangential;

				radial = CGPointZero;
				// radial acceleration
				if(p->pos.x || p->pos.y)
					radial = ccpNormalize(p->pos);
				tangential = radial;
				radial = ccpMult(radial, p->modeA.radialAccel);

				// tangential acceleration
				float newy = tangential.x;
				tangential.x = -tangential.y;
				tangential.y = newy;
				tangential = ccpMult(tangential, p->modeA.tangentialAccel);

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

			// 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 = - cosf(p->modeB.angle) * p->modeB.radius;
				p->pos.y = - sinf(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);
			p->size = MAX( 0, p->size );

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

			//
			// update values in quad
			//

			CGPoint	newPos;

			if( m_ePositionType == kCCPositionTypeFree || m_ePositionType == kCCPositionTypeRelative ) 
			{
				CGPoint diff = ccpSub( currentPosition, p->startPos );
				newPos = ccpSub(p->pos, diff);
			} 
			else
			{
				newPos = p->pos;
			}

			updateQuadWithParticle(p, newPos);
			//updateParticleImp(self, updateParticleSel, p, newPos);

			// update particle counter
			++m_nParticleIdx;

		} 
		else 
		{
			// life < 0
			if( m_nParticleIdx != m_nParticleCount-1 )
			{
				m_pParticles[m_nParticleIdx] = m_pParticles[m_nParticleCount-1];
			}
			--m_nParticleCount;

			if( m_nParticleCount == 0 && m_bIsAutoRemoveOnFinish )
			{
				this->unscheduleUpdate();
				m_pParent->removeChild(this, true);
				return;
			}
		}
	}

#if CC_ENABLE_PROFILERS
	/// @todo CCProfilingEndTimingBlock(_profilingTimer);
#endif

//#ifdef CC_USES_VBO
	this->postStep();
//#endif
}
void CCParticleSystemFrameQuad::update(float dt)
{
    CC_PROFILER_START_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystemFrameQuad - update");

    if (m_bIsActive && m_fEmissionRate)
    {
        float rate = 1.0f / m_fEmissionRate;
        //issue #1201, prevent bursts of particles, due to too high emitCounter
        if (m_uParticleCount < m_uTotalParticles)
        {
            m_fEmitCounter += dt;
        }
        
        while (m_uParticleCount < m_uTotalParticles && m_fEmitCounter > rate) 
        {
            this->addParticle();
            m_fEmitCounter -= rate;
        }

        m_fElapsed += dt;
        if (m_fDuration != -1 && m_fDuration < m_fElapsed)
        {
            this->stopSystem();
        }
    }

    m_uParticleIdx = 0;

    CCPoint currentPosition = CCPointZero;
    if (m_ePositionType == kCCPositionTypeFree)
    {
        currentPosition = this->convertToWorldSpace(CCPointZero);
    }
    else if (m_ePositionType == kCCPositionTypeRelative)
    {
        currentPosition = m_obPosition;
    }

    if (m_bVisible)
    {
        while (m_uParticleIdx < m_uParticleCount)
        {
            tCCParticle *p = &m_pParticles[m_uParticleIdx];

            // life
            p->timeToLive -= dt;

            if (p->timeToLive > 0) 
            {
                // Mode A: gravity, direction, tangential accel & radial accel
                if (m_nEmitterMode == kCCParticleModeGravity) 
                {
                    CCPoint tmp, radial, tangential;

                    radial = CCPointZero;
                    // radial acceleration
                    if (p->pos.x || p->pos.y)
                    {
                        radial = ccpNormalize(p->pos);
                    }
                    tangential = radial;
                    radial = ccpMult(radial, p->modeA.radialAccel);

                    // tangential acceleration
                    float newy = tangential.x;
                    tangential.x = -tangential.y;
                    tangential.y = newy;
                    tangential = ccpMult(tangential, p->modeA.tangentialAccel);

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

                // 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 = - cosf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y = - sinf(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);
                p->size = MAX( 0, p->size );

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

                //
                // update values in quad
                //

                CCPoint    newPos;

                if (m_ePositionType == kCCPositionTypeFree || m_ePositionType == kCCPositionTypeRelative) 
                {
                    CCPoint diff = ccpSub( currentPosition, p->startPos );
                    newPos = ccpSub(p->pos, diff);
                } 
                else
                {
                    newPos = p->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)
                {
                    newPos.x+=m_obPosition.x;
                    newPos.y+=m_obPosition.y;
                }

                updateQuadWithParticle(p, newPos);
                //updateParticleImp(self, updateParticleSel, p, newPos);

                // update particle counter
                ++m_uParticleIdx;
            } 
            else 
            {
                // life < 0
                int currentIndex = p->atlasIndex;
                if( m_uParticleIdx != m_uParticleCount-1 )
                {
                    m_pParticles[m_uParticleIdx] = m_pParticles[m_uParticleCount-1];
                }
                if (m_pBatchNode)
                {
                    //disable the switched particle
                    m_pBatchNode->disableParticle(m_uAtlasIndex+currentIndex);

                    //switch indexes
                    m_pParticles[m_uParticleCount-1].atlasIndex = currentIndex;
                }
				else if( m_uParticleIdx != m_uParticleCount-1 )
				{
					//switch quads texCoords
					ccV3F_C4B_T2F_Quad temp = m_pQuads[m_uParticleIdx];
					m_pQuads[m_uParticleIdx] = m_pQuads[m_uParticleCount-1];
					m_pQuads[m_uParticleCount-1] = temp;
				}


                --m_uParticleCount;

                if( m_uParticleCount == 0 && m_bIsAutoRemoveOnFinish )
                {
                    this->unscheduleUpdate();
                    m_pParent->removeChild(this, true);
                    return;
                }
            }
        } //while
        m_bTransformSystemDirty = false;
    }
    if (! m_pBatchNode)
    {
        postStep();
    }

    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystemFrameQuad - update");
}
void BillboardParticleSystem::update(float dt)
{
    if(_camera)
    {
        const Mat4& cameraViewMatrix = _camera->getViewMatrix().getInversed();
        cameraViewMatrix.getRightVector(&_cameraRight);
        cameraViewMatrix.getUpVector(&_cameraUp);
    }
    const Mat4& WorldMat = getNodeToWorldTransform();
    Quaternion rotation;;
    WorldMat.getRotation(&rotation);
    Mat4 roaMat;
    Mat4::createRotation(rotation,&roaMat);

    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;
        }

        while (_particleCount < _totalParticles && _emitCounter > rate) 
        {
            this->addParticle();
            _emitCounter -= rate;
        }

        _elapsed += dt;
        if (_duration != -1 && _duration < _elapsed)
        {
            this->stopSystem();
        }
    }

    _particleIdx = 0;

    Vec3 currentPosition = Vec3::ZERO;
    if (_positionType == PositionType::FREE)
    {
        currentPosition = this->convertToWorldSpace3D(Vec3::ZERO);
    }
    else if (_positionType == PositionType::RELATIVE)
    {
        currentPosition.x = _position.x;
        currentPosition.y = _position.y;
        currentPosition.z = _positionZ;
    }

    {
        while (_particleIdx < _particleCount)
        {
            sBillboardParticle *p = &_particles[_particleIdx];

            // life
            p->timeToLive -= dt;

            if (p->timeToLive > 0) 
            {
                // Mode A: gravity, direction, tangential accel & radial accel
                if (_emitterMode == Mode::GRAVITY)
                {
                    Vec2 tmp, radial, tangential;

                    radial = Vec2::ZERO;
                    // radial acceleration
                    if (p->pos.x || p->pos.y)
                    {
                        radial = p->pos.getNormalized();
                    }
                    tangential = radial;
                    radial = radial * p->modeA.radialAccel;

                    // tangential acceleration
                    float newy = tangential.x;
                    tangential.x = -tangential.y;
                    tangential.y = newy;
                    tangential = tangential * p->modeA.tangentialAccel;

                    // (gravity + radial + tangential) * dt
                    tmp = radial + tangential + modeA.gravity;
                    tmp = tmp * dt;
                    p->modeA.dir = p->modeA.dir + tmp;

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

                    // this is cocos2d-x v3.0
                    tmp = p->modeA.dir * dt * _yCoordFlipped;
                    p->pos = p->pos + tmp;
                }

                // 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 = - cosf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y = - sinf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y *= _yCoordFlipped;
                }

                // 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);
                p->size = MAX( 0, p->size );

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

                //
                // update values in quad
                //

                Vec3    newPos;
                Vec3 parPos(p->pos.x,p->pos.y,0);
                roaMat.transformVector(&parPos);
                if (_positionType == PositionType::FREE)
                {
                    Vec3 diff = convertToNodeSpace3D(currentPosition) - convertToNodeSpace3D(p->startPos);
                    //newPos.x =  p->pos.x - diff.x;
                    //newPos.y =  p->pos.y - diff.y;
                    //newPos.z = - diff.z;
                    newPos = parPos-diff;
                }
                else if(_positionType == PositionType::RELATIVE)
                {
                    Vec3 diff = currentPosition - p->startPos;
                    newPos.x = p->pos.x - diff.x;
                    newPos.y =  p->pos.y - diff.y;
                    newPos.z = - diff.z;
                } 
                else
                {
                    newPos.x = p->pos.x;
                    newPos.y = p->pos.y;
                    newPos.z = 0;
                }

                updateQuadWithParticle(p, newPos);
                //updateParticleImp(self, updateParticleSel, p, newPos);

                // update particle counter
                ++_particleIdx;
            } 
            else 
            {
                // life < 0
                int currentIndex = p->atlasIndex;
                if( _particleIdx != _particleCount-1 )
                {
                    _particles[_particleIdx] = _particles[_particleCount-1];
                }
                --_particleCount;

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

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

    CC_PROFILER_STOP_CATEGORY(kProfilerCategoryParticles , "BillboardParticleSystem - update");
}
    void ParticleSystem::update(fzFloat dt)
    {
        if( m_isActive && m_emissionRate ) {
            fzFloat rate = 1.0f / m_emissionRate;
            m_emitCounter += dt;
            while( m_particleCount < m_totalParticles && m_emitCounter > rate ) {
                addParticle();
                m_emitCounter -= rate;
            }
            
            m_elapsed += dt;
            if(m_duration != -1 && m_duration < m_elapsed)
                stopSystem();
        }
        
        
        m_particleIdx = 0;
        
        while( m_particleIdx < m_particleCount )
        {
            fzParticle& p = p_particles[m_particleIdx];
            
            // life
            p.timeToLive -= dt;
            
            if( p.timeToLive > 0 ) {
                
                // Mode A
                if( m_emitterMode == kFZParticleModeGravity ) {
                    
                    fzPoint tmp(p.pos);
                    if(tmp != FZPointZero)
                    {
                        // calculate tangential
                        fzPoint tangential(tmp.getPerp());
                        tangential.normalize();
                        tangential *= p.mode.A.tangentialAccel;
                        
                        // radial acceleration
                        tmp *= p.mode.A.radialAccel;

                        // radial + tangential
                        tmp += tangential;
                    }
                    
                    // (gravity + dir + radial + tangential) * dt
                    tmp += mode.A.gravity;
                    tmp += p.mode.A.dir;

                    p.pos += tmp * dt;
                }
                
                // Mode B
                else {				
                    // Update the angle and radius of the particle.
                    p.mode.B.angle += p.mode.B.degreesPerSecond * dt;
                    p.mode.B.radius += p.mode.B.deltaRadius * dt;
                    
                    p.pos.x = -fzMath_cos(p.mode.B.angle) * p.mode.B.radius;
                    p.pos.y = -fzMath_sin(p.mode.B.angle) * p.mode.B.radius;
                }
                
                // color
                p.color += p.deltaColor * dt;
                
                // size
                p.size += p.deltaSize * dt;
                p.size = p.size < 0 ? 0 : p.size;
                
                // angle
                p.rotation += p.deltaRotation * dt;
                
                
                // update values in quad
                updateQuadWithParticle(p);
                
                // update particle counter
                ++m_particleIdx;
                
            } else {
                // life < 0
                --m_particleCount;

                if( m_particleIdx != m_particleCount )
                    memmove(&p_particles[m_particleIdx], &p_particles[m_particleCount], sizeof(fzParticle));
                
                if( m_particleCount == 0 && m_autoRemoveOnFinish ) {
                    unschedule();
                    removeFromParent(true);
                    return;
                }
            }
        }
        
        if(m_particleCount)
        makeDirty(0);
        
#if FZ_VBO_STREAMING
        postStep();
#endif
    }
Example #5
0
void NParticleSystemQuad::update(float 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;
        }

        while (_particleCount < _totalParticles && _emitCounter > rate)
        {
            this->addParticle();
            _emitCounter -= rate;
        }

        _elapsed += dt;
        if (_duration != -1 && _duration < _elapsed)
        {
            this->stopSystem();
        }
    }

    _particleIdx = 0;

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

    {
        while (_particleIdx < _particleCount)
        {
            tParticle *p = &_particles[_particleIdx];

            // life
            p->timeToLive -= dt;

            if (p->timeToLive > 0)
            {
                // Mode A: gravity, direction, tangential accel & radial accel
                if (_emitterMode == Mode::GRAVITY)
                {
                    Vec2 tmp, radial, tangential;

                    radial = Vec2::ZERO;
                    // radial acceleration
                    if (p->pos.x || p->pos.y)
                    {
                        radial = p->pos.getNormalized();
                    }
                    tangential = radial;
                    radial = radial * p->modeA.radialAccel;

                    // tangential acceleration
                    float newy = tangential.x;
                    tangential.x = -tangential.y;
                    tangential.y = newy;
                    tangential = tangential * p->modeA.tangentialAccel;

                    // (gravity + radial + tangential) * dt
                    tmp = radial + tangential + modeA.gravity;
                    tmp = tmp * dt;
                    p->modeA.dir = p->modeA.dir + tmp;

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

                    // this is cocos2d-x v3.0
                    tmp = p->modeA.dir * dt * _yCoordFlipped;
                    p->pos = p->pos + tmp;
                }

                // 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 = - cosf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y = - sinf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y *= _yCoordFlipped;
                }

                // 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);
                p->size = MAX( 0, p->size );

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

                //
                // update values in quad
                //

                Vec2    newPos;

                if (_positionType == PositionType::FREE || _positionType == PositionType::RELATIVE)
                {
                    Vec2 diff = currentPosition - p->startPos;
                    newPos = p->pos - diff;
                }
                else
                {
                    newPos = p->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 (_batchNode)
                {
                    newPos.x+=_position.x;
                    newPos.y+=_position.y;
                }

                updateQuadWithParticle(p, newPos);
                //updateParticleImp(self, updateParticleSel, p, newPos);

                // update particle counter
                ++_particleIdx;
            }
            else
            {
                // life < 0
                int currentIndex = p->atlasIndex;
                if( _particleIdx != _particleCount-1 )
                {
                    _particles[_particleIdx] = _particles[_particleCount-1];
                }
                if (_batchNode)
                {
                    //disable the switched particle
                    _batchNode->disableParticle(_atlasIndex+currentIndex);

                    //switch indexes
                    _particles[_particleCount-1].atlasIndex = currentIndex;
                }


                --_particleCount;

                if( _particleCount == 0 && _isAutoRemoveOnFinish )
                {

                    this->unscheduleUpdate();
                    _parent->removeChild(this, true);
                    // 親から remove されるときにコールバック関数を呼ぶ
                    if (onFinishListener) {
                        onFinishListener(this);
                    }
                    return;
                }
            }
        } //while
        _transformSystemDirty = false;
    }

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

    CC_PROFILER_STOP_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update");
}