/** SPACE : cycla genom verktygen.
G : visa quadtree
P : pausa simulationen.
K : komprimera quadtree:et
F : ny brusig terräng.
V : ny konstant terräng.

A,Z : manipulera kompressionsgraden.
S,X : manipulera eldens livslängd.
D,C : manipulera eldens spridning.
*/ Node fire; PFont font; boolean showGrid = false; boolean paused = false; int timer = 0; int compression = 16; int fireGrowth = 4; float fireSpread = 0.125; float[][] flammability; int tool = 0; final int FIRE=0, MORE_FUEL=1, LESS_FUEL=2; final String[] TOOL_NAMES = new String[]{"start fire","more fuel","less fuel"}; //------------------------- void setup(){ size(256,276); font = loadFont("Silkscreen-8.vlw"); textFont( font ); fire = new Node(0,0,width); flammability = new float[width][width]; randomFlammability(); frameRate(60); } //------------------------- void draw(){ if(!paused) update(); loadPixels(); fire.draw(); if(showGrid) fire.drawBoundaries( color(128) ); updatePixels(); fill(0); noStroke(); rect(0,width,width,height-width); fill(255); textAlign(LEFT); text( "burn speed: "+fireGrowth ,5, height-12); text( memoryUsage() ,5, height-2); textAlign(RIGHT); text( fireSpread+" :fire spread" ,width-2, height-12); text( fireAmount() ,width-2, height-2); textAlign(CENTER); text( TOOL_NAMES[tool],width/2, height-7); stroke(255,128); if(!paused) timer++; line(timer%width,height,timer%width,width); if(mousePressed && mouseY=0 && mouseY>=0){ if(tool==FIRE) startFire(mouseX,mouseY); if(tool==MORE_FUEL) modifyFlammability(mouseX,mouseY, 0.2); if(tool==LESS_FUEL) modifyFlammability(mouseX,mouseY,-0.2); if(tool==MORE_FUEL || tool==LESS_FUEL) fire.redraw(); } } //------------------------- void keyPressed(){ if( key==' ' ) tool = (tool+1)%3; if( key=='k' ) fire.compress(64,16); if( key=='g' ) { showGrid = !showGrid; fire.redraw(); } if( key=='p' ) paused = !paused; if( key=='n' ) fire = new Node(0,0,width); if( key=='a' ) compression = min(128,compression*2); if( key=='z' ) compression = max(1,compression/2); if( key=='s' ) fireGrowth = min(128,fireGrowth*2); if( key=='x' ) fireGrowth = max(1,fireGrowth/2); if( key=='d' ) fireSpread = min(0.5,fireSpread*2); if( key=='c' ) fireSpread = max(1f/256,fireSpread/2); if( key=='f' ) randomFlammability(); if( key=='v' ) constantFlammability(); } //------------------------- void mousePressed(){ } //------------ float posterize(float x){ return ((int)(8*x+1))/(float)8; } //------------------------- void randomFlammability(){ float s = 0.02; noiseDetail(2,0.8); for(int i=0; idist(mx,my,x,y) ){ float d = (2.5/radius)*dist(mx,my,x,y); float f = amount*exp(-d*d); flammability[x][y] = constrain(0.02+flammability[x][y]+f,0,1); } } //------------------------- float ignitionProbability(int x, int y){ return fireSpread * getFlammability(x,y); } //------------------------- float getFlammability(int x, int y){ return posterize( (x<0 || y<0 || x>width-1 || y>width-1) ? 1 : flammability[x][y] ); } //------------------------- color getPixelColor(int x, int y, int value){ color ash = color(32+64*getFlammability(x,y)); color flame = color( 255, random(128,255), 0 ); color grass = color(0,64+getFlammability(x,y)*128,0); color c = (value<64 ? lerpColor(grass,flame,value/64f) : flame ); if(value>128) c = lerpColor( flame, color(64), value/128f - 1 ); return c; } //------------------------- String memoryUsage(){ if(mouseY=0 && mouseY>=0){ int bytes = fire.getBitSum()/8; return "memory: "+( bytes/1024 )+"."+(bytes/102)%10+" kB"; } else return "- - -"; } //------------------------- String fireAmount(){ if(mouseY=0 && mouseY>=0){ return fire.get(mouseX,mouseY)+" :fire at cursor"; } else return "- - -"; } //------------ void startFire(int x, int y){ fire.forceCellSize(x,y,minCellSize); fire.node(x,y).value = 64; fire.calculateExtremes(); fire.calculateAverages(); } //------------ void update(){ //Node spread = new Node(0,0,w); fire.spread( fire ); fire.update(); fire.calculateExtremes(); fire.calculateAverages(); fire.compress( compression ,compression ); } //#########################