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.
166 lines
3.5 KiB
C++
166 lines
3.5 KiB
C++
/*
|
|
** Haaf's Game Engine 1.7
|
|
** Copyright (C) 2003-2007, Relish Games
|
|
** hge.relishgames.com
|
|
**
|
|
** hgeParticleSystem helper class header
|
|
*/
|
|
|
|
|
|
#ifndef HGEPARTICLE_H
|
|
#define HGEPARTICLE_H
|
|
|
|
|
|
//#include "hge.h"
|
|
//#include "hgesprite.h"
|
|
#include "hgevector.h"
|
|
#include "hgecolor.h"
|
|
#include "hgerect.h"
|
|
|
|
#include <list>
|
|
|
|
class JQuad;
|
|
|
|
#define MAX_PARTICLES 500
|
|
#define MAX_PSYSTEMS 100
|
|
|
|
struct hgeParticle
|
|
{
|
|
hgeVector vecLocation;
|
|
hgeVector vecVelocity;
|
|
|
|
float fGravity;
|
|
float fRadialAccel;
|
|
float fTangentialAccel;
|
|
|
|
float fSpin;
|
|
float fSpinDelta;
|
|
|
|
float fSize;
|
|
float fSizeDelta;
|
|
|
|
hgeColor colColor; // + alpha
|
|
hgeColor colColorDelta;
|
|
|
|
float fAge;
|
|
float fTerminalAge;
|
|
};
|
|
|
|
struct hgeParticleSystemInfo
|
|
{
|
|
JQuad* sprite; // texture + blend mode
|
|
int nEmission; // particles per sec
|
|
float fLifetime;
|
|
|
|
float fParticleLifeMin;
|
|
float fParticleLifeMax;
|
|
|
|
float fDirection;
|
|
float fSpread;
|
|
bool bRelative;
|
|
|
|
float fSpeedMin;
|
|
float fSpeedMax;
|
|
|
|
float fGravityMin;
|
|
float fGravityMax;
|
|
|
|
float fRadialAccelMin;
|
|
float fRadialAccelMax;
|
|
|
|
float fTangentialAccelMin;
|
|
float fTangentialAccelMax;
|
|
|
|
float fSizeStart;
|
|
float fSizeEnd;
|
|
float fSizeVar;
|
|
|
|
float fSpinStart;
|
|
float fSpinEnd;
|
|
float fSpinVar;
|
|
|
|
hgeColor colColorStart; // + alpha
|
|
hgeColor colColorEnd;
|
|
float fColorVar;
|
|
float fAlphaVar;
|
|
};
|
|
|
|
class hgeParticleSystem
|
|
{
|
|
public:
|
|
hgeParticleSystemInfo info;
|
|
|
|
hgeParticleSystem(const char *filename, JQuad *sprite);
|
|
hgeParticleSystem(hgeParticleSystemInfo *psi);
|
|
hgeParticleSystem(const hgeParticleSystem &ps);
|
|
~hgeParticleSystem() { }
|
|
|
|
hgeParticleSystem& operator= (const hgeParticleSystem &ps);
|
|
|
|
|
|
void Render();
|
|
void FireAt(float x, float y);
|
|
void Fire();
|
|
void Stop(bool bKillParticles=false);
|
|
void Update(float fDeltaTime);
|
|
void MoveTo(float x, float y, bool bMoveParticles=false);
|
|
void Transpose(float x, float y) { fTx=x; fTy=y; }
|
|
void TrackBoundingBox(bool bTrack) { bUpdateBoundingBox=bTrack; }
|
|
|
|
int GetParticlesAlive() const { return nParticlesAlive; }
|
|
float GetAge() const { return fAge; }
|
|
void GetPosition(float *x, float *y) const { *x=vecLocation.x; *y=vecLocation.y; }
|
|
void GetTransposition(float *x, float *y) const { *x=fTx; *y=fTy; }
|
|
hgeRect* GetBoundingBox(hgeRect *rect) const { memcpy(rect, &rectBoundingBox, sizeof(hgeRect)); return rect; }
|
|
|
|
private:
|
|
hgeParticleSystem();
|
|
|
|
//static HGE *hge;
|
|
|
|
float fAge;
|
|
float fEmissionResidue;
|
|
|
|
hgeVector vecPrevLocation;
|
|
hgeVector vecLocation;
|
|
float fTx, fTy;
|
|
|
|
int nParticlesAlive;
|
|
hgeRect rectBoundingBox;
|
|
bool bUpdateBoundingBox;
|
|
|
|
typedef std::list<hgeParticle> ParticleBuffer;
|
|
ParticleBuffer mParticleBuffer;
|
|
|
|
float mTimer;
|
|
};
|
|
|
|
class hgeParticleManager
|
|
{
|
|
public:
|
|
hgeParticleManager();
|
|
~hgeParticleManager();
|
|
|
|
void Update(float dt);
|
|
void Render();
|
|
|
|
hgeParticleSystem* SpawnPS(hgeParticleSystemInfo *psi, float x, float y);
|
|
bool IsPSAlive(hgeParticleSystem *ps) const;
|
|
void Transpose(float x, float y);
|
|
void GetTransposition(float *dx, float *dy) const {*dx=tX; *dy=tY;}
|
|
void KillPS(hgeParticleSystem *ps);
|
|
void KillAll();
|
|
|
|
private:
|
|
hgeParticleManager(const hgeParticleManager &);
|
|
hgeParticleManager& operator= (const hgeParticleManager &);
|
|
|
|
int nPS;
|
|
float tX;
|
|
float tY;
|
|
hgeParticleSystem* psList[MAX_PSYSTEMS];
|
|
};
|
|
|
|
|
|
#endif
|