www.pudn.com > 2DGameAnimS60C_v1_0.zip > ParticleSystem.cpp
//////////////////////////////////////////////////////////////////////// // // ParticleSystem.cpp // // Copyright (c) 2003 Nokia Mobile Phones Ltd. All rights reserved. // //////////////////////////////////////////////////////////////////////// #include#include "RenderableFactory.h" #include "BaseAnim.h" #include "ParticleSystem.h" //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// TVectorFP::TVectorFP() { iX = 0; iY = 0; } //////////////////////////////////////////////////////////////////////// TVectorFP::TVectorFP(const TPoint& aPoint) { iX = aPoint.iX; iY = aPoint.iY; } //////////////////////////////////////////////////////////////////////// TPoint TVectorFP::ScaleToPoint(TInt aFactor) const { TPoint result; result.iX = ( iX * aFactor ) >> 8; result.iY = ( iY * aFactor ) >> 8; return result; } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// TParticle::TParticle() { Reset(); } //////////////////////////////////////////////////////////////////////// void TParticle::Reset() { iVirtualFrameNum = -1; } //////////////////////////////////////////////////////////////////////// void TParticle::Start(TInt aVirtualFrameNum,TInt aDeltaVFN,TInt aMaxVFN,TPoint aPosition,TPoint aVelocity,TInt aDragRatio) { iVirtualFrameNum = aVirtualFrameNum; iDeltaVFN = aDeltaVFN; iMaxVFN = aMaxVFN; iPosition = aPosition; iVelocity = aVelocity; iDragRatio = aDragRatio; } //////////////////////////////////////////////////////////////////////// void TParticle::Simulate() { if ( !IsActive() ) { return; } else { iVirtualFrameNum += iDeltaVFN; // Have we finished yet? if (iVirtualFrameNum >= iMaxVFN) { // Yes, so switch off: Reset(); } iPosition += iVelocity; iVelocity.iX = ( iVelocity.iX * iDragRatio ) >> dragRatioDownshift; iVelocity.iY = ( iVelocity.iY * iDragRatio ) >> dragRatioDownshift; } } //////////////////////////////////////////////////////////////////////// TBool TParticle::IsActive() const { return iVirtualFrameNum >= 0; } //////////////////////////////////////////////////////////////////////// void TParticle::Render(CBaseAnim& aAnim, const TPoint& aOrigin,const TRect& aScreenRect,CFbsBitGc* aCallerGc) const { if ( IsActive() ) { TInt screenX = ( iPosition.iX >> 4 ) - aOrigin.iX; TInt screenY = ( iPosition.iY >> 4 ) - aOrigin.iY; TPoint screenPos( screenX, screenY ); aAnim.RenderFrameCentered(iVirtualFrameNum >> 8,screenPos,aScreenRect,aCallerGc); } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// CParticleSystem::CParticleSystem(CBaseAnim& aAnim) : iAnim(aAnim) { // A "don't care" value: iSeed = 3141592; } //////////////////////////////////////////////////////////////////////// CParticleSystem* CParticleSystem::NewL(TInt aMaxParticles,CBaseAnim& aAnim) { CParticleSystem* self = new(ELeave) CParticleSystem(aAnim); CleanupStack::PushL(self); self->ConstructL(aMaxParticles); CleanupStack::Pop(); return self; } //////////////////////////////////////////////////////////////////////// CParticleSystem::~CParticleSystem() { delete[] iParticles; iParticles = NULL; } //////////////////////////////////////////////////////////////////////// void CParticleSystem::ConstructL(TInt aMaxParticles) { iMaxParticles = aMaxParticles; iParticles = new TParticle[ aMaxParticles ]; User::LeaveIfNull(iParticles); Reset(); } //////////////////////////////////////////////////////////////////////// void CParticleSystem::Reset() { for ( TInt p = 0 ; p < iMaxParticles ; p++ ) { iParticles[ p ].Reset(); } iNextParticleIndex = 0; } //////////////////////////////////////////////////////////////////////// void CParticleSystem::Simulate() { for ( TInt p = 0 ; p < iMaxParticles ; p++ ) { iParticles[ p ].Simulate(); } } //////////////////////////////////////////////////////////////////////// void CParticleSystem::Render(const TPoint& aOrigin,const TRect& aScreenRect,CFbsBitGc* aCallerGc) const { // // We take care to maintain a consistent drawing order, // oldest ( == least recently started ) first: // TInt p; for ( p = iNextParticleIndex - 1 ; p >= 0 ; p-- ) { iParticles[ p ].Render(iAnim,aOrigin,aScreenRect,aCallerGc); } for ( p = iMaxParticles - 1 ; p >= iNextParticleIndex ; p-- ) { iParticles[ p ].Render(iAnim,aOrigin,aScreenRect,aCallerGc); } } //////////////////////////////////////////////////////////////////////// void CParticleSystem::Generate(const TPoint& aWorldPos, const TVectorFP& aVector, const TPoint& aGeneratorVelocity, const TInt aRadius, const TInt aSpeed) { TParticle * p_particle = &iParticles[ iNextParticleIndex ]; iNextParticleIndex++; if (iNextParticleIndex >= iMaxParticles) { iNextParticleIndex = 0; } // We start the particle downrange from the notional point of origin: TPoint position = aWorldPos + aVector.ScaleToPoint(aRadius); // The particle's initial velocity includes a component from the generator's own motion: TPoint velocity = aGeneratorVelocity + aVector.ScaleToPoint(aSpeed); // Generate a (pseudo-)random integer for use in setting // parameters for the new particle. We only want the topmost // few bits of the Math::Rand() result, since these have the // least "pattern" to them: TInt random = Math::Rand(iSeed) >> 22; // Decide how fast to run the animation for the new particle. // A deltaVFN of 0x0100 implies an animation rate of one frame // per simulation cycle (that is, we will get a rate of between // 1 and 1.5 frames per simulation cycle): TInt randDeltaVFN = 0x0100 + ( random & 0x7f ); // Decide which animation frame to start our particle on. // A VFN of 0x0100 corresponds to frame #1 (that is, we skip // frame #0 of the animation 50% of the time): TInt randVFN = random & 0x0100; p_particle->Start(randVFN,randDeltaVFN,0x0fff,position,velocity,0x00e0); } //////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////