# Please review my simple particle system

## Recommended Posts

I created a simple particle system in C++ using classes. It is a 2D system. It works for now. I plan on adding extra options to the system, that's why certain variables are not really used yet. Thanks in forward. psystem.h
#include "particle.h"

class ParticleSystem
{
private:

std::vector<Particle> system;

double gravfactor;

// The box limits in which the Particles may live
int xleft;
int xright;
int ytop;
int ybottom;
// A margin in case the particles are represented by something bigger than a pixel
int margin;

public:

ParticleSystem( int xleft, int xright, int ytop, int ybottom, int margin, double gravfactor );

void AddPtc( int x, int y, double velocity, double angle );
void CreateExplosion( int size, int x, int y, double minvel, double maxvel );

void UpdateAll( int deltatime );
void ChangeGrav( double newgravfactor );

int Size();
int GetX( int i );
int GetY( int i );

};

ParticleSystem::ParticleSystem( int xleft, int xright, int ytop, int ybottom, int margin, double gravfactor )
: gravfactor(gravfactor),
xleft(xleft),
xright(xright),
ytop(ytop),
ybottom(ybottom),
margin(margin)
{
}

void ParticleSystem::AddPtc( int x, int y, double velocity, double angle )
{
system.push_back( Particle( x, y, velocity, angle, system.size() ) );
}

void ParticleSystem::CreateExplosion( int size, int x, int y, double minvel, double maxvel )
{
for( int i = 0; i < size; i++ ) {
system.push_back( Particle( x, y,
(double)(rand() %(int)((maxvel-minvel) * 100)) / 100.0 + minvel, // minvel to maxvel (.00)
(double)(rand() %360),
system.size() ) );
}
}

void ParticleSystem::UpdateAll( int deltatime )
{
for( unsigned int i = 0; i < system.size(); i++ ) {
system[i].Update( deltatime, gravfactor );
}

std::vector<Particle>::iterator iter;

for( iter = system.begin(); iter != system.end(); iter++ ) {
if( iter->GetX() + margin < xleft ) {
system.erase( iter );
iter--;
}
else if( iter->GetX() - margin > xright ) {
system.erase( iter );
iter--;
}
else if( ( iter->GetY() + margin < ytop ) && ( gravfactor <= 0 ) ) {
system.erase( iter );
iter--;
}
else if( ( iter->GetY() - margin > ybottom ) && ( gravfactor >= 0 ) ) {
system.erase( iter );
iter--;
}
}
}

void ParticleSystem::ChangeGrav( double newgravfactor )
{
gravfactor = newgravfactor;
}

int ParticleSystem::Size()
{
return system.size();
}

int ParticleSystem::GetX( int i )
{
return xleft + system[i].GetX();
}

int ParticleSystem::GetY( int i )
{
return ytop + system[i].GetY();
}


particle.h
class Particle
{
private:

int ID;
// Coordinates
double posx;
double posy;
// Velocity in px/ms
double velx;
double vely;
// Lifespan in ms
int age;
// Gravitational stuff
double GRAVITY;

// Functions
double toRad( double angdeg ) { return angdeg / 180.0 * 3.14; }

public:

Particle();
Particle( int x, int y, double velocity, double angle, int id );

void Update( int deltatime, double gravfactor );

int GetX() { return (int)posx; }
int GetY() { return (int)posy; }
int GetID() { return ID; }

};

// Default constructor
Particle::Particle()
: ID(-1),
posx(0.0),
posy(0.0),
velx(0.0),
vely(0.0),
age(0),
GRAVITY(8.91)
{
}

Particle::Particle( int x, int y, double velocity, double angle, int id )
: ID(id),
posx(x),
posy(y),
velx(0),
vely(0),
age(0),
GRAVITY(8.91)
{
}

// Update a particle
void Particle::Update( int deltatime, double gravfactor )
{
// Update position
posx += velx * deltatime;
posy += vely * deltatime;
// Update velocity
vely += ((GRAVITY * gravfactor) / 6000) * deltatime; // 6000 is a factor obtained experimentally
// We get older over time...
age++;
}



##### Share on other sites
- Do not implement class members in the .h header files, use .cpp files!
- Do you really need double precision? float is more than enough in most cases
- You should use a vector class instead of X/Y pairs
- You should allow gravity to be on an arbitrary axis, not only -Y
- Use pre-incrementation unless you need post-incrementation
- erase(iter) followed by iter-- might work for std::vectors, but I doubt it will for other data structures. You might try to find another way of doing this.
- In ParticleSystem::UpdateAll, you should combine your conditionnal statements using ||
- Many occurances of truncation from size_t to int, it's not the end of the world but that's not a good habit (at least use static_cast<> or you'll get compiler warnings).
- Why is Particle::GRAVITY in full caps?
- That experimentally obtained "6000" number looks like a magic number to me
- Increase your particle age by deltaTime to be frame-time independant
- Use a real number for the deltaTime, not an integer
- Might be a good idea to find an alternative to rand(), but again it's not the end of the world.
- You don't seem to be using the particle age for anything

That's a lot of stuff, but you don't have to be that much strict. Your particle system is a bit basic but, even in its current state, it should do the job well for simple games.

##### Share on other sites
Quote:
 Original post by Trillian- Do not implement class members in the .h header files, use .cpp files!

I read a tutorial on how to do this, but when i tried converting my Tetris application to this system, I couldn't get it to work... I shall reattempt some other time.
Quote:
 - Do you really need double precision? float is more than enough in most cases

You're probably right, I've always used doubles, that's probably why I used them now.
Quote:
 - You should use a vector class instead of X/Y pairs

I don't understand how I can use a vector to store two coordinates more effectively.
Quote:
 - You should allow gravity to be on an arbitrary axis, not only -Y

This is probably a good idea. Gravity is also on +Y right now btw, by using a negative gravfactor ;)
Quote:
 - Use pre-incrementation unless you need post-incrementation

I'm guessing this is relating to the Particle::Update() function.
Quote:
 - erase(iter) followed by iter-- might work for std::vectors, but I doubt it will for other data structures. You might try to find another way of doing this.

Quote:
 - In ParticleSystem::UpdateAll, you should combine your conditionnal statements using ||

Ah yes, good idea. The long list of if's is from the time when I had different debug messages printing to the console for all those conditions
Quote:
 - Many occurances of truncation from size_t to int, it's not the end of the world but that's not a good habit (at least use static_cast<> or you'll get compiler warnings).

Surprisingly I don't get any warnings, even though I set my compiler to -pedantic
Quote:
 - Why is Particle::GRAVITY in full caps?

Because it's a constant. I always write my constants in full caps. I can't actually make it a constant though, seeing classes don't allow that.
Quote:
 - That experimentally obtained "6000" number looks like a magic number to me

It is ;) If I don't use it, the particles will fly down instantly (accelerating at a staggering 8.91 px/ms²). By experimenting I found that the value 6000 allows for something one could experience as natural gravity when using gravfactor = 1.0.
Quote:
 - Increase your particle age by deltaTime to be frame-time independant

Good idea.
Quote:
 - Use a real number for the deltaTime, not an integer

What is a real number? Why is an intenger not a real number? I'm using integers to represent the amount of ms passed by.
Quote:
 - Might be a good idea to find an alternative to rand(), but again it's not the end of the world.

I wouldn't know any alternative.
Quote:
 - You don't seem to be using the particle age for anything

Not yet, as stated in the OP ;) I'm planning on using it in the System, where particles die after they reach a certain age.

Quote:
 That's a lot of stuff, but you don't have to be that much strict. Your particle system is a bit basic but, even in its current state, it should do the job well for simple games.

It is meant as an experiment really. I'm planning on using it to have some pretty effects in my Tetris game.

## Create an account

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627638
• Total Posts
2978327

• 10
• 12
• 22
• 13
• 34