Sign in to follow this  
assainator

particle system

Recommended Posts

i tought it would be nice to make explosions in my game so i wanted to create a particle system. i've searched and read and started to write my own. but i failed: it was bad, very fragile(it was a static thing with no possibility's to expand) so i rewrote the whole thing again i failed: for to much options (things that are rarely used (specially in my game)) so again: i rewrote the whole thing, few options, expandable, dynamic. and i succeded partialy. it does render some particles but it's doing some strange things. could someone please look into my code and point/explain me to the problem? the source: main.cpp
#include <gl/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include "math.h"
#include <math.h>
#include "particle.h"


ParticleSys Ptry(15000, 0.0, 0.0, 5);

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();

	Ptry.Update();

	glColor3f(1.0,0.0,0.0);
	glBegin(GL_QUADS);
		glVertex2f( 0.005, 0.005);
		glVertex2f(-0.005, 0.005);
		glVertex2f(-0.005,-0.005);
		glVertex2f( 0.005,-0.005);
	glEnd();


	glutSwapBuffers();
}

void Animations(int value)
{
	glutPostRedisplay();
	glutTimerFunc(1,Animations,0);
}

void processNormalKeys(unsigned char key, int x, int y)
{
	if(key == 'f')
	{
		Ptry.Start();
	}
}


int main(int argc, char **argv)
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);


	//initializing window
	glutInitWindowSize(800,600);
	glutInitWindowPosition(400,20);
	glutCreateWindow("Particle Experiments");
	glEnable(GL_DEPTH_TEST);



	//handing display function to GLUT
	glutDisplayFunc(display);

	//handing the keyboard and special functions to glut
	glutKeyboardFunc(processNormalKeys);
	//glutSpecialFunc(processSpecialKeys);

	glMatrixMode(GL_PROJECTION);

	//hand over the animations and transformations
	glutTimerFunc(1,Animations,0);

	//gluPerspective(0,     //view angle
 //                0.2,    //aspect ratio
 //                0.0,    //near clip
 //                200.0); //far clip

	glMatrixMode(GL_MODELVIEW);
	glutMainLoop();

	return 0;
}

math.h
#ifndef __MATH_H_H
#define __MATH_H_H

#include <math.h>
#include <stdlib.h>

typedef struct
{
	float x,y;
}P2D;


class math
{
	public:
		float randomFloat();
};

#endif //__MATH_H_H

math.cpp
#include "math.h"
#include <math.h>
#include <stdlib.h>


float math::randomFloat()
{
	float number = (float)rand() / ((float)RAND_MAX );
	number += 0.1;
	number /= 10;
	return number;
}
particle.cpp
#ifndef __PARTICLE_H_H
#define __PARTICLE_H_H

#include "math.h"

typedef struct
{
	P2D pos;
	P2D direction;
	float life;
	bool alive;
}PARTICLE;

class ParticleSys
{
	public:
		PARTICLE P[1000];
		P2D pos;

		int MaxLife;
		int BRate;
		bool play;

		ParticleSys::ParticleSys(int MaximumLife, float Pos_X, float Pos_Y, int BirthRate);
		void Birth();
		int FindFreeParticle();
		void Update();
		void Render();
		void Start();
};


#endif //__PARTICLE_H_H
particle.cpp
#include <math.h>
#include "math.h"
#include "particle.h"
#include <gl/glut.h>

math Pmath;

ParticleSys::ParticleSys(int MaximumLife, float Pos_X, float Pos_Y, int BirthRate)
{
	pos.x = Pos_X;
	pos.y = Pos_Y;
	MaxLife = MaximumLife;
	BRate = BirthRate;
	play = false;
}

int ParticleSys::FindFreeParticle()
{
	for(int Pfree = 0; Pfree < 1000; Pfree++)
	{
		if(!P[Pfree].alive)
		{
			return Pfree;
		}
	}
}


void ParticleSys::Render()
{
	for(int ParticleSys = 0; ParticleSys < 1000; ParticleSys++)
	{
		if(P[ParticleSys].alive)
		{
			glColor3f(0.0, 0.9, 0.9);
			glBegin(GL_QUADS);
				glVertex2f( P[ParticleSys].pos.x + -0.005, P[ParticleSys].pos.y +  0.005);
				glVertex2f( P[ParticleSys].pos.x +  0.005, P[ParticleSys].pos.y +  0.005);
				glVertex2f( P[ParticleSys].pos.x +  0.005, P[ParticleSys].pos.y + -0.005);
				glVertex2f( P[ParticleSys].pos.x + -0.005, P[ParticleSys].pos.y + -0.005);
			glEnd();
		}
	}
}

void ParticleSys::Update()
{
	if(play)
	{
		Birth();
		for(int UpdateP = 0; UpdateP < 1000; UpdateP++)
		{
			P[UpdateP].life += glutGet(GLUT_ELAPSED_TIME);
			if(P[UpdateP].life > MaxLife)
			{
				P[UpdateP].alive = false;
			}

			if(P[UpdateP].alive)
			{
				P[UpdateP].pos.x += P[UpdateP].direction.x;
				P[UpdateP].pos.y += P[UpdateP].direction.y;
			}
		}
		Render();
	}
}

void ParticleSys::Birth()
{
	for(int BirthP = 0; BirthP < BRate; BirthP++)
	{
		int FreeSpace = FindFreeParticle();

		P[BirthP].pos.x = P[BirthP].pos.x;
		P[BirthP].pos.y = P[BirthP].pos.y;

		P[BirthP].direction.x = Pmath.randomFloat() / 100;
		P[BirthP].direction.y = Pmath.randomFloat() / 100;

		P[BirthP].alive = true;
		P[BirthP].life = 0.0;
	}
}

void ParticleSys::Start()
{
	play = true;
}

a image: [URL='http://www.JustFreeSpace.Com/viewer5.php?id=12688particleProblem.jpg'][IMG]http://www.JustFreeSpace.Com/thumb3/12688particleProblem.jpg[/IMG][/URL] if you compile, you'll see that (as on the image) a few particles fly away from the center (the red box). but there are a few problems: -only one time some particles spawn away it should happen more often. -they only go in one direction (the upper right corner) but they should go into all directions. thanks in advance, assainator

Share this post


Link to post
Share on other sites
Study this, it has some parts that you need like different position and
and movement in different direction. It can be improved, but for right now
its "enough" for me.


#ifndef _RAIN_H_
#define _RAIN_H_

class Rain
{
struct Vector{ float x; float y; float z; float w;
Vector(): x(0),y(0),z(0),w(0) { }
} ;
private:

Vector posVec; //position vector
Vector velVec; //velocity vector
Vector colMtrx; //color matrix
Vector txCoord; // Texture Coord matrix

float Force;
float Mass;
float accel;
float dt;
float scale_size;

public:
Rain(float mass = 1.0);
~Rain() { }


void draw_droplet(int *Texture,int texNum, bool Bind);
void resetPos();


Vector& getPosVec() { return posVec; }
Vector& getVelVec() { return velVec; }
Vector& getColMtrx(){ return colMtrx;}

void setX(Vector& vec, float x = 0) { vec.x = x;}
void setY(Vector& vec, float y = 0) { vec.y = y;}
void setZ(Vector& vec, float z = 0) { vec.z = z;}
void setW(Vector& vec, float w = 0) { vec.w = w;}

float getX(Vector& vec)const{return vec.x;}
float getY(Vector& vec)const{return vec.y;}
float getZ(Vector& vec)const{return vec.z;}
float getW(Vector& vec)const{return vec.w;}

float getAccel() { return accel; }
float getTime() { return dt; }
void setTime(float dtme){dt = dtme; }
};
#endif





//rain.cpp
#include"Rain.h"
#include<GL/glut.h>

Rain::Rain(float mass)
{
//Position vector and velocity vector
posVec.x = 0; velVec.x = 0;
posVec.y = 0; velVec.y = 0;
posVec.z = 0; velVec.z = 0;
posVec.w = 0; velVec.w = 0;
//color matrix and texture coord matrix
colMtrx.x = 0; txCoord.x = 0;
colMtrx.y = 0; txCoord.y = 0;
colMtrx.z = 0.50; txCoord.z = 0;
colMtrx.w = 0; txCoord.w = 0;

scale_size = 1.0;

dt = 0.0;
Mass = mass;
accel = 0.00981;
Force = Mass * accel;
}
void Rain::draw_droplet(int *Texture,int texNum, bool Bind)
{
float len = 1.0 * scale_size;

if(Bind)
{
glColor4f(1.0,1.0,1.0,0.5);
glBindTexture(GL_TEXTURE_2D,Texture[texNum]);
}
else
{
glColor4f(colMtrx.x,colMtrx.y,colMtrx.z,colMtrx.w);
}

//draw quad CCW
glBegin(GL_QUADS);
glTexCoord2f(1.0,0.0); glVertex3f(-len,len,0.0);
glTexCoord2f(0.0,0.0); glVertex3f(-len,-len,0.0);
glTexCoord2f(0.0,1.0); glVertex3f(len,-len,0.0);
glTexCoord2f(1.0,1.0); glVertex3f(len,len,0.0);
glEnd();
}


void Rain::resetPos()
{
;
}




My main uses these func :


//draws rain in rectangle position.
void InitRain()
{
for(int i = 0,j(0),k(0),l(0); i < MAX_P; i++)
{
rain[i].setTime(0.0);

rain[i].setY(rain[i].getPosVec(),rand()%50+10 + (float)rand()/RAND_MAX/100);

rain[i].setX(rain[i].getVelVec(),float(rand()/RAND_MAX/100));
rain[i].setY(rain[i].getVelVec(),(float)rand()/RAND_MAX/100);
rain[i].setZ(rain[i].getVelVec(),float(rand()/RAND_MAX/1000));

if(i < MAX_P * 0.25)//Front
{
rain[i].setX(rain[i].getPosVec(),-(MAX_P*0.25)/2 + i*2);
rain[i].setZ(rain[i].getPosVec(), MAX_P/6);
}

else if(i > MAX_P * 0.25 && i < MAX_P * 0.50)//back
{
rain[i].setX(rain[i].getPosVec(), -(MAX_P*0.25)/2 + j*2);
rain[i].setZ(rain[i].getPosVec(),-MAX_P/3);
j++;
}
else if(i > MAX_P * 0.50 && i < MAX_P * 0.75)//left -- back to front
{
rain[i].setX(rain[i].getPosVec(), -MAX_P/8);
rain[i].setZ(rain[i].getPosVec(), -MAX_P/3 + k*2);
k++;
}
else //right back to front
{
rain[i].setX(rain[i].getPosVec(), MAX_P/3);
rain[i].setZ(rain[i].getPosVec(), -MAX_P/3 + l*2);
l++;
}
}

}





void DrawRain()
{
for(int i = 0; i < MAX_P; i++)
{
static float clk_strt1 = clock()*0.001;
float clk_end1 = clock()*0.001;
rain[i].setTime(clk_strt1);

glPushMatrix();
glTranslatef(rain[i].getX(rain[i].getPosVec()),//set position
rain[i].getY(rain[i].getPosVec()),
rain[i].getZ(rain[i].getPosVec()));

glRotatef(90.0,0.0,0.0,1.0);
rain[i].draw_droplet(Textures,RAIN,true);//bind texture
glPopMatrix();

clk_strt1 = clk_end1- clk_strt1;
}

}





void UpdateRain()
{
for(int i = 0; i < MAX_P; i++)
{
static float clk_strt2 = clock()*0.001;
float clk_end2 = clock()*0.001;

rain[i].setTime(rain[i].getTime() + clk_strt2 );

rain[i].setY( rain[i].getPosVec() ,
rain[i].getY(rain[i].getPosVec())
- rain[i].getY(rain[i].getVelVec()));

rain[i].setY(rain[i].getVelVec(),
rain[i].getY(rain[i].getVelVec()) + rain[i].getAccel() * rain[i].getTime() * 0.01);


clk_strt2 = clk_end2 - clk_strt2;

if(rain[i].getY(rain[i].getPosVec()) < -50) //-50 min bottom distance
{
rain[i].setY(rain[i].getPosVec(),30);
rain[i].setY(rain[i].getVelVec(),(float)rand()/RAND_MAX);
rain[i].setTime(0.0);
}

}
}






Here is a what came about, the video is crappy but the actual application is
pretty neat.

http://www.youtube.com/watch?v=L08XNXMfxFQ

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this