We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexDiscussionExhibition › Fire in processing
Pages: 1 2 
Fire in processing (Read 3886 times)
Fire in processing
Dec 15th, 2009, 3:57pm
 
I made a fire simulator in processing.
I know its not realistic but its a cool little effect i made for a game i am working on and thought i would share.
Click to generate fire.
Code:
float[][] fire = new float [100000][15];
float currentflamef,nextflamef;
int currentflame=0,nextflame;
void setup(){
 size(400,400);
 rectMode(CENTER);
 smooth();
 noStroke();
 frameRate(60);
}
void draw(){
 background(200);
 if(mousePressed==true){
   create_fire();
 }
 update_fire();
 draw_fire();
}
void update_fire(){
 for(int flame=0 ; flame<100000 ; flame++){
   if(fire[flame][0]==1){

     if(get(int(fire[flame][1]),int(fire[flame][2]))>200){
       fire[flame][0]=0;
     }
     fire[flame][1]=fire[flame][1]+fire[flame][5]*cos(fire[flame][3]);
     fire[flame][2]=fire[flame][2]+fire[flame][5]*sin(fire[flame][3]);
   }
   fire[flame][7]+=1;
   if(fire[flame][7]>fire[flame][6]){
     fire[flame][0]=0;
   }
 }
}
void draw_fire(){
 for(int flame=0 ; flame<currentflame ; flame++){
   if(fire[flame][0]==1){
     fill(fire[flame][9],fire[flame][10],0,40);
     pushMatrix();
     translate(fire[flame][1],fire[flame][2]);
     rotate(fire[flame][8]);
     rect(0,0,fire[flame][4],fire[flame][4]);
     popMatrix();
   }
 }
}
void create_fire(){
 nextflame=currentflame+10;
 for(int flame=currentflame ; flame<nextflame ; flame++){
   fire[flame][0]=1;
   fire[flame][1]=mouseX;
   fire[flame][2]=mouseY;
   fire[flame][3]=random(0,PI*2);//angle
   fire[flame][4]=random(5,15);//size
   fire[flame][5]=random(.5,1);//speed
   fire[flame][6]=random(5,20)/fire[flame][5];//maxlife
   fire[flame][7]=0;//currentlife
   fire[flame][8]=random(0,TWO_PI);
   fire[flame][9]=random(200,255);//red
   fire[flame][10]=random(50,150);//green
 }
 currentflame=nextflame;
}

Sorry for the messiness and i know im not coding it in the most efficient way.
Enjoy =)
-Devan
Re: Fire in processing
Reply #1 - Dec 15th, 2009, 7:16pm
 
Very nice! Be sure to let me know if you do any electricity or lightning effects.  I've been wanting to do something like that. Smiley
Re: Fire in processing
Reply #2 - Dec 16th, 2009, 12:35am
 
nice effect but

float[100000][15];

= one and a half million floats! (and about 80% cpu which won't leave much for the rest of the game).

btw there's a nice lightning effect in one of the recent applets posted to openprocessing
Re: Fire in processing
Reply #3 - Dec 16th, 2009, 1:17am
 
In the past I've seen people set ridiculously high lengths to their arrays to avoid index out of bound errors - surely not the case here?
Re: Fire in processing
Reply #4 - Dec 16th, 2009, 1:55am
 
The effect is nice, but the code can be improved... (as you point out).
I hope you won't mind some advices.

First, you allocate 15 slots in the second part of the 'fire' array, but use only 11.
Second, you use "magic numbers" everywhere, which works only on a small program like this one. You better create some well named constants which carry the meaning of these slots.
Third, actually, don't use the previous advices (sic) but create a simple class (actually just a structure, no need for constructors or accessors) and use its fields: it allows to set different types for each variable (instead of casting to int, etc.) and it will increase greatly the readability.
Fourth, the 100000 is indeed arbitrary, and will finally backfire (sic): I just reduced the value, it worked fine but quickly end with ArrayIndexOutOfBoundsException, which will happen whatever the value you will put.
A smaller array with shifting of values (or perhaps an ArrayList or a queue?) would be more efficient.

Keep up the good job!
Re: Fire in processing
Reply #5 - Dec 16th, 2009, 10:49am
 
There's a good example in the Reas/Fry processing book about shifting the values in an array to just continually re-use them:

Examples 33-15, and 33-16. You can download all the examples from the book here:

http://processing.org/learning/books/
Re: Fire in processing
Reply #6 - Dec 16th, 2009, 2:30pm
 
Ok so i started working on a new version. Made is so it recycles the array so it never has a limit.
Here is the new code
Code:
int num = 500;
float[][] fire = new float [num][12];
void setup(){
 size(400,400);
 rectMode(CENTER);
 smooth();
 noStroke();
 frameRate(60);
}
void draw(){
 background(200);
 if(mousePressed==true){
   create_fire();
 }
 update_fire();
 draw_fire();
}
void update_fire(){
 for(int i=num-1; i>0; i--){
   for(int fireprop=0;fireprop<11;fireprop++){
   fire[i][fireprop]=fire[i-1][fireprop];
   }
 }
 for(int flame=0 ; flame<num ; flame++){
   if(fire[flame][0]==1){
fire[flame][1]=fire[flame][1]+fire[flame][5]*cos(fire[flame][3]);
fire[flame][2]=fire[flame][2]+fire[flame][5]*sin(fire[flame][3]);
   }
   fire[flame][7]+=1;
   if(fire[flame][7]>fire[flame][6]){
fire[flame][0]=0;
   }
 }
}
void draw_fire(){
 for(int flame=0 ; flame<num ; flame++){
   if(fire[flame][0]==1){
fill(fire[flame][9],fire[flame][10],0,40);
pushMatrix();
translate(fire[flame][1],fire[flame][2]);
rotate(fire[flame][8]);
rect(0,0,fire[flame][4],fire[flame][4]);
popMatrix();
   }
 }
}
void create_fire(){
 for(int flame=0;flame<200;flame++){
   fire[flame][0]=1;
   fire[flame][1]=mouseX;
   fire[flame][2]=mouseY;
   fire[flame][3]=random(0,PI*2);//angle
   fire[flame][4]=random(5,15);//size
   fire[flame][5]=random(1,2);//speed
   fire[flame][6]=random(5,20);//maxlife
   fire[flame][7]=0;//currentlife
   fire[flame][8]=random(0,TWO_PI);
   fire[flame][9]=random(200,255);//red
   fire[flame][10]=random(50,150);//green
 }
}

But now the problem is that alot of the flames will stay in the middle until you let go of the mouse. Does anyone have any idea why? Its probably something simple that im missing. And @PhiLho, thanks for the feedback to use classes, ive alwas wanted to get into them just never had the incentive, but i guess now i have to  Smiley
Thanks everyone for your feedback =)

EDIT:
Sorry forgot to thanks Giles for the awesome tutorials,
Thanks man i appreciate it they were really useful  Wink
Re: Fire in processing
Reply #7 - Dec 16th, 2009, 4:09pm
 
No problem Smiley

Your createfire method was wrong...

It was overwriting many values in the array, when it only needed to overwrite the first value. The updatefire method then shifts everything down one. All you need to do in createfire is re-create the first value in the array.

Code:
void create_fire()
{
fire[0][0]=1;
fire[0][1]=mouseX;
fire[0][2]=mouseY;
fire[0][3]=random(0,PI*2);//angle
fire[0][4]=random(5,15);//size
fire[0][5]=random(1,2);//speed
fire[0][6]=random(5,20);//maxlife
fire[0][7]=0;//currentlife
fire[0][8]=random(0,TWO_PI);
fire[0][9]=random(200,255);//red
fire[0][10]=random(50,150);//green
}
Re: Fire in processing
Reply #8 - Dec 16th, 2009, 4:13pm
 
If you want to create more particles/second than the framerate you will have to put these two bits in the same method, and then call that method multiple times in draw..... but they have to called the same number of times each as one is creating the new item in the array [0], and the other is shifting the values up.
Re: Fire in processing
Reply #9 - Dec 16th, 2009, 4:23pm
 
I tidied up a bit more:

Code:
int num = 5000;
float[][] fire = new float [num][12];
void setup(){
size(400,400);
rectMode(CENTER);
smooth();
noStroke();
frameRate(60);
}
void draw(){
background(200);
if(mousePressed==true)
{
for(int i=0; i<20; i++)
{
create_fire();
}
}
update_fire();
draw_fire();
}
void update_fire()
{
for(int flame=0 ; flame<num ; flame++)
{
if(fire[flame][0]==1)
{
fire[flame][1]=fire[flame][1]+fire[flame][5]*cos(fire[flame][3]);
fire[flame][2]=fire[flame][2]+fire[flame][5]*sin(fire[flame][3]);
}
fire[flame][7]+=1;
if(fire[flame][7]>fire[flame][6]){
fire[flame][0]=0;
}
}
}
void draw_fire(){
for(int flame=0 ; flame<num ; flame++){
if(fire[flame][0]==1){
fill(fire[flame][9],fire[flame][10],0,40);
pushMatrix();
translate(fire[flame][1],fire[flame][2]);
rotate(fire[flame][8]);
rect(0,0,fire[flame][4],fire[flame][4]);
popMatrix();
}
}
}
void create_fire()
{

for(int i=num-1; i>0; i--)
{
for(int fireprop=0;fireprop<11;fireprop++)
{
fire[i][fireprop]=fire[i-1][fireprop];
}

fire[0][0]=1;
fire[0][1]=mouseX;
fire[0][2]=mouseY;
fire[0][3]=random(0,PI*2);//angle
fire[0][4]=random(5,15);//size
fire[0][5]=random(1,2);//speed
fire[0][6]=random(10,50);//maxlife
fire[0][7]=0;//currentlife
fire[0][8]=random(0,TWO_PI);
fire[0][9]=random(200,255);//red
fire[0][10]=random(50,150);//green
}
}


I moved part of updatefire into createfire, so the adding of the new value in the array, and the "moving up" are together in one method as they should be.... you can then call this method 10...20 as many times as you like in draw() to get a denser fire effect.

As other people pointed out...using a Flame class would let you name all the variables so the code would be much easier to read.
Re: Fire in processing
Reply #10 - Dec 16th, 2009, 6:56pm
 
It seems like this version runs slower than my old one. Does that happen to anyone else or is it just a spike in my computer.
Re: Fire in processing
Reply #11 - Dec 16th, 2009, 11:41pm
 
Try this and you should get full speed.

Code:

import processing.opengl.*;

int num = 1000;

size(640,480, OPENGL);
frameRate(120);
hint(ENABLE_OPENGL_4X_SMOOTH);
Re: Fire in processing
Reply #12 - Dec 16th, 2009, 11:50pm
 
Maybe as it is creating 60 x 20 = 120 new "flames" per second. You could reduce the number of loops in draw (currently 20).
Re: Fire in processing
Reply #13 - Dec 17th, 2009, 12:33am
 
By using OpenGL, it works much faster.

Code:
import processing.opengl.*;

int num = 120;
float[][] fire = new float [num][12];

void setup(){
size(400,400, OPENGL);
frameRate(120);
hint(ENABLE_OPENGL_4X_SMOOTH);
rectMode(CENTER);
smooth();
noStroke();
}
void draw(){
background(200);
if(mousePressed==true)
{
for(int i=0; i<2; i++)
{
create_fire();
}
}
update_fire();
draw_fire();
}
void update_fire()
{
for(int flame=0 ; flame<num ; flame++)
{
if(fire[flame][0]==1)
{
fire[flame][1]=fire[flame][1]+fire[flame][5]*cos(fire[flame][3]);
fire[flame][2]=fire[flame][2]+fire[flame][5]*sin(fire[flame][3]);
}
fire[flame][7]+=1;
if(fire[flame][7]>fire[flame][6]){
fire[flame][0]=0;
}
}
}
void draw_fire(){
for(int flame=0 ; flame<num ; flame++){
if(fire[flame][0]==1){
fill(fire[flame][9],fire[flame][10],0,40);
pushMatrix();
translate(fire[flame][1],fire[flame][2]);
rotate(fire[flame][8]);
rect(0,0,fire[flame][4],fire[flame][4]);
popMatrix();
}
}
}
void create_fire()
{

for(int i=num-1; i>0; i--)
{
for(int fireprop=0;fireprop<11;fireprop++)
{
fire[i][fireprop]=fire[i-1][fireprop];
}

fire[0][0]=1;
fire[0][1]=mouseX;
fire[0][2]=mouseY;
fire[0][3]=random(0,PI*2);//angle
fire[0][4]=random(5,15);//size
fire[0][5]=random(1,2);//speed
fire[0][6]=random(10,50);//maxlife
fire[0][7]=0;//currentlife
fire[0][8]=random(0,TWO_PI);
fire[0][9]=random(200,255);//red
fire[0][10]=random(50,150);//green
}
}
Re: Fire in processing
Reply #14 - Dec 17th, 2009, 3:47pm
 
the OpenGL may be faster...but you also reduced the number of particles being generated every frame by a factor of 10 (from 20 to 2).
Pages: 1 2