setInterval function running indefinitely on two activations? - p5.js

I'm using setInterval in a simple sketch that generates a shape + text in random colors, rotation, and locations five times (using a counter). It activates on button press and works when the button is pressed once. However, when the button is pressed before the first five are down being drawn, the function repeats indefinitely. Would love tips on how to fix.
var canvas;
var interval;
var counter = 0;
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function setup () {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '-1')
background('white');
inp = createInput();
inp.position(80, 150);
inp.input(inputEvent);
button = createButton('Go');
button.position(85 + inp.width, 150);
button.mousePressed(indefSomewhere);
}
function inputEvent() {
console.log(this.value())
}
function goSomewhere() {
const place = inp.value();
// for (let i = 0; i < 20; i++) {
push();
fill(random(255), random(255), random(255));
translate(random(width), random(height));
rotate(random(2*PI));
noStroke();
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
scale(0.5);
endShape(CLOSE);
push();
fill(random(255), random(255), random(255));
text(place, 100, 124);
pop();
pop();
counter++;
console.log(counter);
if(counter >= 5) {
counter = 0;
clearInterval(interval);
console.log(counter);
} else if(counter === 0 ) {
clearInterval(interval);
}
// }
}
function indefSomewhere() {
interval = setInterval(goSomewhere, 100);
}
function draw() {
fill(0);
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
endShape(CLOSE);
fill(255);
if(inp.value() != null) {
textSize(32);
text(inp.value(), 87.5, 125);
}
}
EDIT: Okay, I've added a clear interval to the indefSomewhere() function and it prevents the indefinite drawing of shapes. However double clicking doesn't activate the drawing twice. Is setInterval simply the wrong choice for this situation?

If the problem comes when setInterval() is called while the interval is already set, I would make so that if the interval hasn't been set, it calls setInterval(), but if it has, it adds +5 to the limit of the counter.
This could be the code:
var canvas;
var interval;
var intervalSet;
var counter = 0;
var maxCounter;
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function setup () {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '-1')
background('white');
inp = createInput();
inp.position(80, 150);
inp.input(inputEvent);
button = createButton('Go');
button.position(85 + inp.width, 150);
button.mousePressed(indefSomewhere);
}
function inputEvent() {
console.log(this.value())
}
function goSomewhere() {
const place = inp.value();
// for (let i = 0; i < 20; i++) {
push();
fill(random(255), random(255), random(255));
translate(random(width), random(height));
rotate(random(2*PI));
noStroke();
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
scale(0.5);
endShape(CLOSE);
push();
fill(random(255), random(255), random(255));
text(place, 100, 124);
pop();
pop();
counter++;
console.log(counter);
if(counter >= maxCounter) {
counter = 0;
intervalSet = false;
clearInterval(interval);
console.log(counter);
} else if(counter === 0 ) {
intervalSet = false;
clearInterval(interval);
}
// }
}
function indefSomewhere() {
if(!intervalSet){
maxCounter = 5;
intervalSet = true;
interval = setInterval(goSomewhere, 100);
}else{
maxCounter += 5;
}
}
function draw() {
fill(0);
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
endShape(CLOSE);
fill(255);
if(inp.value() != null) {
textSize(32);
text(inp.value(), 87.5, 125);
}
}
This is a related question.

Related

Typewriter effect P5.JS

js and trying to animate a text for it to look as if it was being typed, but I am stuck with this...
var palabra= "Hola!"; =
var pos = 0;
function setup() {
createCanvas(canvasWH, canvasWH);
frameRate(10);
}
function draw() {
textFont('Georgia');
textSize(20);
text(palabra.substring(pos, pos + 1), pos+++, canvasWH/2, canvasWH, 100);
pos = +++
// Check if we are at the end to restart animation
if () {
//restart animation
}
}```
pos++ is the way to increment.
restartDelay controls how many frames to wait before clearing after drawing is complete
var palabra= "Hola!";
var pos = 0;
var restartDelay = 5;
function setup() {
createCanvas(500, 500);
frameRate(10);
}
function draw() {
background(255);
textFont('Georgia');
textSize(20);
text(palabra.substring(0, pos + 1), 50, 50);
pos++;
// Check if we are at the end to restart animation
if (pos > palabra.length + restartDelay) {
//restart animation
pos = 0;
}
}

How to use custom shapes in a repeating loop pattern?

I already made a custom shape (myFunction), and I also made patterns using simpler shapes. I want to know how to replace those simple shapes with my custom shape while maintaining the pattern drawn on processing...
You're already calling functions such as noFill(), noStroke(), etc.
It's the same for your function: call it by simply using it's name and () (because it has no arguments): myFunction();
Let's say you want to draw it in pattern 1, you could do something like:
if (pattern==1) {
for (int x=50; x<width; x+=100) {
for (int y=20; y<height; y+=100) {
myFunction();
}
}
}
You will need to pay attention to rendering though.
Running the above will not display anything you call in noFill() in myFunction() and also noStroke() in draw(), right after background(): you won't be able to see a shape with no fill and no stroke :)
One suggestion is to add a stroke:
void myFunction() {
noFill();
stroke(255);
ellipse(300, 300, 200, 400);
ellipse(300, 300, 400, 200);
translate(300, 300);
rotate(radians(130));
ellipse(0, 0, 200, 400);
translate(0, 0);
rotate(radians(0));
ellipse(0, 0, 400, 200);
}
Of course feel free to experiment and make this look nicer.
Here's a modified version of your sketch that uses a few key presses to change the pattern type and shape type at runtime:
int pattern = 1;
// 0 = pluseEllipseCluser, 1 = blobs, 2= myFunction spirograph circles
int shape = 0;
void setup() {
size(600, 600);
println("press 1,2 to change pattern");
println("press p/b/c to change shapes");
}
void draw() {
background(30);
noStroke();
if (pattern==1) {
for (int x=50; x<width; x+=100) {
for (int y=20; y<height; y+=100) {
drawSelectedShapes(x, y);
}
}
}
if (pattern==2) {
float rando = random(10, 90);
for (float x= rando; x >= 0; x-=random(2.5)) {
for (float y= rando; y >= 0; y-=random(2.5)) {
drawSelectedShapes(x, y);
}
}
}
}
void drawSelectedShapes(float x, float y){
if(shape == 0){
plusEllipseCluser(x, y);
}
if(shape == 1){
blobs();
}
if(shape == 2){
myFunction();
}
}
void plusEllipseCluser(float x, float y){
fill(random(255), random(255), random(255), random(255));
ellipse(x, y+30, 50, 20); //plus ellipse cluster
ellipse(x, y+30, 20, 50);
}
void blobs(){
noStroke();
fill(random(250), random(120), random(100));
ellipse(random(width), random(height), 20, 50);
noFill();
stroke(random(255));
ellipse(random(width), random(height), 50, 20);
}
void myFunction() {
noFill();
stroke(255);
ellipse(300, 300, 200, 400);
ellipse(300, 300, 400, 200);
translate(300, 300);
rotate(radians(130));
ellipse(0, 0, 200, 400);
translate(0, 0);
rotate(radians(0));
ellipse(0, 0, 400, 200);
}
void keyPressed(){
if(key == '1') {
pattern = 1;
}
if(key == '2') {
pattern = 2;
}
if(key == 'p'){
shape = 0;
}
if(key == 'b'){
shape = 1;
}
if(key == 'c'){
shape = 2;
}
}
Notice that the example above also calls plusEllipseCluser() passing two arguments: it's a basic example of defining and calling a function that takes two arguments. Of course you've already called functions with arguments before (e.g. random(min,max), ellipse(x,y,w,h), etc.)
Have fun with shapes and patterns.

p5.js not drawing a 3d box

I am creating a simulator using P5.js. Within the simulator, I need a green box, however it does not seem to be appearing. The code is below:
var outputs = [];
function setup() {
createCanvas(600, 400, WEBGL);
background(200);
for (var i = 0; i < 1; i++) {
drop = new Water(width / 2, height / 2, 0, 1);
outputs[i] = drop;
}
}
function draw() {
push();
translate(200, 150, 0);
stroke(0, 100, 0);
fill(0, 255, 0);
box(150, 150, 150);
pop();
for (var i = 0; i < outputs.length; i++) {
outputs[i].update();
}
background(200);
}
Here is the water class:
function Water(x_, y_, z_, yVel_) {
this.r = random(0.25, 1);
this.xOff = random(-(this.r / 10), (this.r / 10));
this.zOff = random(-(this.r / 10), (this.r / 10));
this.x = x_ + this.xOff;
this.y = y_;
this.z = z_ + this.zOff;
this.yVel = yVel_;
this.pos = createVector(this.x, this.y, this.z);
this.show = function() {
push();
translate(this.pos.x, this.pos.y, this.pos.z);
noStroke();
fill(0, 0, 255);
sphere(this.r * 2);
pop();
}
this.update = function() {
this.vel = createVector(random(-(this.r / 10), (this.r / 10)),
this.yVel, random(-(this.r / 10),
(this.r / 10)));
this.pos.add(this.vel);
this.show();
}
}
This is a web based simulation, with another module which appears to be working fine.
Any help would be greatly appreciated. Thanks in advance!
Removing the parts that require the Water class, and moving the background function call to the top of draw, it seems to work just fine.
So, the problem is
Either that you forgot to put background on top
Or something's wrong with the Water class.
Here's your code with the mentioned problems fixed.
var outputs = [];
function setup() {
createCanvas(600, 400, WEBGL);
}
function draw() {
background(200);
push();
translate(200, 150, 0);
stroke(0, 100, 0);
fill(0, 255, 0);
box(150, 150, 150);
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/p5.min.js"></script>
Its not rendering because you're background is over your scene
function draw() {
background(200);
push();
translate(200, 150, 0);
stroke(0, 100, 0);
fill(0, 255, 0);
box(150, 150, 150);
pop();
for (var i = 0; i < outputs.length; i++) {
outputs[i].update();
}
}
What your doing is drawing the box and the drops and you cover it all up with your background
if you don't have a background you will see how p5.js renders animation
p5.js not moving it, its just looping through draw every frame and the background covers up the previous frame

The line move with position in clmtrackr. How to create line with not moving by p5.js

I'm new to p5.js and I'm trying to create a horizontal line by using p5.js with the position 21 clmtrackr.js. But the line is moving. I want to create the line with not moving. Here my code.
var ctracker;
var trigHeight = 0;
var ypos = 0;
var button;
var test = false;
function setup() {
var videoInput = createCapture();
videoInput.size(400, 300);
videoInput.position(0, 0);
var cnv = createCanvas(400, 300);
cnv.position(0, 0);
ctracker = new clm.tracker();
ctracker.init(pModel);
ctracker.start(videoInput.elt);
noStroke();
button = createButton("set height");
button.position(150, 260);
button.mousePressed(showLine)
background(100);
}
function draw() {
clear();
noStroke();
var positions = ctracker.getCurrentPosition();
for (var i = 0; i < positions.length; i++) {
fill(0, 255, 0);
rect(positions[i][0], positions[i][1], 3, 3);
if (i == 21) {
ypos = positions[i][1];
}
}
stroke("rgb(0,255,0)");
strokeWeight(4);
test && line(0, trigHeight, width * 2, trigHeight
}
function showLine() {
test = true;
}
Thank you.

Processing - Move circle with cursor position

I made a simple drawing program to draw lines and increase/decrase the thickness of the line:
float strokeWeight = 2;
void setup() {
size(640, 360);
noSmooth();
fill(126);
background(255);
strokeWeight(strokeWeight);
}
void draw() {
background(0);
ellipse(mouseX, mouseY, strokeWeight/2, strokeWeight/2);
background(255);
if (mousePressed) {
stroke(0);
line(mouseX, mouseY, pmouseX, pmouseY);
}
if (keyPressed) {
if (key == '+') {
strokeWeight = strokeWeight + 0.5;
}
if (key == '-') {
strokeWeight = strokeWeight - 0.5;
}
if (strokeWeight >= 0.5) {
strokeWeight(strokeWeight);
}
}
}
Now I want to move a circle with my cursor that indicates the current thickness of the line. I tried something like this:
ellipse(mouseX, mouseY, strokeWeight/2, strokeWeight/2)
But this way it draws ellipses over and over again. Is there a way to "erase" the circle made before?
I am not 100% sure that I've understood your question, but you probably want to use PGrahics, on one you keep the lines, on the other you draw the circle.
float strokeWeight = 2;
PGraphics canvas;
PGraphics thickness_circle;
void setup() {
size(640, 360);
canvas = createGraphics(width, height);
thickness_circle = createGraphics(width, height);
thickness_circle.beginDraw();
thickness_circle.noFill();
thickness_circle.strokeWeight(1);
thickness_circle.stroke(255, 0, 0);
thickness_circle.endDraw();
}
void draw() {
background(255);
if (keyPressed) {
if (key == '+') {
strokeWeight += 0.5;
}
if (key == '-') {
strokeWeight -= 0.5;
}
strokeWeight = strokeWeight >= 0.5 ? strokeWeight : 0.5;
}
if (mousePressed) {
canvas.beginDraw();
canvas.strokeWeight(strokeWeight);
canvas.line(mouseX, mouseY, pmouseX, pmouseY);
canvas.endDraw();
}
image(canvas, 0, 0);
thickness_circle.beginDraw();
thickness_circle.clear();
thickness_circle.ellipse(mouseX, mouseY, strokeWeight, strokeWeight);
thickness_circle.endDraw();
image(thickness_circle, 0, 0);
}

Resources