Improvements against http://code.google.com/p/wagic/issues/detail?id=50, Mana animation slows PSP down.
Two things: 1) there was an extremely inefficient implementation in the particle system of a queue where, when particles expired, each expired element would be copied over(replaced) by one at the rear of the container. Depending on the performance of the update, this could range anywhere from 100 to 500 (the max particle count) memcpy operations per update loop. I replaced the flat array with a std::list, and simply pop the unneeded elements when they expire now. This seems to shave ~30% off the time spent in the Update() call. 2) Hardcoded the number of emitters for the mana particles to 60 (the default in the psi file seems to be around 114). This reduces the amount of iterations per tapped mana by just over half, which also helps the performance, and it's not really noticeable - the glow effect is a *tiny* bit more muted, but chances are, if you didn't read this comment, you probably wouldn't have noticed. I've gone from having my psp start lagging noticeably at 8 tapped mana to about 12 - at this point, I think the bigger remaining lag is the fact that when there's a cache miss for a card image, we're doing synchronous i/o on the main thread - the framerate drop this causes is far more noticable than the mana particle lag.
This commit is contained in:
@@ -17,6 +17,8 @@
|
||||
#include "hgecolor.h"
|
||||
#include "hgerect.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
class JQuad;
|
||||
|
||||
#define MAX_PARTICLES 500
|
||||
@@ -127,7 +129,8 @@ private:
|
||||
hgeRect rectBoundingBox;
|
||||
bool bUpdateBoundingBox;
|
||||
|
||||
hgeParticle particles[MAX_PARTICLES];
|
||||
typedef std::list<hgeParticle> ParticleBuffer;
|
||||
ParticleBuffer mParticleBuffer;
|
||||
|
||||
float mTimer;
|
||||
};
|
||||
|
||||
Binary file not shown.
@@ -121,7 +121,6 @@ void hgeParticleSystem::Update(float fDeltaTime)
|
||||
{
|
||||
int i;
|
||||
float ang;
|
||||
hgeParticle *par;
|
||||
hgeVector vecAccel, vecAccel2;
|
||||
|
||||
if(fAge >= 0)
|
||||
@@ -141,24 +140,23 @@ void hgeParticleSystem::Update(float fDeltaTime)
|
||||
// update all alive particles
|
||||
|
||||
if(bUpdateBoundingBox) rectBoundingBox.Clear();
|
||||
par=particles;
|
||||
|
||||
for(i=0; i<nParticlesAlive; i++)
|
||||
ParticleBuffer::iterator particle = mParticleBuffer.begin();
|
||||
while(particle != mParticleBuffer.end())
|
||||
{
|
||||
par->fAge += fDeltaTime;
|
||||
if(par->fAge >= par->fTerminalAge)
|
||||
particle->fAge += fDeltaTime;
|
||||
if(particle->fAge >= particle->fTerminalAge)
|
||||
{
|
||||
nParticlesAlive--;
|
||||
if (par != &particles[nParticlesAlive])
|
||||
memcpy(par, &particles[nParticlesAlive], sizeof(hgeParticle));
|
||||
i--;
|
||||
++particle;
|
||||
mParticleBuffer.pop_front();
|
||||
continue;
|
||||
}
|
||||
|
||||
vecAccel = par->vecLocation-vecLocation;
|
||||
vecAccel = particle->vecLocation-vecLocation;
|
||||
vecAccel.Normalize();
|
||||
vecAccel2 = vecAccel;
|
||||
vecAccel *= par->fRadialAccel;
|
||||
vecAccel *= particle->fRadialAccel;
|
||||
|
||||
// vecAccel2.Rotate(M_PI_2);
|
||||
// the following is faster
|
||||
@@ -166,20 +164,20 @@ void hgeParticleSystem::Update(float fDeltaTime)
|
||||
vecAccel2.x = -vecAccel2.y;
|
||||
vecAccel2.y = ang;
|
||||
|
||||
vecAccel2 *= par->fTangentialAccel;
|
||||
par->vecVelocity += (vecAccel+vecAccel2)*fDeltaTime;
|
||||
par->vecVelocity.y += par->fGravity*fDeltaTime;
|
||||
vecAccel2 *= particle->fTangentialAccel;
|
||||
particle->vecVelocity += (vecAccel+vecAccel2)*fDeltaTime;
|
||||
particle->vecVelocity.y += particle->fGravity*fDeltaTime;
|
||||
|
||||
//par->vecVelocity.y = 0.1f;
|
||||
par->vecLocation += par->vecVelocity;
|
||||
particle->vecLocation += particle->vecVelocity;
|
||||
|
||||
par->fSpin += par->fSpinDelta*fDeltaTime;
|
||||
par->fSize += par->fSizeDelta*fDeltaTime;
|
||||
par->colColor += par->colColorDelta*fDeltaTime;
|
||||
particle->fSpin += particle->fSpinDelta*fDeltaTime;
|
||||
particle->fSize += particle->fSizeDelta*fDeltaTime;
|
||||
particle->colColor += particle->colColorDelta*fDeltaTime;
|
||||
|
||||
if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y);
|
||||
if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(particle->vecLocation.x, particle->vecLocation.y);
|
||||
|
||||
par++;
|
||||
++particle;
|
||||
}
|
||||
|
||||
// generate new particles
|
||||
@@ -190,49 +188,48 @@ void hgeParticleSystem::Update(float fDeltaTime)
|
||||
int nParticlesCreated = (unsigned int)fParticlesNeeded;
|
||||
fEmissionResidue=fParticlesNeeded-nParticlesCreated;
|
||||
|
||||
par=&particles[nParticlesAlive];
|
||||
|
||||
for(i=0; i<nParticlesCreated; i++)
|
||||
{
|
||||
if(nParticlesAlive>=MAX_PARTICLES) break;
|
||||
|
||||
par->fAge = 0.0f;
|
||||
par->fTerminalAge = Random_Float(info.fParticleLifeMin, info.fParticleLifeMax);
|
||||
hgeParticle newParticle;
|
||||
newParticle.fAge = 0.0f;
|
||||
newParticle.fTerminalAge = Random_Float(info.fParticleLifeMin, info.fParticleLifeMax);
|
||||
|
||||
par->vecLocation = vecPrevLocation+(vecLocation-vecPrevLocation)*Random_Float(0.0f, 1.0f);
|
||||
par->vecLocation.x += Random_Float(-2.0f, 2.0f);
|
||||
par->vecLocation.y += Random_Float(-2.0f, 2.0f);
|
||||
newParticle.vecLocation = vecPrevLocation+(vecLocation-vecPrevLocation)*Random_Float(0.0f, 1.0f);
|
||||
newParticle.vecLocation.x += Random_Float(-2.0f, 2.0f);
|
||||
newParticle.vecLocation.y += Random_Float(-2.0f, 2.0f);
|
||||
|
||||
ang=info.fDirection-M_PI_2+Random_Float(0,info.fSpread)-info.fSpread/2.0f;
|
||||
if(info.bRelative) ang += (vecPrevLocation-vecLocation).Angle()+M_PI_2;
|
||||
par->vecVelocity.x = cosf(ang);
|
||||
par->vecVelocity.y = sinf(ang);
|
||||
par->vecVelocity *= Random_Float(info.fSpeedMin, info.fSpeedMax);
|
||||
newParticle.vecVelocity.x = cosf(ang);
|
||||
newParticle.vecVelocity.y = sinf(ang);
|
||||
newParticle.vecVelocity *= Random_Float(info.fSpeedMin, info.fSpeedMax);
|
||||
|
||||
par->fGravity = Random_Float(info.fGravityMin, info.fGravityMax);
|
||||
par->fRadialAccel = Random_Float(info.fRadialAccelMin, info.fRadialAccelMax);
|
||||
par->fTangentialAccel = Random_Float(info.fTangentialAccelMin, info.fTangentialAccelMax);
|
||||
newParticle.fGravity = Random_Float(info.fGravityMin, info.fGravityMax);
|
||||
newParticle.fRadialAccel = Random_Float(info.fRadialAccelMin, info.fRadialAccelMax);
|
||||
newParticle.fTangentialAccel = Random_Float(info.fTangentialAccelMin, info.fTangentialAccelMax);
|
||||
|
||||
par->fSize = Random_Float(info.fSizeStart, info.fSizeStart+(info.fSizeEnd-info.fSizeStart)*info.fSizeVar);
|
||||
par->fSizeDelta = (info.fSizeEnd-par->fSize) / par->fTerminalAge;
|
||||
newParticle.fSize = Random_Float(info.fSizeStart, info.fSizeStart+(info.fSizeEnd-info.fSizeStart)*info.fSizeVar);
|
||||
newParticle.fSizeDelta = (info.fSizeEnd-newParticle.fSize) / newParticle.fTerminalAge;
|
||||
|
||||
par->fSpin = Random_Float(info.fSpinStart, info.fSpinStart+(info.fSpinEnd-info.fSpinStart)*info.fSpinVar);
|
||||
par->fSpinDelta = (info.fSpinEnd-par->fSpin) / par->fTerminalAge;
|
||||
newParticle.fSpin = Random_Float(info.fSpinStart, info.fSpinStart+(info.fSpinEnd-info.fSpinStart)*info.fSpinVar);
|
||||
newParticle.fSpinDelta = (info.fSpinEnd-newParticle.fSpin) / newParticle.fTerminalAge;
|
||||
|
||||
par->colColor.r = Random_Float(info.colColorStart.r, info.colColorStart.r+(info.colColorEnd.r-info.colColorStart.r)*info.fColorVar);
|
||||
par->colColor.g = Random_Float(info.colColorStart.g, info.colColorStart.g+(info.colColorEnd.g-info.colColorStart.g)*info.fColorVar);
|
||||
par->colColor.b = Random_Float(info.colColorStart.b, info.colColorStart.b+(info.colColorEnd.b-info.colColorStart.b)*info.fColorVar);
|
||||
par->colColor.a = Random_Float(info.colColorStart.a, info.colColorStart.a+(info.colColorEnd.a-info.colColorStart.a)*info.fAlphaVar);
|
||||
newParticle.colColor.r = Random_Float(info.colColorStart.r, info.colColorStart.r+(info.colColorEnd.r-info.colColorStart.r)*info.fColorVar);
|
||||
newParticle.colColor.g = Random_Float(info.colColorStart.g, info.colColorStart.g+(info.colColorEnd.g-info.colColorStart.g)*info.fColorVar);
|
||||
newParticle.colColor.b = Random_Float(info.colColorStart.b, info.colColorStart.b+(info.colColorEnd.b-info.colColorStart.b)*info.fColorVar);
|
||||
newParticle.colColor.a = Random_Float(info.colColorStart.a, info.colColorStart.a+(info.colColorEnd.a-info.colColorStart.a)*info.fAlphaVar);
|
||||
|
||||
par->colColorDelta.r = (info.colColorEnd.r-par->colColor.r) / par->fTerminalAge;
|
||||
par->colColorDelta.g = (info.colColorEnd.g-par->colColor.g) / par->fTerminalAge;
|
||||
par->colColorDelta.b = (info.colColorEnd.b-par->colColor.b) / par->fTerminalAge;
|
||||
par->colColorDelta.a = (info.colColorEnd.a-par->colColor.a) / par->fTerminalAge;
|
||||
newParticle.colColorDelta.r = (info.colColorEnd.r-newParticle.colColor.r) / newParticle.fTerminalAge;
|
||||
newParticle.colColorDelta.g = (info.colColorEnd.g-newParticle.colColor.g) / newParticle.fTerminalAge;
|
||||
newParticle.colColorDelta.b = (info.colColorEnd.b-newParticle.colColor.b) / newParticle.fTerminalAge;
|
||||
newParticle.colColorDelta.a = (info.colColorEnd.a-newParticle.colColor.a) / newParticle.fTerminalAge;
|
||||
|
||||
if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y);
|
||||
if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(newParticle.vecLocation.x, newParticle.vecLocation.y);
|
||||
|
||||
nParticlesAlive++;
|
||||
par++;
|
||||
mParticleBuffer.push_back(newParticle);
|
||||
++nParticlesAlive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +238,6 @@ void hgeParticleSystem::Update(float fDeltaTime)
|
||||
|
||||
void hgeParticleSystem::MoveTo(float x, float y, bool bMoveParticles)
|
||||
{
|
||||
int i;
|
||||
float dx,dy;
|
||||
|
||||
if(bMoveParticles)
|
||||
@@ -249,10 +245,11 @@ void hgeParticleSystem::MoveTo(float x, float y, bool bMoveParticles)
|
||||
dx=x-vecLocation.x;
|
||||
dy=y-vecLocation.y;
|
||||
|
||||
for(i=0;i<nParticlesAlive;i++)
|
||||
ParticleBuffer::iterator particle = mParticleBuffer.begin();
|
||||
for (; particle != mParticleBuffer.end(); ++particle)
|
||||
{
|
||||
particles[i].vecLocation.x += dx;
|
||||
particles[i].vecLocation.y += dy;
|
||||
particle->vecLocation.x += dx;
|
||||
particle->vecLocation.y += dy;
|
||||
}
|
||||
|
||||
vecPrevLocation.x=vecPrevLocation.x + dx;
|
||||
@@ -289,24 +286,21 @@ void hgeParticleSystem::Stop(bool bKillParticles)
|
||||
if(bKillParticles)
|
||||
{
|
||||
nParticlesAlive=0;
|
||||
mParticleBuffer.clear();
|
||||
rectBoundingBox.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void hgeParticleSystem::Render()
|
||||
{
|
||||
int i;
|
||||
// DWORD col;
|
||||
hgeParticle *par=particles;
|
||||
|
||||
//col=info.sprite->GetColor();
|
||||
|
||||
for(i=0; i<nParticlesAlive; i++)
|
||||
ParticleBuffer::iterator particle = mParticleBuffer.begin();
|
||||
for (;particle != mParticleBuffer.end(); ++particle)
|
||||
{
|
||||
info.sprite->SetColor(par->colColor.GetHWColor());
|
||||
JRenderer::GetInstance()->RenderQuad(info.sprite, par->vecLocation.x+fTx, par->vecLocation.y+fTy, par->fSpin*par->fAge, par->fSize, par->fSize);
|
||||
par++;
|
||||
info.sprite->SetColor(particle->colColor.GetHWColor());
|
||||
JRenderer::GetInstance()->RenderQuad(
|
||||
info.sprite,
|
||||
particle->vecLocation.x+fTx, particle->vecLocation.y+fTy,
|
||||
particle->fSpin * particle->fAge,
|
||||
particle->fSize, particle->fSize);
|
||||
}
|
||||
|
||||
//info.sprite->SetColor(col);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,9 @@ ManaIcon::ManaIcon(int color, float x, float y, float destx, float desty) : Pos(
|
||||
else
|
||||
particleSys = NEW hgeParticleSystem(psi); //Cache will clean psi up later.
|
||||
|
||||
|
||||
// if we want to throttle the amount of particles for mana,
|
||||
// here's where to do it - this is hardcoded to something like 114 in the psi file
|
||||
particleSys->info.nEmission = 60;
|
||||
icon = manaIcons[color];
|
||||
|
||||
particleSys->FireAt(x, y);
|
||||
@@ -252,15 +254,15 @@ void GuiMana::RenderStatic(){
|
||||
|
||||
void GuiMana::Render()
|
||||
{
|
||||
|
||||
for (vector<ManaIcon*>::iterator it = manas.begin(); it != manas.end(); ++it)
|
||||
(*it)->Render();
|
||||
|
||||
if (OptionManaDisplay::DYNAMIC != options[Options::MANADISPLAY].number)
|
||||
RenderStatic();
|
||||
|
||||
}
|
||||
|
||||
bool remove_dead(ManaIcon* m) { return ManaIcon::DEAD != m->mode; }
|
||||
|
||||
void GuiMana::Update(float dt)
|
||||
{
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user