如何在“处理”中优化动画,并使其不留下图像痕迹?

时间:2019-05-29 01:47:10

标签: animation optimization processing

我正在创建一个正在处理的太阳系模型,删除背景后,我发现行星正向其留下一道影像。回到背景时,程序可以正常运行,但是我想添加更多内容,并且我肯定这效率不高,并且会使事情陷入困境。

我对处理非常陌生,我真的不确定如何解决这个问题。也许在延迟创建短径后删除以前的图像?

这些只是我认为是从代码中挑选出来的重要樱桃的部分,这只是一个行星的示例。抱歉,如果代码很笨拙,任何建议都会很高兴地接受。

Planet p1;

void setup() {
 mercury = loadImage("mercury.png")

 p1 = new Planet(40, random(TWO_PI), 0.05);

}

void draw() {
  //background(0)
  translate(width / 2, height / 2);
  p1.display1();
  p1.orbit();
}


class Planet  {
  float radius;
  float angle;
  float distance;
  float orbitSpeed;

  Planet(float r, float d, float o) {
     radius = r;
     distance = d;
     orbitSpeed = o;
     angle = random(TWO_PI);
  }

  void orbit() {
    angle = angle + orbitSpeed;
  }

  void display1() {
    pushMatrix();
    rotate(angle);
    translate(distance, 0);
    imageMode(CENTER);
    image(mercury, radius, radius, 10, 10);
    popMatrix();
  }
}

我意识到这可能会发生,而且我不确定如何阻止它。

2 个答案:

答案 0 :(得分:0)

您描述的行为仅仅是计算机图形的本质;这就是游戏,操作系统和硬件显示所有工作的方式–它们清除并重新绘制每一帧的所有内容。

处理中,被推到缓冲区的图形对象会无限期地保留在那里,直到缓冲区被清除或在其上方推入某些东西为止(这就是为什么行星在不调用{ {1}} –先前的帧保留在缓冲区中。

您担心background()效率低下。不能,因为它是最快的操作之一(只需设置每个像素的值,由用户指定)。

处理过程确实提供了background()函数,但这等效于clear()

如果您仍然担心效率和速度,加快处理速度的一种方法是使用background(0)渲染器而不是默认的FX2D渲染器。另一种方法是将绘制的对象缓存到AWT对象中,以防止连续进行栅格化(由于您的行星是图像文件,并且未进行处理绘制,因此您不必担心)。

答案 1 :(得分:0)

您的代码非常简单,因此在此阶段不需要优化。 正如micycle所说,您正在以平移的位置绘制图像,与blitting非常相似。

就路径而言,您可以使用的一种常见技巧不是完全清除屏幕,而是绘制一个透明矩形作为背景。透明度越高,足迹越长。

这是您代码的经过调整的版本:

// planet object
Planet p1;
// planet texture
PImage mercury;

void setup() {
  size(300, 300);
  // draw image from center
  imageMode(CENTER);
  // clear to black one
  background(0);
  // remove strokes (we'll use rect() later)
  noStroke();
  // set the fill to black but with 9/255 transparency (~3.5% transparent)
  fill(0,9);
  // init texture
  mercury = loadImage("mercury.png");
  // init planet
  p1 = new Planet(40, random(TWO_PI), 0.05);
}

void draw() {
  // draw a transparent rectangle instead of completely clearing the screen
  rect(0,0,width,height);
  // render planet
  translate(width / 2, height / 2);
  p1.display1();
  p1.orbit();
}


class Planet {
  float radius;
  float angle;
  float distance;
  float orbitSpeed;

  Planet(float r, float d, float o) {
    radius = r;
    distance = d;
    orbitSpeed = o;
    angle = random(TWO_PI);
  }

  void orbit() {
    angle = angle + orbitSpeed;
  }

  void display1() {
    pushMatrix();
    rotate(angle);
    translate(distance, 0);
    image(mercury, radius, radius, 10, 10);
    popMatrix();
  }
}

这是一种高效的快速“肮脏”技巧,因为您无需存储先前的位置并重画多次,但是它在步道的灵活性方面具有局限性。希望通过调整fill() alpha参数可以达到理想的效果。

稍后,如果您要绘制许多许多行星,那么事情开始缓慢运行时会在VisualVM达到峰值。对CPU进行概要分析,并查看花费最长时间完成的方法,并集中精力研究这些方法。无需优化所有操作,只需最慢的调用即可。请记住,“处理”具有多个渲染器:JAVA2D是默认渲染器,但是还有FX2DP2D / P3D,它们的行为会有所不同。我强烈建议您在最后一刻进行优化(否则代码的灵活性和可读性可能会降低,从而减慢开发/迭代速度。)