4

I'm trying to create a wobbly circle with multiple ellipses in the background, however I can't add the for loop to the draw function otherwise it will be running in every frame, and if I add it to setup then the wobbly circle leaves a trace. And if I use clear() then it removes my background. How can I solve this, please?

function setup() {
  createCanvas(600, 600);

  for (var i = 0; i < 1000; i++){
    fill(255);
    ellipse(random(0, width), random(0, width), random(5, 5), random(5, 5));
  }
  
  x = width/2;       // Circle center x
  y = height/2;       // Circle center y
  r = 100;       // Circle radius
  verts = 200;   // Number of vertices for drawing the circle
  wobbleSlider = createSlider(0, 200, 100, 1);   // How much the circle radius can vary
  smthSlider = createSlider(1, 500, 70, 1);     // How smooth the noise function is (higher is smoother)
  t = 1;
  

}

function draw() {
  let wobble = wobbleSlider.value()
  let smth = smthSlider.value();

  //clear();
  t += 0.01
  beginShape()
    for(let i = 0; i < verts; i++){
      let f = noise(50*cos(i/verts*2*PI)/smth + t, 50*sin(i/verts*2*PI)/smth + t)
      vertex(x + (r+wobble*f) * cos( (i/verts) * 2 * PI ), y + (r+wobble*f) * sin( (i/verts) * 2 * PI ) )
    }
  endShape(CLOSE)

}
html, body {
  margin: 0;
  padding: 0;
}
canvas {
  display: block;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <script src="sketch.js"></script>
  </body>
</html>

enter image description here

tmmbt
  • 45
  • 4
  • What's wrong with the current code? – Konrad Nov 08 '22 at 23:25
  • @KonradLinkowski - I have added a screenshot to show better what the issue is. But basically, the frame is not being cleared, so every time it runs it leaves a "trace" from the wobble. – tmmbt Nov 08 '22 at 23:41
  • 2
    Might be worth taking a look at https://stackoverflow.com/questions/70231135/copy-canvas-to-graphics-object-in-p5-js, which contains an example of copying and restoring the canvas. The concept being that you copy the canvas once the background is established, and then restore it at the beginning of every draw() prior to laying down the wobbly circle. No guarantee that it'll be faster than redrawing the entire canvas, but worth a shot... – Trentium Nov 09 '22 at 00:58

1 Answers1

5

What you want is some sort of layering system that allows you to have a fixed background and draw over it things that chage. You can achieve this with graphics. It basically allows you to create an independent "canvas" and draw over it, then you can render it like an image in your animation.

First you use createGraphics which is similar to createCanvas with the difference that you can store the result in a variable like: let myGraphics = createGraphics(600,600). Then you draw over it like in your canvas. For example ellipse(...) becomes myGraphics.ellipse(...). Then you can render it using image like image(myGraphics, 0, 0).

See the working code below If this answers your question dont forget to mark it as the answer using the green check at the left of the answer so others can reference from it in the future :)

let background;

function setup() {
  createCanvas(600, 600);
  background = createGraphics(600, 400);
  
  for (var i = 0; i < 1000; i++){
    background.fill(255);
    background.ellipse(random(0, width), random(0, width), random(5, 5), random(5, 5));
  }
  
  x = width/2;       // Circle center x
  y = height/2;       // Circle center y
  r = 100;       // Circle radius
  verts = 200;   // Number of vertices for drawing the circle
  wobbleSlider = createSlider(0, 200, 100, 1);   // How much the circle radius can vary
  smthSlider = createSlider(1, 500, 70, 1);     // How smooth the noise function is (higher is smoother)
  t = 1;
  

}

function draw() {
  clear();
  image(background,0,0);
  let wobble = wobbleSlider.value()
  let smth = smthSlider.value();

  //clear();
  t += 0.01
  beginShape()
    for(let i = 0; i < verts; i++){
      let f = noise(50*cos(i/verts*2*PI)/smth + t, 50*sin(i/verts*2*PI)/smth + t)
      vertex(x + (r+wobble*f) * cos( (i/verts) * 2 * PI ), y + (r+wobble*f) * sin( (i/verts) * 2 * PI ) )
    }
  endShape(CLOSE)

}
html, body {
  margin: 0;
  padding: 0;
}
canvas {
  display: block;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <script src="sketch.js"></script>
  </body>
</html>
Daniel Cruz
  • 1,437
  • 3
  • 5
  • 19