处理:如何提高程序的帧率? [英] Processing: How can I improve the framerate in my program?

查看:107
本文介绍了处理:如何提高程序的帧率?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我已经在处理中工作了几周了,尽管我没有编程经验,但我继续进行更复杂的项目.我正在编程一个进化模拟器,该模拟器会生成具有随机属性的生物.

So I've been working in Processing for a few weeks now, and, though I'm not experienced in programming, I have moved on to more complex projects. I'm programming an evolution simulator, that spawns creatures with random properties.

最终,我将添加复制,但是到目前为止,这些生物只是在屏幕上漂浮,并在一定程度上跟随鼠标.它与输入的声音相互作用,但是我注释掉了这些部分,以便可以在画布上查看它,它不应真正改变问题,我只是想指出来.

Eventually, I'll add reproduction, but as of now the creatures just sort of float around the screen, and follow the mouse somewhat. It interacts with sound from the line in, but I commented those parts out so that it can be viewed on the canvas, it shouldn't really change the question, I just thought I would point it out.

截至目前,帧速率远低于我的理想水平,并且随着产生更多生物而逐渐降低.我是在犯一些根本性的错误,还是每帧运行了太多功能?

As of now, the framerate is far less than ideal for me, and it slowly lowers as more creatures are spawned. Am I making some fundamental mistake, or am I just running too many functions per frame?

这是源代码,您可以在浏览器中使用它这里:

Here's the source code, and you can play with it in the 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 i = 0; i < 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 i = 0; i <= 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();
        }
    }
}

推荐答案

正确的,正如我怀疑的那样,所有不必要的pushMatrix()popMatrix()调用和大量的行似乎是主要的罪魁祸首.有很多冗余代码.

Right, as I suspected, all the unnecessary pushMatrix(), popMatrix() calls and the large amount of lines seemed to be the main culprits, still, there was a lot of redundant code.

我只是以一种更简洁的方式重构了代码,它看起来运行良好. 这是我的改进"版本:

I simply refactored the code in a cleaner manner and it seems to run fine. Here is my 'improved' version:

int maxCreatures = 75;
int numCreatures = 0;
int spawnNthFrame = 50;//spawn a 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 i = 0; i < numCreatures; i++) creatures[i].update();
}

和Creature类:

and the Creature class:

class Creature{
 int x,y,cXInc,cYInc;//if x,y are ints, increments would be 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 for each piece = 360/number of hair lines
     float hairAngle,hairLength,hairCos,hairSin;
     for(int i = 0; i < 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);
   }
 }
}

好的,现在解释.

首先,我将与一个生物相关的所有变量与确定草图运行方式的全局"变量分开(产生了多少个生物,等等).

First, I separated all the variables that were related to one creature from the 'global' ones that determine how the sketch runs (how many creatures get spawned, etc.).

这使得主代码长约25行,而总长度却少于100行,不到原始代码的一半.

This makes the main code about 25 lines long and altogether a bit below 100 lines which is less than half of the original.

第一部分没有做任何特别的事情.在 draw()函数中,我不是每帧创建一个Creature,而是使用 spawnNthFrame 变量每N帧绘制一个,这使得查看状态的状态变得很容易.生物使它变慢.如果您为该变量设置一个较小的数字(如2),则每帧会产生大量生物.

The first part doesn't do anything special. In the draw() function, instead of creating a Creature every frame, I draw one every Nth frame using the spawnNthFrame variable, this made it easy to see which state of the creature made it slow. If you set a small number like 2 to that variable it should spawn a lot of creatures per frame.

Creature类具有存储在数组中的原始代码的所有属性.

The Creature class has all the properties the original code stored in arrays.

代替做

pushMatrix();
translate();
ellipse();
rotate()
ellipse()
popMatrix();

我只是在x,y处绘制椭圆. 关于旋转的一点提示.我注意到它们是增量 90度处理具有一些适合 90,180,360 度的常数 弧度: HALF_PI,PI,TWO_PI ,有时可能会方便.

I simply draw the ellipses at x,y. A little hint on the rotations. I've noticed they were increments of 90 degrees. Processing has some nice constants for 90,180,360 degrees in radians: HALF_PI, PI, TWO_PI which can be handy sometimes.

现在考虑多毛"的情况,这是我为自己注释的内容:

Now for the 'hairy' situation, here's something I commented out for myself:

//if(i == 1) for(int j = 0; j <= 360; j+=70) , well 360/70 is about 5, if (i == 2) , 12 hair
//if = 3-> 360 lines ? do you really need that many lines, that thick ? how about 30 ? 5*12=60, but if you draw the lines through the centre, not from the centre, you can get away with half the lines

因此,有3个用于绘制线条的循环,每个循环具有不同的增量.基本上 有360/70行,360/30行和360行. 大约有5,12和360行.关于5,12条线,我通过在中心绘制直径"线而不是从中心绘制半径"线而减少了一半.

So there were 3 loops for drawing lines, each having different increments. Basically there were either 360/70 lines, 360/30 lines and 360 lines. Roughly about 5,12 and 360 lines. About the 5,12 lines, I kind of halved that by drawing 'diameter' lines across the centre as opposed to 'radius' lines from the centre.

这就是我的意思,

我还认为,具有该strokeWeight和抖动动作的360行可能看起来像一束难以计数的行,所以我想,为什么要分开头发? :P

Also I think that 360 lines with that strokeWeight and the jittery motion will probably look like a bunch of lines hard to count, so I thought, why split hairs? :P

也许该生物看起来与60半径类似,这意味着30个直径.

Maybe the creature will look pretty similar with about 60 radii which means 30 diameters.

现在解释一下用于此的触发函数. 最主要的是极坐标到笛卡尔坐标"转换:

Now to explain a bit of the trig functions used for this. The main thing is the 'polar to cartesian' coordinates conversion:

极性类似于:

我正在圆上移动到一个由角度(非常类似于时钟的手柄)和半径(距中心的距离)所描述的方向."

"I am moving on a circle to a direction described by an angle (much like one handle of a clock) and radius (distance from centre)."

和笛卡尔

我正在基于两个(水平/X和垂直/Y)移动,有点像曼哈顿的街道,但我作弊并且还斜着穿过墙."

"I'm moving based on two axes (horizontal/X and vertical/Y), kind of like the streets of Manhattan, but I cheat and also move diagonally through walls."

如果有任何意义... :) 无论如何,您可以使用以下公式将角度和半径对转换为 x和y 对:

If that makes any sense... :) Anyway, you convert the angle and radius pair to the x and y pair using the formula:

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

对于每一行:

angle = hairAngle
radius = hairLength

所以带有* x +(hairCos * -hairLength)*的 line()看起来有点像这样:

So the line() with *x + (hairCos * -hairLength)* looks a bit like this:

x + (hairCos * -hairLength) = 
move to x and from there move by hairLength
to the left(-) for the current angle (hairCos)

与y相似,但使用cos,因此这将线的第一个点放在从中心(即生物的x)移动的角度的相反正方向(-hairLength),第二个为对角线".想象一下绘制对角线"(从(-x,-y)到(+ x,+ y)),但是您也旋转它们.

Similar for y, but using cos, so this puts the first point of the line in the opposite direct (-hairLength) of the angle moving from the centre (which is the Creature's x) and the second is 'diagonal'. Imagine drawing 'diagonals' (from (-x,-y) to (+x,+y)), but you also rotate these.

更新

显然也可以复制/粘贴此代码也可以在javascript中使用(最好在Chromium/Chrome中查看).您也可以在此处运行它:

Apparently copy/pasting this code works in javascript too (best viewed in Chromium/Chrome). You can also run it right here:

var maxCreatures = 75;
var numCreatures = 0;
var spawnNthFrame = 50;//spawn a 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 i = 0; i < 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 for each piece = 360/number of hair lines
     var hairAngle,hairLength,hairCos,hairSin;
     for(var i = 0; i < 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>

这篇关于处理:如何提高程序的帧率?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆