2

I am trying to create some custom shapes in p5js by plotting a certain number of vertices (determined by stepCount) in a circular shape and then connecting the points.

Depending on the stepCount, the shape can be a line, rectangle, pentagon, hexagon, etc., all the way up to a circle. When I hardcode the stepCount and refresh the page, the changes are reflected as intended.

The problem is that I want to use dat.GUI to manipulate the stepCount live from the page. When I do this, I get a flashing outline with the intended shape clipped out of it.

This is my code below:

let p;
let x;
let y;

function setup() {
  createCanvas(windowWidth, windowHeight);
  p = new Planet();
  console.log("Planet generated.");
  let gui = new dat.GUI();
  gui.add(p, 'radius', 0, 500);
  gui.add(p, 'stepCount', 0, 50)

}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

function draw() {
  background(100);
  makePlanet();
}

function Planet() {
  this.radius = 200;
  this.angle = 0;
  this.stepCount = 20;
  this.step = TWO_PI / this.stepCount;
  this.angle = 0;
}

function makePlanet() {
  beginShape();
  for (i = 0; i < p.stepCount + 1; i++) {
    x = p.radius * sin(p.angle);
    y = p.radius * cos(p.angle);
    vertex(windowWidth / 2 - x, windowHeight / 2 - y);
    p.angle = p.angle + p.step;
    if (i >= p.stepCount) {
      endShape();
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>

I know that this has something to do with p.angle = p.angle + p.step running in a loop, but I'm having trouble figuring out whether the solution is mathematical or lies in the way I'm storing the variables in Planet().

Any guidance is greatly appreciated, I just want to learn.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174

1 Answers1

1

You've to round the p.stepCount to an integral value. The angle for one step depends on the number of steps, so it has to be recalculated (p.steps). p.angle should be reset in every frame, to start at beginning:

function makePlanet() {
    // round stepCount
    stepCount =  round(p.stepCount);
    // calculate step angle 
    p.steps = TWO_PI / stepCount;
    // reset start angle
    p.angle = 0;
    // create shape
    beginShape();
    for (i = 0; i <= stepCount; i++) {
        x = p.radius * sin(p.angle);
        y = p.radius * cos(p.angle);
        vertex(windowWidth / 2 - x, windowHeight / 2 - y);
        p.angle = p.angle + p.steps;
        if (i >= stepCount) {
            endShape();
        }
    }
}

Further more, the minimum number of steps should be 3:

gui.add(p, 'stepCount', 3, 50)

See the example

let p, x, y;

function setup() {
    createCanvas(windowWidth, windowHeight);
    p = new Planet();
    console.log("Planet generated.");
    let gui = new dat.GUI();
    gui.add(p, 'radius', 0, 500);
    gui.add(p, 'stepCount', 3, 50)
}

function windowResized() {
    resizeCanvas(windowWidth, windowHeight);
}

function draw() {
    background(100);
    makePlanet();
}

function Planet() {
    this.radius = 50;
    this.angle = 0;
    this.stepCount = 5
    this.step = TWO_PI / this.stepCount;
    this.angle = 0;
}

function makePlanet() {
    // round stepCount
    stepCount =  round(p.stepCount);
    // calculate step angle 
    p.steps = TWO_PI / stepCount;
    // reset start angle
    p.angle = 0;
    // create shape
    beginShape();
    for (i = 0; i <= stepCount; i++) {
        x = p.radius * sin(p.angle);
        y = p.radius * cos(p.angle);
        vertex(windowWidth / 2 - x, windowHeight / 2 - y);
        p.angle = p.angle + p.steps;
        if (i >= stepCount) {
            endShape();
        }
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thanks, it works! Since I wanted to add the capability for drawing lines and points, I was also able to reach a solution by changing the following: `gui.add(p, 'stepCount', 3, 50)` to `gui.add(p, 'stepCount', 0, 50).step(1)` – Anokhee Jandhyala Dec 17 '19 at 19:20