optimization - Processing: How can I improve the framerate in my program? -


so i've been working in processing few weeks now, and, though i'm not experienced in programming, have moved on more complex projects. i'm programming evolution simulator, spawns creatures random properties.

eventually, i'll add reproduction, of creatures sort of float around screen, , follow mouse somewhat. interacts sound line in, commented parts out can viewed on canvas, shouldn't change question, thought point out.

as of now, framerate far less ideal me, , lowers more creatures spawned. making fundamental mistake, or running many functions per frame?

here's source code, , can play in browser here:

//import ddf.minim.*; //import ddf.minim.signals.*; //import ddf.minim.analysis.*; //import ddf.minim.effects.*;  //minim minim; //audioinput in; boolean newcreature = true; boolean matured[]; int ellipses[]; int hair[]; int maxcreaturenumber = 75; //int volume; //int volumetolerance = 1; int creatureindex = -1; int creaturex[]; int creaturey[]; float strokeweightattribute[]; float creaturesize[]; float creatureendsize[]; float creaturexincrement[]; float creatureyincrement[]; float bubblesize; float easing = 0.05; float angle = 0.00; color colorattribute[];  void setup() {     background(0);     size(1000,500);     nofill();     //minim = new minim(this);     //in = minim.getlinein(minim.stereo, 512);     creaturex = new int[maxcreaturenumber];     creaturey = new int[maxcreaturenumber];     ellipses = new int[maxcreaturenumber];     hair = new int[maxcreaturenumber];     strokeweightattribute = new float[maxcreaturenumber];     creatureendsize = new float[maxcreaturenumber];     creaturesize = new float[maxcreaturenumber];     creaturexincrement = new float[maxcreaturenumber];     creatureyincrement = new float[maxcreaturenumber];     matured = new boolean[maxcreaturenumber];     colorattribute = new color[maxcreaturenumber]; }  void draw() {   angle += 0.05;   fill(0, 50);   rect(-1, -1, 1001, 501);   // for(int = 0; < in.buffersize() - 1; i++) {   //     if(in.mix.get(i) * 50 > volumetolerance) {   //         volume++;   //     }   // }   if(newcreature && creatureindex < maxcreaturenumber - 1) {       initspontaneouscreature();   }   updatecreatures();   // bubblesize = volume/250;   bubblesize += 0.01;   // volume = 0; }  //void stop() { //    minim.stop(); //    super.stop(); //}  void initspontaneouscreature() {     creatureindex++;     creatureendsize[creatureindex] = int(random(5, 20));     creaturex[creatureindex] = int(random(1000));     if(creaturex[creatureindex] >= 500) {         creaturex[creatureindex] -= creatureendsize[creatureindex];     }     else {         creaturex[creatureindex] += creatureendsize[creatureindex];     }     creaturey[creatureindex] = int(random(500));     if(creaturey[creatureindex] >= 250) {         creaturey[creatureindex] -= creatureendsize[creatureindex];     }     else {         creaturey[creatureindex] += creatureendsize[creatureindex];     }     ellipses[creatureindex] = int(random(4));     hair[creatureindex] = int(random(4));     strokeweightattribute[creatureindex] = random(1, 4);     colorattribute[creatureindex] = color(int(random(20,255)), int(random(20,255)), int(random(20,255)));     matured[creatureindex] = false;     newcreature = false;     while(ellipses[creatureindex] == 0 && hair[creatureindex] == 0) {         ellipses[creatureindex] = int(random(4));         hair[creatureindex] = int(random(4));     } }  void updatecreatures() {     for(int n = 0; n <= creatureindex; n++) {         if(matured[n]) {             creaturex[n] += ((((mousex) - creaturex[n]) * easing) / (60/*-abs(volume/5))*/)) + random(-5, 6);             creaturey[n] += ((((mousey) -creaturey[n]) * easing) / (60/*-abs(/*volume/5))*/)) + random(-5,6);             drawcreature();         }         else {             if(creatureendsize[n] != creaturesize[n]) {                 creaturesize[n] += bubblesize;                 if(creaturesize[n] > creatureendsize[n]) {                     creaturesize[n] -= (creaturesize[n] - creatureendsize[n]);                 }             }             else {                 newcreature = true;                 matured[n] = true;                 // bubblesize = 0;             }             drawcreature();         }     } }  void drawcreature() {     for(int n = 0; n <= creatureindex; n++) {         if(matured[n]) {             stroke(colorattribute[n]);             strokeweight(strokeweightattribute[n]);             for(int = 0; <= 4; i++) {                 if(ellipses[n] == i) {                     if(i == 0) {                      }                     else if (i == 1) {                       pushmatrix();                       translate(creaturex[n], creaturey[n]);                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       rotate(radians(180));                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       popmatrix();                     }                     else if(i == 2) {                       pushmatrix();                       translate(creaturex[n], creaturey[n]);                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       rotate(radians(180));                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       rotate(radians(270));                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       popmatrix();                      }                     else if(i == 3) {                       pushmatrix();                       translate(creaturex[n], creaturey[n]);                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       rotate(radians(90));                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       rotate(radians(180));                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       rotate(radians(270));                       ellipse(creaturesize[n], creaturesize[n], creaturesize[n], creaturesize[n]);                       popmatrix();                     }                 }                 if(hair[n] == i) {                     if(i == 0) {                      }                     else if (i == 1) {                         pushmatrix();                         translate(creaturex[n], creaturey[n]);                         for(int j = 0; j <= 360; j+=70) {                             rotate(j);                             stroke(colorattribute[n], random(255));                             line(0,0, creaturesize[n] + random(10), creaturesize[n] + random(10));                         }                         popmatrix();                     }                     else if(i == 2) {                         pushmatrix();                         translate(creaturex[n], creaturey[n]);                         for(int j = 0; j <= 360; j+=30) {                             rotate(j);                             stroke(colorattribute[n], random(255));                             line(0,0, creaturesize[n] + random(10), creaturesize[n] + random(10));                         }                         popmatrix();                     }                     else if(i == 3) {                         pushmatrix();                         translate(creaturex[n], creaturey[n]);                         for(int j = 0; j <= 360; j+=1) {                             rotate(j);                             stroke(colorattribute[n], random(255));                             line(0,0, creaturesize[n] + random(10), creaturesize[n] + random(10));                         }                         popmatrix();                     }                 }             }         }         if(!matured[n]) {             stroke(abs(sin(angle) * 255));             //strokeweight(5);             ellipse(creaturex[n], creaturey[n], creaturesize[n] * 5,  creaturesize[n] * 5);             nostroke();         }     } } 

right, suspected, unnecessary pushmatrix(), popmatrix() calls , large amount of lines seemed main culprits, still, there lot of redundant code.

i refactored code in cleaner manner , seems run fine. here 'improved' version:

int maxcreatures = 75; int numcreatures = 0; int spawnnthframe = 50;//spawn creature every 50 frames creature[] creatures;  void setup() {   background(0);   size(1000,500);   nofill();   creatures = new creature[maxcreatures]; }  void draw() {   fill(0, 50);   rect(-1, -1, 1001, 501);   if(framecount % spawnnthframe == 0){     println("creatures: " + numcreatures);     if(numcreatures < maxcreatures) {       //creature constructor float endsize,int x, int y,int ellipses,int hair,float strokew,color c       creatures[numcreatures] = new creature(random(5, 20),int(random(1000)),int(random(500)),int(random(4)),int(random(4)),random(1, 4),color(int(random(20,255)), int(random(20,255)), int(random(20,255))));       numcreatures++;     }   }   for(int = 0; < numcreatures; i++) creatures[i].update(); } 

and creature class:

class creature{  int x,y,cxinc,cyinc;//if x,y ints, increments into, right?  float cstrokeweight,csize,cendsize,csizeinc = 0.01,easing = 0.05,angle = 0.00;  color ccolor;  int hair,numhair,ellipses;  boolean matured = false;   creature(float endsize,int x, int y,int ellipses,int hair,float strokew,color c){     cendsize = endsize;     this.x = x;     if(x >= 500) x -= cendsize;     else         x += cendsize;     this.y = y;     if(y >= 250) x -= cendsize;     else         x += cendsize;     this.ellipses = ellipses;     this.hair = hair;     if(hair == 1) numhair = 3;//~5, half that, draw through centre, etc.     if(hair == 2) numhair = 6;     if(hair == 3) numhair = 30;//no default value     cstrokeweight = strokew;     this.ccolor = c;  }  void update(){    if(matured) {      x += (((mousex - x) * easing) / 60) + random(-5, 6);     y += (((mousey - y) * easing) / 60) + random(-5, 6);    }else {     if(csize < cendsize) csize += csizeinc;     else matured = true;     angle += 0.05;    }     this.draw();  }  void draw(){    if(matured){      stroke(ccolor);      strokeweight(cstrokeweight);      if(ellipses == 1){//2 ellipses diagonally        ellipse(x,y,csize,csize);        ellipse(x+csize,y+csize,csize,csize);      }      if(ellipses == 2){        ellipse(x,y,csize,csize);        ellipse(x,y+csize,csize,csize);        ellipse(x+csize,y+csize,csize,csize);      }      if(ellipses == 3){        ellipse(x,y,csize,csize);        ellipse(x+csize,y,csize,csize);        ellipse(x,y+csize,csize,csize);        ellipse(x+csize,y+csize,csize,csize);      }      float hairangleinc = two_pi/numhair;//angle increment each piece = 360/number of hair lines      float hairangle,hairlength,haircos,hairsin;      for(int = 0; < numhair; i++){        hairangle = hairangleinc * i;        haircos = cos(hairangle);        hairsin = sin(hairangle);        hairlength = random(20);        stroke(ccolor, random(255));        line(x + (haircos * -hairlength),y + (hairsin * -hairlength), x + (haircos * hairlength),y + (hairsin * hairlength));       }    }else{      stroke(abs(sin(angle) * 255));      ellipse(x,y, csize * 5,  csize * 5);    }  } } 

ok, explanations.

first, separated variables related 1 creature 'global' ones determine how sketch runs (how many creatures spawned, etc.).

this makes main code 25 lines long , altogether bit below 100 lines less half of original.

the first part doesn't special. in draw() function, instead of creating creature every frame, draw 1 every nth frame using spawnnthframe variable, made easy see state of creature made slow. if set small number 2 variable should spawn lot of creatures per frame.

the creature class has properties original code stored in arrays.

instead of doing

pushmatrix(); translate(); ellipse(); rotate() ellipse() popmatrix(); 

i draw ellipses @ x,y. little hint on rotations. i've noticed increments of 90 degrees. processing has nice constants 90,180,360 degrees in radians: half_pi, pi, two_pi can handy sometimes.

now 'hairy' situation, here's commented out myself:

//if(i == 1) for(int j = 0; j <= 360; j+=70) , 360/70 5, if (i == 2) , 12 hair //if = 3-> 360 lines ? need many lines, thick ? how 30 ? 5*12=60, if draw lines through centre, not centre, can away half lines 

so there 3 loops drawing lines, each having different increments. there either 360/70 lines, 360/30 lines , 360 lines. 5,12 , 360 lines. 5,12 lines, kind of halved drawing 'diameter' lines across centre opposed 'radius' lines centre.

here's mean, halflines

also think 360 lines strokeweight , jittery motion bunch of lines hard count, thought, why split hairs? :p

maybe creature pretty similar 60 radii means 30 diameters.

now explain bit of trig functions used this. main thing 'polar cartesian' coordinates conversion:

polar like:

"i moving on circle direction described angle (much 1 handle of clock) , radius (distance centre)."

and cartesian

"i'm moving based on 2 axes (horizontal/x , vertical/y), kind of streets of manhattan, cheat , move diagonally through walls."

if makes sense... :) anyway, convert angle , radius pair x , y pair using formula:

x = cos(angle) * radius y = sin(angle) * radius 

for each line:

angle = hairangle radius = hairlength 

so line() *x + (haircos * -hairlength)* looks bit this:

x + (haircos * -hairlength) =  move x , there move hairlength left(-) current angle (haircos) 

similar y, using cos, puts first point of line in opposite direct (-hairlength) of angle moving centre (which creature's x) , second 'diagonal'. imagine drawing 'diagonals' (from (-x,-y) (+x,+y)), rotate these.

update

apparently copy/pasting code works in javascript (best viewed in chromium/chrome). can run right here:

var maxcreatures = 75;  var numcreatures = 0;  var spawnnthframe = 50;//spawn creature every 50 frames  var creatures = [];    function setup() {    background(0);    createcanvas(1000,500);    nofill();  }    function draw() {    fill(0, 50);    rect(-1, -1, 1001, 501);    if(framecount % spawnnthframe === 0){      println("creatures: " + numcreatures);      if(numcreatures < maxcreatures) {        //creature constructor float endsize,int x, int y,int ellipses,int hair,float strokew,color c        creatures[numcreatures] = new creature(random(5, 20),int(random(1000)),int(random(500)),int(random(4)),int(random(4)),random(1, 4),color(int(random(20,255)), int(random(20,255)), int(random(20,255))));        numcreatures++;      }    }    for(var = 0; < numcreatures; i++) creatures[i].update();  }          function creature(endsize,x,y,ellipses,hair,strokew,c){   this.x = x;   this.y = y;   this.ellipses = ellipses;   this.hair = hair;   this.numhair = 0;   this.cstrokeweight = strokew;   this.ccolor = c;   this.cxinc = 0;   this.cyinc = 0.01;   this.csize = 0;   this.cendsize = endsize;   this.easing = 0.05;   this.angle = 0.0;   this.matured = false;         if(x >= 500) x -= this.cendsize;      else         x += this.cendsize;      if(y >= 250) x -= this.cendsize;      else         x += this.cendsize;      if(hair == 1) this.numhair = 3;//~5, half that, draw through centre, etc.      if(hair == 2) this.numhair = 6;      if(hair == 3) this.numhair = 30;//no default value       this.update = function(){     if(this.matured) {       this.x += (((mousex - this.x) * this.easing) / 60) + random(-5, 6);      this.y += (((mousey - this.y) * this.easing) / 60) + random(-5, 6);     }else {      if(this.csize < this.cendsize) this.csize += this.csizeinc;      else this.matured = true;      this.angle += 0.05;     }      this.draw();   }   this.draw = function(){     if(this.matured){       stroke(this.ccolor);       strokeweight(this.cstrokeweight);       if(this.ellipses == 1){//2 ellipses diagonally         ellipse(this.x,this.y,this.csize,this.csize);         ellipse(this.x+this.csize,this.y+this.csize,this.csize,this.csize);       }       if(this.ellipses == 2){         ellipse(this.x,this.y,this.csize,this.csize);         ellipse(this.x,this.y+this.csize,this.csize,this.csize);         ellipse(this.x+this.csize,this.y+this.csize,this.csize,this.csize);       }       if(this.ellipses == 3){         ellipse(this.x,this.y,this.csize,this.csize);         ellipse(this.x+this.csize,this.y,this.csize,this.csize);         ellipse(this.x,this.y+this.csize,this.csize,this.csize);         ellipse(this.x+this.csize,this.y+this.csize,this.csize,this.csize);       }       var hairangleinc = two_pi/this.numhair;//angle increment each piece = 360/number of hair lines       var hairangle,hairlength,haircos,hairsin;       for(var = 0; < this.numhair; i++){         hairangle = hairangleinc * i;         haircos = cos(hairangle);         hairsin = sin(hairangle);         hairlength = random(20);         stroke(this.ccolor, random(255));         line(this.x + (haircos * -hairlength),this.y + (hairsin * -hairlength), this.x + (haircos * hairlength),this.y + (hairsin * hairlength));        }     }else{       stroke(abs(sin(this.angle) * 255));       ellipse(this.x,this.y, this.csize * 5,  this.csize * 5);     }   }  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>

creatures js sketch preview


Comments

Popular posts from this blog

asp.net - repeatedly call AddImageUrl(url) to assemble pdf document -

java - Android recognize cell phone with keyboard or not? -

iphone - How would you achieve a LED Scrolling effect? -