【问题标题】:How can I optimize an animation in Processing, and keep it from leaving a trail of images?如何在处理中优化动画,并防止它留下图像痕迹?
【发布时间】:2019-05-29 01:47:10
【问题描述】:

我正在创建一个正在处理的太阳系模型,在移除背景后,我注意到行星在它们身后留下了它们图像的痕迹。当后台重新进入时,程序运行良好,但我想添加更多内容,我确信这效率低下并且会陷入困境。

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

这些只是我认为从代码中挑选出来的重要部分,这只是一个星球的例子。对不起,如果代码很笨拙,任何建议都乐意接受。

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();
  }
}

我意识到这可能会发生,但我不知道如何阻止它。

【问题讨论】:

  • 此时我不会担心优化任何东西。将先前的 X 位置存储在 ArrayList 中,并在每一帧重绘它们。我的猜测是你想做的任何事情都可以。

标签: animation optimization processing


【解决方案1】:

您描述的行为只是计算机图形学的本质;这就是游戏、操作系统和硬件显示器的工作方式——它们每帧都会清除和重绘所有内容。

Processing 中,被推送到缓冲区的图形对象会无限期地保留在那里,直到缓冲区被清除或将某些东西推到它们上面(这就是为什么行星在不调用 @ 的情况下留下轨迹的原因987654321@ – 之前的帧保留在缓冲区中)。

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

Processing 确实提供了clear() 函数,但这等效于background(0)

如果您仍然关心效率和速度,加快处理速度的一种方法是使用FX2D 渲染器而不是默认的AWT 渲染器。另一种方法是将绘制的对象缓存到PGraphics 对象中以防止连续光栅化(因为您的行星是图像文件而不是经过处理绘制的,所以您不必担心这一点)。

【讨论】:

    【解决方案2】:

    您的代码很简单,在这个阶段不需要优化。 正如 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();
      }
    }
    

    这是一个高效的快速'n'dirty hack,因为您不需要存储以前的位置并多次重绘,但是它在轨迹的灵活性方面存在局限性。希望调整 fill() alpha 参数可以获得您想要的效果。

    稍后,如果您要绘制许多许多行星,它会开始缓慢运行,并在VisualVM 达到峰值。分析 CPU 并查看完成时间最长的方法并专注于这些方法。不需要优化一切,只需要最慢的调用。请记住,Processing 有多个渲染器:JAVA2D 是默认渲染器,但也有 FX2DP2D/P3D,它们的行为会有所不同。我强烈建议在最后一刻进行优化(否则代码的灵活性和可读性可能会降低,并且会减慢开发/迭代速度)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-05
      • 2019-06-09
      • 1970-01-01
      • 2018-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-04
      相关资源
      最近更新 更多