Advertisement

Creating multiple particle emitters

Started by June 20, 2003 08:48 AM
5 comments, last by Billy Lee 21 years, 8 months ago
I''ve implemented the lesson 19 particle system. I have now put it in a class Particles() so that I can create multiple instances of it. I''m trying to have a trail of particles that follow each bullet fired from the spaceship.

Particles bullet_particles[3] = {Particles(), Particles(), Particles()};

GLvoid initBulletParticles()
{
	for (int count = 0; count < 3; count++)
	{
		bullet_particles[count].initialiseParticles();
	}

} // End of method initBulletParticles


int initGL()
{
        initBulletParticles();
...
}
I don''t think this is the right way to do it though. For the trial of particles following the spaceship, I do this:

Particles		*ship_particles = NULL;

GLvoid initShipParticles()
{
	ship_particles = new Particles();
	ship_particles->initialiseParticles();
}

int initGL()
{
	initShipParticles();
...
}
I tried doing it this way for the bullets but it doesn''t compile due to the array. Can anyone help?
Hmm? If I understand your code correctly, you are trying to hard-code the number of bullets that will be fired. In general, this is a bad thing.

Perhaps a better method would be to add a Particles member to the bullet type. That way when a bullet is created, its particles are too. (Don''t forget to initialize the particles in the bullet''s constructor). The only slight graphical problem you might have with that is that when the bullet hits something/is destroyed, the particles will just dissapear.

Perhaps one way around this is to add some kind of global particle tracking class that keeps tabs on all of the particles. This way when your bullet dies, the particle could be detatched and sent to the tracker ( or it would probably of been better for them to start off there! ) and you wait for all of the particles to fade out, then you delete the particles.

Of course all of that is just theoretical, and me being the one that wrote it I doubt much of it will work

Oh, and you probably want to restructure your particles a bit. How I have them set up in my program is that I have an Emitter class which defines all of the constant properties of the collection of particles (Spawn delays, gravity, drag, ect) and then it has a member which is a pointer to the actual particles. When I create the emitter I have to specify how many particles there are going to be (along with all of the other properties) and the emitter allocates the exact amount of memory needed for all of those particles (Along with vertex/index buffers, those make for speedy drawing)
Advertisement
Could you post an example of your code? I''m still having trouble. I''ve been changing my code, trying several alternatives but it seems like all my particles are global rather than in their own classes. When I fire a bullet, all the particles get brighter, probably because they are being overlapped by new particles in the exact same positions and moving in the same directions and speeds. Here''s my header file for the particles:

#ifndef _particles_h_#define _particles_h_// Particles structuretypedef struct{	bool  active;				// Active (Yes/no)	float life;					// Lifespan	float fade;					// Fade speed	float x, y, z;				// Position	float xv, yv, zv;			// Velocities	float r, g, b;				// Colour	float xr, yr, zr;			// The particle''s susceptibility to friction in the air} Particle;// Class for holding a collection of particles/*class ParticleEmitter{	public:		int no_of_particles;		Particle *particles;}*/class Particles{	private:		float slowdown;		float x_speed, y_speed;		float zoom;		float getNewXSpeed();		float getNewYSpeed();	public:		int id;											// ID of particle class		Particles(int n);		void initialiseParticles();		void drawParticles(float x_pos, float y_pos);		virtual ~Particles();};#endif


I haven''t used the id variable yet. BTW, is your code based on the one in the ''Game Programming Tricks of the Trade'' book?
My particle emitter class is of my own design (Which is why I'm surprised it works). Also it uses D3D for rendering - but I imagine it wouldn't be that hard to change it to Open GL.

Heres what my struct / class defs look like, although they won't really do you much good without the implementation. Oh, and to use this, I first create an emitter_p struct that will describe the properties of the emitter. Then I use the SetProperties function of the Emitter class and that creates the buffers and inits all of the particles

typedef struct particle{	D3DXVECTOR3 dir;	D3DXVECTOR3 pos;	float life[2];	float size[3];	float angle;	float rot;	short rotDir;	// used for ROTRAND mode} particle;typedef struct emitter_p{	int count;			// Number of particles	D3DXVECTOR3 pos;	// Position of the emitter	D3DXVECTOR3 dir;	// Direction and base velocity of spew	D3DXVECTOR3 grav;	// Global force applied to all particles	// Ranges	float drag;		D3DXVECTOR3 vary[2];// Spew inaccuracy ( and speed! )	DWORD color[2];	// Color	float life[2];	// Particle life	float delay[2];	// Delay between particles	float bound[3];	// Spew box area (x/y/z width)	float size[4];	// Min/Max start Min/Max end	float rotRate[2];	// num of rotations per second	int minBurst;	// Minimum number of particles to burst at once	Texture *tex;// Texture to apply	DWORD flags;	// Options!//	int srcblend, dstblend;} emitter_p;class CEmitter {public:	CEmitter();	virtual ~CEmitter();	bool SetProperties(emitter_p properties);	inline void Stop();	inline void Activate();	void Draw();	void LoadProperties(LPCSTR file);private:	void Release();	void InitParticles();	inline void InitParticle(particle* pParticle, bool bDead = false);	void InitDeadParticles();	bool bActive;	bool bOkToBurst;	double delay;	// time before the next particle spawn	emitter_p prop;	// properties	// Dynamic stuff (delete on destruction)	particle *pParticles;	VertexTC *pVerts;	LPDIRECT3DINDEXBUFFER9 pIB;	LPDIRECT3DVERTEXBUFFER9 pVB;}; 


I do notice a couple differences though. One being that you don't have a method that initializes a single particle instead of all of them at once. This ensures that dead particles are spawned with different properties than their previous life. Also are you randomizing the spawn location and vectors so that every particle doesn't have the same direction? For example in my emitter properties, I supply min/max ranges for almost every particle variable, then generate a random number in between those two values, and then I assign the variable. This makes every particle different.
Oh, and I find having an active variable in the particle struct useless - you already have the life, and if the life is less than or equal to 0 it is dead.
Sorry if this wasn't what you needed. I could give you an example or two of how I create a random ranged float and assign it, but I really don't want to post the entire code (its near 500 lines, plus it isn't fully completed ).

[edited by - Hawkeye3 on June 23, 2003 2:23:32 PM]
The individual particles are reinitialised within the draw function when they die out and I am randomising. How does your SetProperties function work? Does it assign hard-coded values to the properties? My particles do work but I just want multiple emitters. I''ve got it partly working but I think they are sharing the particles between the emitters rather than having their own.
My particle properties are randomly generated from in between a range of numbers specified in the emitter_p structure (Which is loaded from a plain text file). Oh, and I''ve found that re-generating every property on the particle every time is a waste of CPU time. Its quicker to just re-init the critical things like position, life, and direction.

I still don''t see how your particles can be ending up the same if you are using two different emitters. Have you tried changing the second one''s settings so that it points in the opposite direction so you can clearly see if it is separate or not?

Oh, I just thought of something, are you pushing/popping the matrix between emitters? That may be one thing to check. In my emitter though, it doesn''t affect the modelview matrix in any way so I don''t have to do that ( its much more efficient and faster ).
Advertisement
I do have particles coming out of separate emitters but I think they are sharing the particles e.g. if I declare the number of particles to be 200 and have 2 emitters, there will only be a maximum of 200 particles on screen at once rather than 400. I''ve found an article at Gamasutra which describes a particle manager that handles multiple particle systems so I''ll try to implement that.

This topic is closed to new replies.

Advertisement