P5js 显示递归发生

P5js Display recursion happening

我在 p5js 中弄乱了递归,我想知道是否可以显示递归的发生。例如,我将使用 p5js 网站上提供的代码:

function setup() {
  createCanvas(720, 400);
  noStroke();
  noLoop();
}

function draw() {
  drawCircle(width / 2, 280, 6);
}

function drawCircle(x, radius, level) {
  const tt = (126 * level) / 4.0;
  fill(tt);
  ellipse(x, height / 2, radius * 2, radius * 2);
  if (level > 1) {
    level = level - 1;
    drawCircle(x - radius / 2, radius / 2, level);
    drawCircle(x + radius / 2, radius / 2, level);
  }
}

它运行它并立即显示所有内容。有什么办法可以改变它,让它显示每个单独的圆圈形成吗?

这可能不是最简洁的方法,但您可以将每个递归步骤存储为匿名函数,并在每次调用 draw 时迭代这些函数。

function setup() {
  createCanvas(720, 400);
  noStroke();
  frameRate(1);
  nextLevel=[];
  nextLevel.push(() => drawCircle(width / 2, 280, 6));
}

function draw() {
  thisLevel = [...nextLevel]
  nextLevel = []
  for(func of thisLevel){
    func()
  }
}

function drawCircle(x, radius, level) {
  const tt = (126 * level) / 4.0;
  fill(tt);
  ellipse(x, height / 2, radius * 2, radius * 2);
  if (level > 1) {
    level = level - 1; 
    nextLevel.push(() => drawCircle(x - radius / 2, radius / 2, level));
    nextLevel.push(() => drawCircle(x + radius / 2, radius / 2, level));
  }
}

这将导致此可视化:

您可以尝试一种更 object-oriented 的方法,方法是保留一个可以循环访问的圆对象列表。

圆形对象将跟踪显示自身的所有相关信息,以及显示自身的方法。

在调用下一级递归之前,调用 redraw(),它将绘制所有已保存的圆。

为了延迟下一关的动画效果,请使用 setTimeout()。

let Circle = function(x,radius,tt){
    this.x=x;
    this.radius=radius;
    this.tt=tt;
    this.display=function(){
        fill(this.tt);
        ellipse(this.x, height / 2, this.radius * 2, this.radius * 2);
    }
}

let circles = [];

function setup() {
  createCanvas(720, 400);
  noStroke();
  noLoop();
  drawCircle(width / 2, 280, 8);
}

function draw() {
  for(let circle of circles) {
      circle.display();
  }
}

function drawCircle(x, radius, level) {
  const tt = (126 * level) / 4.0 - 35;
  circles.push(new Circle(x,radius,tt));
  redraw()
  if (level > 1) {
    level = level - 1;
    setTimeout( function() {
      drawCircle(x - radius / 2, radius / 2, level);
      drawCircle(x + radius / 2, radius / 2, level);
    },1500)

  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script>

也许最简单的方法就是经常增加关卡并重绘。在下面的代码中,setInterval 每 500 毫秒递增一次 step 变量,然后其余代码保持不变。

let step = 1;

function setup() {
  createCanvas(720, 400);
  noStroke();
  noLoop();

  // increment step every half second
  setInterval(() => {
    if (++step == 7) step = 1;
    draw();
  }, 500);
}

function draw() {
  drawCircle(width / 2, 280, step);
}

function drawCircle(x, radius, level) {
  fill((126 * level) / 4.0);
  ellipse(x, height / 2, radius * 2, radius * 2);
  if (level-- > 1) {
    drawCircle(x - radius / 2, radius / 2, level);
    drawCircle(x + radius / 2, radius / 2, level);
  }
}

一种方法是:不使用递归来绘制圆圈,而是使用它将这些圆圈作为对象添加到数组中。然后,递归完成后,您可以使用 draw() 函数一次绘制一个圆圈。这将使它们以与在递归中创建时相同的顺序出现:

let circles = [];
let i = 0;

function setup() {
  createCanvas(720, 400);
  noStroke();
  drawCircle(width / 2, 280, 6);
  frameRate(5);
}

// draw the array of circles one at a time
function draw() {
  let c = circles[i++];
  fill(c.col);
  circle(c.x, height/2, c.r);
  if (i == circles.length) 
    noLoop();
}

function drawCircle(x, radius, level) {
  const tt = (126 * level) / 4.0;
  
  // push the circle object into the array
  circles.push(new Circle(x, radius * 2, tt));
  
  if (level > 1) {
    level = level - 1;
    drawCircle(x - radius / 2, radius / 2, level);
    drawCircle(x + radius / 2, radius / 2, level);
  }
}

class Circle {
  constructor(x, r, col) {
    this.x = x;
    this.r = r;
    this.col = col;
  }
}