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;
}
}
我在 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;
}
}