【问题标题】:How can I handle drawing a circle, having that circle break, and begin drawing elsewhere?我如何处理画一个圆圈,让圆圈中断,然后开始在其他地方画?
【发布时间】:2014-11-08 09:35:45
【问题描述】:

在处理中工作,我正在尝试构建我的第一个生成补丁。我想要发生的是开始在屏幕上的某个地方画一个圆圈(一个沿着圆圈路径的点),但是在随机的时间后,圆圈会破裂,线会在随机的方向上随机移动一段时间,并开始在别处画一个新的圆圈。

现在我画了一个圆圈,我有一个切换机制,可以在随机时间后打开和关闭。我不知道如何让它从原来的圈子“打破”,更不用说让它在其他地方开始一个新的圈子了。有人会对如何做到这一点有一些建议吗?我认为它可能有一个有趣的视觉效果。

Rotor r;
float timer = 0;
boolean freeze = false;

void setup() {
  size(1000,600);
  smooth();
  noFill();
  frameRate(60);
  background(255);

  timeLimit();
  r = new Rotor(random(width),random(height),random(40,100));
}

void draw() {
  float t = frameCount / 100.0;
  timer = timer + frameRate/1000;

  r.drawRotor(t);

  if(timer > timeLimit()){
    timer = 0;
    timeLimit();

    if(freeze == true){
      freeze = false; 
    }else{
      freeze = true;
    }

    background(255);
  }
}

float timeLimit(){
  float timeLimit = random(200); 
  return timeLimit;
}

转子类:

class Rotor {

  color c;
  int thickness;
  float xPoint;
  float yPoint;
  float radius;
  float angle = 0;
  float centerX;
  float centerY;

  Rotor(float cX, float cY, float rad) {
    c = color(0);
    thickness = 1;
    centerX = cX;
    centerY = cY;
    radius = rad;
  } 

  void drawRotor(float t) {
    stroke(c);
    strokeWeight(thickness);
    angle = angle + frameRate/1000;
    xPoint = centerX + cos(angle) * radius;
    yPoint = centerY + sin(angle) * radius;
    ellipse(xPoint, yPoint,thickness,thickness);
  }


}

【问题讨论】:

    标签: geometry processing


    【解决方案1】:

    调用background()通常是在draw中的第一件事。这是因为绘图仅在每个循环(帧)结束时呈现。因此,在开始时调用 bg 将清除最后一帧中绘制的所有内容。如果您需要坚持通过帧绘制,可以删除对background() 的调用,或者每帧绘制你的东西。或者在 PGraphics 中绘制东西并显示它。

    另一件事是每次“转子”停止时,你应该给它新的随机坐标。

    如果您要删除 background() 调用,则可以解决问题:

    Rotor r;
    float timer = 0;
    boolean freeze = false;
    
    void setup() {
      size(1000,600);
      smooth();
      noFill();
      frameRate(60);
      background(255);
    
      timeLimit();
    
      r = new Rotor(random(width),random(height),random(40,100));
    
    
    }
    
    void draw() {
      float t = frameCount / 100.0;
      timer = timer + frameRate/1000;
    
      r.drawRotor(t);
    
      if(timer > timeLimit()){
        timer = 0;
        timeLimit();
    
    
        //***** here new coordinates!!
         r = new Rotor(random(width),random(height),random(40,100));
        //*****
    
    
        if(freeze == true){
          freeze = false; 
        }else{
          freeze = true;
        }
    
    
    
        //***** no background()
        // background(255);
      }
    }
    
    float timeLimit(){
      float timeLimit = random(200); 
      return timeLimit;
    }
    
    class Rotor {
    
      color c;
      int thickness;
      float xPoint;
      float yPoint;
      float radius;
      float angle = 0;
      float centerX;
      float centerY;
    
      Rotor(float cX, float cY, float rad) {
        c = color(0);
        thickness = 1;
        centerX = cX;
        centerY = cY;
        radius = rad;
      } 
    
      void drawRotor(float t) {
        stroke(c);
        strokeWeight(thickness);
        angle = angle + frameRate/1000;
        xPoint = centerX + cos(angle) * radius;
        yPoint = centerY + sin(angle) * radius;
        ellipse(xPoint, yPoint,thickness,thickness);
      }
    
    
    }
    

    现在,如果您需要清屏,您可以制作一个列表(ArrayList?),并在前一个完成后添加一个新的转子。但是您需要管理转子以便能够在不设置动画的情况下自行显示。所以新创建的转子会动画,旧的只会显示它的弧线而不动画。或者制作一个不调用 bg 的 PGraphis 并将其显示在可以调用 bg 的主画布中......

    附带说明,请注意,在 frameRate 中依赖时间的东西使其依赖于系统性能。您可以使用millis() 来避免这种情况。到目前为止还不是问题,因为这还很轻,但如果项目进一步发展,可能会成为问题。

    【讨论】:

      【解决方案2】:

      首先回答您关于“打破”圈子的问题:您需要创建新的rotor 实例或仅更改其属性,例如centerradius。如果我的想法正确,您只需要一个 rotor 实例,所以只需更改此值:

      r.centerX = newX;
      r.centerY = newY
      r.radius = random(40,100) //as you have in setup
      

      但是如何计算新位置?它可能是随机的,但您想创建路径,因此您需要计算它。棘手的部分来了。那么如何制作连接线并开始新的循环呢?

      首先你需要两个mode。首先画圆,第二画线。实现这一点的最简单方法是更新rotor draw 方法[您可以将mode 变量作为drawRotor 函数的参数或作为全局变量传递]:

      if(mode == 1){
        angle += frameRate/1000;
      }else{
        radius += 2;
      }
      

      如您所见,我只是在增加绘制圆的角度和增加绘制线的半径之间有所不同(不是随机方向,而是从中心开始)。然后我们需要计算圆心的新位置。为此,我们根据angle 简单计算它将如何继续并替换新的radius,因此整个部分将如下所示:

      if(mode != 1){              
        float newR = random(40,100);
        float newX = r.centerX + cos(r.angle) * (r.radius - newR);
        float newY = r.centerY + sin(r.angle) * (r.radius - newR);      
        r.newPos(newX, newY);
        r.radius = newR; //we cant change it earlier because we need also old value
      }
      

      仅当您将模式更改回绘图圈时,这才会在您的“时间处理程序”函数中发生。模式可以在处理程序中简单更改

       mode *= -1; //but need to be init to 1 inside setup()
      

      如果你想让路径始终可见,只需删除 background() 函数,但如果你想要一些很酷的效果,请在 draw() 的请求下添加它

      noStroke();              //No stroke needed and you turn it on again in drawRotor()
      fill( 255,255,255, 10 ); //This will set transparency to 10%
      rect(0,0,width,height);  //You put layer after each "point" you draw
      noFill();                //This will restore fill settings as you have before 
      

      Here我粘贴整个代码只是为了演示,您应该根据自己的目的修改它。最好编写自己的版本。

      【讨论】:

        猜你喜欢
        • 2012-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多