p5.js shape update issue - javascript

Um. I need help with the following p5.js code to make the shapes stop "bluring"
I mean how to make it so those shapes no longer have trails.
I believe the issue is relates to the "update" part. But i am not sure how to fix it.
Thanks
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(40, 100, 124);
background(backCol);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
noFill();
noStroke();
rect(0, 0, width, height);
for (let a = 0; a < cubes.length; a++) {
cubes[a].update();
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 50;
}
update() {
this.shape();
}
shape() {
push();
stroke(255);
translate(this.x - width / 2, this.y - height / 2, 0);
rotateX(millis() / 1000);
rotateY(millis() / 800);
ambientMaterial('clear');
box(this.size);
pop();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

You have to clear the background, by background() at begin of draw:
function draw() {
background(backCol);
noFill();
noStroke();
rect(0, 0, width, height);
for (let a = 0; a < cubes.length; a++) {
cubes[a].update();
}
}
Note, background() does not just set the background color, it actually clears the background. Invoking background() in draw(), ensures that the canvas is cleared in every frame.
See the example:
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(40, 100, 124);
background(backCol);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
noStroke();
rect(0, 0, width, height);
for (let a = 0; a < cubes.length; a++) {
cubes[a].update();
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 50;
}
update() {
this.shape();
}
shape() {
push();
stroke(255);
translate(this.x - width / 2, this.y - height / 2, 0);
rotateX(millis() / 1000);
rotateY(millis() / 800);
ambientMaterial('clear');
box(this.size);
pop();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

Related

Translate processing to p5.js

Could someone explain to me why this translation doesn't work?
Since I'm super new to both processing and p5.js, I keep getting error messages...
This is the processing code that I'd like to change.
Particle[] particles;
float alpha;
void setup() {
size(900, 500);
background(0);
noStroke();
setParticles();
}
void draw() {
frameRate(30);
alpha = map(height, 0, width, 5, 35);
fill(4, 255);
rect(0, 0, width, height);
background(0);
loadPixels();
for (Particle p : particles) {
p.move();
}
updatePixels();
}
void setParticles() {
particles = new Particle[10000];
for (int i = 0; i < 10000; i++) {
float x = random(width);
float y = random(height);
float adj = map(y, 0, height, 255, 0);
int c = color(60, adj, 255);
particles[i]= new Particle(x, y, c);
}
}
void mousePressed() {
setParticles();
}
class Particle {
float posX, posY, incr, theta;
color c;
Particle(float xIn, float yIn, color cIn) {
posX = xIn;
posY = yIn;
c = cIn;
}
public void move() {
update();
wrap();
display();
}
void update() {
incr += .008;
theta = noise(posX * .006, posY * .008, incr) * TWO_PI;
posX += 2 * tan(theta);
posY += 2 * sin(theta);
}
void display() {
if (posX > 0 && posX < width && posY > 0 && posY < height) {
pixels[(int)posX + (int)posY * width] = c;
}
}
void wrap() {
if (posX < 0) posX = width;
if (posX > width ) posX = 0;
if (posY < 0 ) posY = height;
if (posY > height) posY = 0;
}
}
And this is the p5.js translation which doesn't work.
var particles;
let particle = [];
const num = 100;
function setup() {
createCanvas(900, 500);
background(0);
noStroke();
setParticles();
}
function draw() {
frameRate(30);
let alpha = map(height, 0, width, 5, 35);
fill(0, alpha);
rect(0, 0, width, height);
loadPixels();
for (var i = 0; i < num; i++) {
particles[i].update();
particles[i].display();
particles[i].wrap();
}
updatePixels();
}
function setParticles() {
particles = new Array(10000);
for (var i = 0; i < 10000; i++) {
var x = random(width);
var y = random(height);
var adj = map(y, 0, height, 255, 0);
let c = color(60, adj, 255);
particles[i] = new Particle(x, y, c);
}
}
function mousePressed() {
setParticles();
}
function Particle (xln, yln, cln) {
this.posX = xln;
this.posY = yln;
this.c = cln;
this.update = function() {
this.incr += .008;
this.theta = noise(this.posX * .006, this.posY * .008, this.incr) * TWO_PI;
this.posX += 2 * tan(this.theta);
this.posY += 2 * sin(this.theta);
}
this.display = function() {
if (this.posX > 0 && this.posX < width && this.posY > 0 && this.posY < height) {
pixels[int(this.posX) + int(this.posY) * width] = c;
}
}
this.wrap = function() {
if (this.posX < 0)
this.posX = width;
if (this.posX > width)
this.posX = 0;
if (this.posY < 0)
this.posY = height;
if (this.posY > height)
this.posY = 0;
}
}
I'll be a great help if anyone with experience could help me!
Cool project! You're very close there were just a few things that needed tweaking.
If you plonk a console.log(this.posX) in the display() function you'll see that it's NaN, if you trace your steps you'll notice that it's caused by:
this.theta = noise(this.posX * 0.006, this.posY * 0.008, this.incr) * TWO_PI;
this.posX += 2 * sin(this.theta);
The problem here being that this.incr wasn't defined, so adding this.incr = 0 to the constructor fixes that.
The following line in the display function is missing a this. for c:
pixels[int(this.posX) + int(this.posY) * width] = c; // should be this.c
You're also not looping through all of the particles, which may be a concious decision but it looks pretty awesome when you do:
for (var i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].display();
particles[i].wrap();
}
When dealing with pixels you have to consider that there are 4 elements in the pixels array which represent the R, G, B, A values in order of each pixel. So to get the index of a given X and Y:
let index = (int(this.posX) + int(this.posY) * width) * 4;
And lastly, you'll probably need to set pixelDensity(1) so that it covers the whole screen, more information can be found in the p5.js docs.
I've used es6 classes rather than functions, but the premise is the same:
var particles = [];
let particle = [];
const num = 100;
function setup() {
createCanvas(900, 400);
pixelDensity(1);
background(0);
noStroke();
setParticles();
}
function draw() {
frameRate(30);
let alpha = map(height, 0, width, 5, 35);
fill(0, alpha);
rect(0, 0, width, height);
loadPixels();
for (var i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].display();
particles[i].wrap();
}
updatePixels();
}
function setParticles() {
particles = new Array(10000);
for (var i = 0; i < 10000; i++) {
var x = random(width);
var y = random(height);
var adj = map(y, 0, height, 255, 0);
let c = color(60, adj, 255);
particles[i] = new Particle(x, y, c);
}
}
function mousePressed() {
setParticles();
}
class Particle {
constructor(xln, yln, cln) {
this.posX = xln;
this.posY = yln;
this.c = cln;
this.incr = 0;
}
update() {
this.incr += 0.008;
this.theta = noise(this.posX * 0.006, this.posY * 0.008, this.incr) * TWO_PI;
this.posX += 2 * tan(this.theta);
this.posY += 2 * sin(this.theta);
}
display() {
if (
this.posX > 0 &&
this.posX < width &&
this.posY > 0 &&
this.posY < height
) {
let index = (int(this.posX) + int(this.posY) * width) * 4;
pixels[index] = this.c;
pixels[index+1] = this.c;
pixels[index+2] = this.c;
pixels[index+3] = this.c;
}
}
wrap() {
if (this.posX < 0) this.posX = width;
if (this.posX > width) this.posX = 0;
if (this.posY < 0) this.posY = height;
if (this.posY > height) this.posY = 0;
}
}
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>
<main>
</main>
<script src="sketch.js"></script>
</body>
</html>
And here's a link to the p5.js editor sketch.

Perlin noise grid transformation question

Objective: Amend the compassGrid() function to create a grid of 25x25 lines of length stepSize. Make sure each compass is at the center of each tile. By default they should all be pointing up. You should use translate() to move to the center of each grid.
I've tried all kinds of stuff, but none of my attempts seem to reach the objective outlined above. Here’s my code:
var stepSize = 20;
function setup() {
createCanvas(500, 500);
}
///////////////////////////////////////////////////////////////////////
function draw() {
background(125);
colorGrid();
compassGrid();
}
///////////////////////////////////////////////////////////////////////
function colorGrid() {
for (var x = 0; x < width; x += width / 25) {
for (var y = 0; y < height; y += height / 25) {
let from = color(255, 0, 0);
let to = color(0, 255, 0);
let interA = lerpColor(from, to, n);
var n = noise(x / 50, y / 50, frameCount / 100);
var c = map(n, 0, 1, 0, 255);
fill(interA);
stroke(c);
rect(x, y, stepSize, stepSize);
}
}
}
///////////////////////////////////////////////////////////////////////
function compassGrid() {
translate(10, 10);
for (var x = 0; x < width; x += width / 25) {
for (var y = 0; y < height; y += height / 25) {
push();
translate(x, y);
stroke("black");
line(0, 0, 0, stepSize - 5);
pop();
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
What's my mistake?

How to push one object infront of another p5js javascript

I have been stuck on this for hours and am unsure on what to do.
Here is my code:
var circles = [];
var circles2 = [];
function setup() {
createCanvas(500, 500);
//there's a "b" for every "a"
for (var a = 50; a < width - 300; a += 20) {
for (var b = 50; b < height - 300; b += 20) {
//add the circles to the array at x = a and y = b
circles.push(new Circle(a, b));
circles2.push(new Conn(a, b));
}
}
for (var a = 250; a < width - 50; a += 20) {
for (var b = 250; b < height - 50; b += 20) {
//add the circles to the array at x = a and y = b
}
}
console.log(circles.length);
}
function draw() {
background(50);
for (var b = 0; b < circles.length; b++) {
circles2[b].show();
circles[b].show();
//console.log("shown");
}
for (var b = 0; b < circles2.length; b++) {
//circles2[b].show();
//console.log("shown");
}
}
function Circle(x, y) {
this.x = x;
this.y = y;
this.show = function() {
fill(255);
noStroke();
ellipse(this.x, this.y, 10, 10);
//console.log("showing");
push();
fill(255);
noStroke();
translate(250, 250);
ellipse(this.x, this.y, 10, 10);
pop();
}
}
function Conn(x, y) {
this.x = x;
this.y = y;
this.show = function() {
noStroke();
let h = 0;
for (let i = 0; i < 251; i++) {
fill(h, 90, 120);
h = (h + 1) % 500;
noStroke();
push()
ellipse(this.x + i, this.y + i, 10, 10);
noStroke();
noLoop();
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
It generates a grid of squares that is supposed to connect to a different grid of squares through gradient lines. However, only the bottom row and right most column of circles on the bottom right circle grid show up for some reason. How can I make it that all circles on the bottom right circle grid are in front of the gradient lines? I've tried push, pop, and everything else. I'm really confused as to why only some of the circles are showing up, but the others are stuck behind these gradients.
Unless you use p5.js in WEBGL mode then there is no object stacking order or z-index or z-buffer. Shapes that you draw always overlap whatever was drawn before them. So in order to make a shape appear on top of another you need to draw the shape underneath first, followed by the shape on top. I believe I was able to achieve this by rearranging your code a little:
var circles = [];
var connections = [];
function setup() {
createCanvas(500, 500);
//there's a "b" for every "a"
for (var a = 50; a < width - 300; a += 20) {
for (var b = 50; b < height - 300; b += 20) {
//add the circles to the array at x = a and y = b
circles.push(new Circle(a, b));
connections.push(new Conn(a, b));
}
}
for (var a = 250; a < width - 50; a += 20) {
for (var b = 250; b < height - 50; b += 20) {
//add the circles to the array at x = a and y = b
}
}
console.log(circles.length);
}
function draw() {
background(50);
// Show connections first
for (var b = 0; b < connections.length; b++) {
connections[b].show();
}
// Show circles second so that they appear on top of the connections
for (var b = 0; b < circles.length; b++) {
circles[b].show();
}
}
function Circle(x, y) {
this.x = x;
this.y = y;
this.show = function() {
fill(255);
noStroke();
ellipse(this.x, this.y, 10, 10);
//console.log("showing");
push();
fill(255);
noStroke();
translate(250, 250);
ellipse(this.x, this.y, 10, 10);
pop();
}
}
function Conn(x, y) {
this.x = x;
this.y = y;
this.show = function() {
noStroke();
let h = 0;
for (let i = 0; i < 251; i++) {
fill(h, 90, 120);
h = (h + 1) % 500;
noStroke();
push()
ellipse(this.x + i, this.y + i, 10, 10);
noStroke();
noLoop();
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

loop object over canvas JS P5

I use JS P5.
I've created a function that creates an ellipse.
I want to loop this ellipse over the whole canvas with some distance between each ellipse.
I didn't use a normal ellipse because I want to put another function on each ellipse later.
So my question how to use a for loop and a nested loop on an object that I create.
This is my code, I have a random way here, but I want is the exact distance, like a grid over the whole page.
Like this example
let shapes = [];
function setup() {
createCanvas(600, 600);
for (let i = 0; i < 500; i++){
let x = random(width);
let y = random(height);
shapes[i] = new shape(x,y,20);
}
}
function draw() {
background(220);
for (let i = 0; i < shapes.length; i++){
shapes[i].display();
}
}
function shape(tx, ty, ts) {
this.x = tx;
this.y = ty;
this.size = ts;
this.angle = 0;
this.update = function(mx, my) {
this.angle = atan2(my - this.y, mx - this.x);
};
this.display = function() {
push();
fill(153, 204, 0);
ellipse(this.x, this.y, this.size, this.size);
pop();
};
}
Edited answer:
let shapes = [];
function setup() {
createCanvas(600, 600);
for(var x=0;x<width;x+=30){
for(var y=0;y<height;y+=30){
shapes.push(new shape(x,y,20));
}
}
}
function draw() {
background(220);
for (let i = 0; i < shapes.length; i++){
shapes[i].display();
}
}
function shape(tx, ty, ts) {
this.x = tx;
this.y = ty;
this.size = ts;
this.angle = 0;
this.update = function(mx, my) {
this.angle = atan2(my - this.y, mx - this.x);
};
this.display = function() {
push();
fill(153, 204, 0);
ellipse(this.x, this.y, this.size, this.size);
pop();
};
}

P5.js how to do 8 directional lerp color/color change?

A last issue i have in this code is that i am not sure how to create color change effect as 8 directional.
I can only map a mouseX to make it lerpColor horizontally or vertically .
But how do i make it work through moving both mouseX and mouseY?
I had it in shift_Color method within the class. I tried to state that within a certain dist(), lerpColor. But now it only showing black color rather than the changing color effect.
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(243, 243, 243);
//background(backCol);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let a = 0; a < cubes.length; a++) {
cubes[a].update();
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 30;
this.stroke = 70;
this.gap = 110
this.shift1 = color(96);
this.shift2 = color(244);
}
update() {
this.shape();
this.shift_Color();
}
shape() {
push();
stroke(this.stroke);
//fill(this.shift1);
this.shift_Color();
translate(this.x - width / 2, this.y - height / 2, 0);
this.magnetic()
box(this.size);
pop();
}
shift_Color() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.shift1 = color(96);
this.shift2 = color(244);
this.shiftX = map(mouseX - width/2,this.gap,distance,0,1.0);
this.change = lerpColor(this.shift1, this.shift2, this.shiftX);
fill(this.change);
} else {
fill(this.shift1);
}
}
magnetic() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.attract = atan2(mouseY - this.y, mouseX - this.x);
rotateX(this.attract);
rotateY(this.attract);
} else {
rotateX(millis() / 1000);
rotateY(millis() / 1000);
}
}
}
If I understood your question properly, there are two problems in your code.
The first is the fact that because you are trying to map the distance between mouse and the cube to number between 0 and 1, you should write lerpColor(this.shift2, this.shift1, this.shiftX) instead of lerpColor(this.shift1, this.shift2, this.shiftX), since this.shift2 is the lighter color and will be the inner color.
Another problem is when mapping the change variable, change should be calculated based on the distance between mouse and the cube (which is the distance variable), not mouseX or mouseY. Solution is to simply do map(distance, 0, this.gap, 0, 1);.
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(243, 243, 243);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let cube of cubes) {
cube.update();
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 30;
this.stroke = 70;
this.gap = 110
this.shift1 = color(96);
this.shift2 = color(244);
}
update() {
this.shape();
this.shift_Color();
}
shape() {
push();
stroke(this.stroke);
//fill(this.shift1);
this.shift_Color();
translate(this.x - width / 2, this.y - height / 2, 0);
this.magnetic()
box(this.size);
pop();
}
shift_Color() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.shiftX = map(distance, 0, this.gap, 0, 1);
// this.shiftX = map(mouseX - width/2,this.gap,distance,0,1.0);
this.change = lerpColor(this.shift2, this.shift1, this.shiftX);
// this.change = lerpColor(this.shift1, this.shift2, this.shiftX);
fill(this.change);
} else {
fill(this.shift1);
}
}
magnetic() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.attract = atan2(mouseY - this.y, mouseX - this.x);
rotateX(this.attract);
rotateY(this.attract);
} else {
rotateX(millis() / 1000);
rotateY(millis() / 1000);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
I also modified some of your code. Like the line
this.shift1 = color(96);
this.shift2 = color(244);
which is not needed currently since neither of these variable changes during execution.

Categories

Resources