p5.js Shape Adjustments Leaving Previous Outlines Visible - javascript

I am trying to simply adjust the shape of an object using a value derived from a slider on a screen using p5.js.
The issue I am having is that the outline of the previously drawn shapes remain, giving an after-trail effect.
I have tried the noStroke() modifier but that simply does not draw the shape. As well the noFill() gives an even weirder, yet still incorrect, behavoir.
Code Example: https://codepen.io/galleywest/pen/oejxyY
var slider
function setup() {
createCanvas(600, 600)
slider = createSlider(0, 50, 0)
}
function draw() {
rect(10, 10, 80, 80, slider.value())
}
How can I mitigate this behavior?

You need to call the background() function to clear out old frames.
var slider
function setup() {
createCanvas(600, 600)
slider = createSlider(0, 50, 0)
}
function draw() {
background(255, 0, 0); //draws a red background
rect(10, 10, 80, 80, slider.value())
}
More info can be found in the reference.

Related

Specific curvy bezier line in p5.js and separating color fills?

Apologies if this is a stupid question - I am completely, brand new to coding and am only on week 2 of learning JavaScript with p5.js.
I am trying to recreate this donut vector:
I have the circle and the inner circle, but how can I create that curvy line, and fill both sections with two different colors?
This is the code I have so far:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220, 249, 168);
fill(255, 189, 238);
strokeWeight(4);
ellipseMode(CENTER);
ellipse(200, 200, 250, 250);

How can I use same random background color to fill rectangle in P5js

I'm trying to do something in P5js. For this, I need to pick random color of an array for background that has to be in setup. Then I want to pick this random selected background color to fill rectangle under draw function.
There are other shapes with randomness under background that has to be run once. And there is another object under rectangle that has to be in a loop. That is why one is in setup and other one is under the draw function. But, I'm going to simplify my problem as:
function setup() {
createCanvas(400, 400);
colorsPaletteSecond = [color(0, 0, 0),
color(160, 57, 164),
color(93, 94, 198),
color(135, 198, 112), ];
let screenColor = random(colorsPaletteSecond);
background(screenColor);
}
function draw() {
stroke(0)
fill(screenColor);
rect(200,200,100,100);
}
I need to define screenColor in the draw section as well, to get the same color as the background. Any suggestions?
Simply move let screenColor to the shared scope so that it's accessible from both functions:
let screenColor;
function setup() {
createCanvas(400, 400);
const colorsPaletteSecond = [
color(0, 0, 0),
color(160, 57, 164),
color(93, 94, 198),
color(135, 198, 112),
];
screenColor = random(colorsPaletteSecond);
background(screenColor);
}
function draw() {
stroke(0);
fill(screenColor);
rect(200, 200, 100, 100);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>

How to move ellipse filled with an image to mask similar background?

I am a super early user of coding from Italy.
I came up with an idea to promote a company logo on their website and I almost reached the goal so I am sharing this problem.
The idea is to obtain a sort of clipping mask effect when the mouse/cursor move on the image
I've made so far a code that does the work with a still ellipse.
When I set the position parameters of the ellipse as mouseX and mouseY the effect does not work if not just a bit of a glitch at the start.
How can I make it work as intended?
Here you can find the link of what I have now:
https://editor.p5js.org/francesco.ficini.designer/full/FLBuhggW-
Here the code:
let img;
let imgbg2;
let maskImage;
function preload() {
img = loadImage("NeroP.jpg");
imgbg2 = loadImage("RossoP.jpg");
}
function setup() {
createCanvas(400, 225);
img.mask(img);
}
function draw() {
background(imgbg2, 0, 0);
//Immages
image(imgbg2, 0, 0);
image(img,0,0);
// Ellipse Mask
maskImage = createGraphics(400, 225);
maskImage.ellipse(200, 100, 50, 50);
imgbg2.mask(maskImage);
image(imgbg2, 0, 0);
}
The thing about the p5.Image.mask function is that it modifies the image that is being masked. Which means that any pixels that are cleared by the mask are gone for good. So if you want to dynamically change the mask you will need to make a copy of the original and re-apply the modified mask any time it changes.
Additionally you will want to avoid creating images and graphics objects in your draw() function because this can result in excessive memory allocation. Instead create a single set of graphics/images and re-use them.
let img;
let imgbg2;
let maskImage;
let maskResult;
function preload() {
img = loadImage("https://www.paulwheeler.us/files/NeroP.jpeg");
imgbg2 = loadImage("https://www.paulwheeler.us/files/RossoP.jpeg");
}
function setup() {
createCanvas(400, 225);
// Create graphics and image buffers in setup
maskImage = createGraphics(imgbg2.width, imgbg2.height);
maskResult = createImage(imgbg2.width, imgbg2.height);
}
function mouseMoved() {
if (maskResult) {
maskImage.clear();
// Ellipse
maskImage.ellipse(mouseX, mouseY, 50, 50);
// Copy the original imgbg2 to the maskResult image
maskResult.copy(
imgbg2,
0, 0, imgbg2.width, imgbg2.height,
0, 0, imgbg2.width, imgbg2.height
);
// apply the mask to maskResult
maskResult.mask(maskImage);
}
}
function draw() {
//Immagini
image(img, 0, 0);
// draw the masked version of the image
image(maskResult, 0, 0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

`line()` in p5js crosses the edges. Beside doing the math myself, is there an easier way to make the line just connect their edges?

I'm trying to draw a line to connect two given circles.
function setup() {
createCanvas(300, 100);
background(220);
noFill();
ellipse(150, 30, 20, 20);
ellipse(100, 50, 20, 20);
line(100, 50, 150, 30);
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.min.js"></script>
The parameters I get are the x, y of the circle's center. If I use the info directly, the line crosses both circles.
I know I can do the math, I'd just like to know if there is an easier way to make the line just connect their edges?
One easy way would be draw the line first then draw the circles and fill them with the background color this way the line inside the circles will be hidden, this only work if you don't mind the background and the circles color to be the same
function setup() {
createCanvas(300, 100);
background(220);
line(100, 50, 150, 30);
fill(220);
ellipse(150, 30, 20, 20);
ellipse(100, 50, 20, 20);
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.min.js"></script>
Using opaque circles
A solution similar to what Sarkar said before, as far as you don't mind the circles having a fill color (whether their color is the same or different to the background color, it doesn't matter), the easiest way of doing this is by simply making the circles cover the line by drawing them afterwards with any fill opaque color.
Using a graphics object
However, if you would like to have this shape as a transparent shape, in order to have more freedom with the use you intend to do of it, you could try this: you create a graphics object, you draw the line, then you activate the erase mode and draw the circles so they erase the part of the line they are overlapping, then you exit the erase mode and draw normally the unfilled circles. Once you have finished with your graphic, you use the image function to draw it over the canvas.
let graphic;
function setup() {
createCanvas(300, 100);
graphic = createGraphics(width, height);
graphic.line(100, 50, 150, 30);
graphic.erase();
graphic.ellipse(150, 30, 20, 20);
graphic.ellipse(100, 50, 20, 20);
graphic.noErase();
graphic.noFill();
graphic.ellipse(150, 30, 20, 20);
graphic.ellipse(100, 50, 20, 20);
background(220);
image(graphic,0,0);
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.min.js"></script>

Extreme Novice needing assistance with mousePressed() event

I am VERY new to P5.js/processing (taking programming for artists). I am trying to make a crude game where an image (Jar Jar) bounces across the screen and another image (lightsaber) that moves with the mouse and when the mouse attached image goes over the bouncing image then the lightsaber will be mirrored and activate a sound. If this at all makes sense...
I have the bouncing image part down so far, but I am unable to make the mousePressed() function work. like I mentioned, I need the "lightsaber.png" to flip when the mouse is pressed. Also, when the mouse is pressed and is directly over the JarJar image, how would I add a score count and sound event?
Thank you!
here is my code so far:
let jarJar;
let jarJarX=5;
let jarJarY=5;
let xspeed;
let yspeed;
let lightSaber;
function preload() {
jarJar = loadImage('jarjar.png');
lightSaber= loadImage ('lightSaber.png');
}
function setup() {
createCanvas(700,700);
xspeed=random (15,22);
yspeed=random (15,22);
}
function draw() {
background(0);
image (lightSaber,mouseX,mouseY,100,100);
image(jarJar,jarJarX,jarJarY, 140, 200);
jarJarX= jarJarX+xspeed;
if (jarJarX<=-300|| jarJarX>=width+200){
xspeed=xspeed*-1;
}
jarJarY= jarJarY+yspeed;
if (jarJarY<-200|| jarJarY>=height+200 ){
yspeed=yspeed*-1;
}
//picture mirrors when mouse pressed
if mouseClicked(){
scale(-1,1);
image(lightSaber);
}
//score counter coordinate with lightsaber hitting image
//
}
Let it be known that I'm not proficient at javaScript. This said, your question is quite simple so I can help anyway.
Some framework will have simple ways to mirror images. Processing likes to scale with a negative number. I re-coded some of your stuff to accommodate my changes. The main changes goes as follows:
I added a method to draw the lightsaber so we can "animate" it (read: flip it for a couple frames when the user clicks around).
I added a 'score' global variable to track the score, and a way for the user to see that score with the text method.
I added a method called "intersect" which isn't very well coded as it's something I did back when I was a student (please don't hurt me, it works just right so I still use it from time to time). For more details on how simple collisions works, take some time to read this answer I wrote some time ago, there are nice pictures too!
I added a mouseClicked method. This method will act like an event, which means that it will be triggered by a specific call (a left mouse button click in this case). This method contains the code to check for a collision between the squares which are the images. If there's an overlap, the score will increase and jarjar will run in another direction (this part is a bonus to demonstrate that this is the place where you can get creative about the collision).
I commented the code so you can get what I'm doing more easily:
let jarJar;
let jarJarX=5;
let jarJarY=5;
let xspeed;
let yspeed;
let lightSaber;
let flipLength;
let score = 0;
function preload() {
jarJar = loadImage('jarjar.png');
lightSaber= loadImage ('lightSaber.png');
}
function setup() {
createCanvas(700, 700);
runJarJarRun();
}
function draw() {
background(0);
drawLightSaber(); // this way I can deal with the lightsaber's appearance in a dedicated method
image(jarJar, jarJarX, jarJarY, 140, 200);
jarJarX= jarJarX+xspeed;
if (jarJarX<=-300|| jarJarX>=width+200) {
xspeed=xspeed*-1;
}
jarJarY= jarJarY+yspeed;
if (jarJarY<-200|| jarJarY>=height+200 ) {
yspeed=yspeed*-1;
}
//score counter coordinate with lightsaber hitting image
textSize(30);
fill(200, 200, 0);
text('Score: ' + score, 10, 40);
}
function drawLightSaber() {
if (flipLength) { // if the number is > 0 this will be true
flipLength--; // measure how ling the saber is flipped in frames # ~60 frames per second
push(); // isolating the translate ans scale manpulations to avoid ruining the rest of the sketch
translate(mouseX + 100, 0); // makes the coordinates so once flipped the lightsaber will still appear at the same location
scale(-1.0, 1.0); // flip x-axis backwards
image (lightSaber, 0, mouseY, 100, 100);
pop(); // ends the sequence started with 'push();'
} else {
image (lightSaber, mouseX, mouseY, 100, 100);
}
}
function runJarJarRun() {
xspeed=random (5, 10);
yspeed=random (5, 10);
}
function mouseClicked() { // this method will trigger once when the left mouse button is clicked
flipLength = 10;
if (intersect(jarJarX, jarJarY, 140, 200, mouseX, mouseY, 100, 100)) {
score++;
runJarJarRun(); // as a bonus, jarjar will run in another direction on hit
// you could totally put some more special effects, like a flash, a sound, some 'mesa ouchie bad!' text, whatever speaks to you
}
}
function intersect(x1, y1, w1, h1, x2, y2, w2, h2) {
let checkX = false;
let checkY = false;
if ( (x1<x2 && (x1+w1)>x2) || (x1<(x2+w2) && (x1+w1)>x2+w2) || (x1>x2 && (x1+w1)<(x2+w2)) ) {
checkX = true;
}
if ( (y1<y2 && (y1+h1)>y2) || (y1<(y2+h2) && (y1+h1)>y2+h2) || (y1>y2 && (y1+h1)<(y2+h2)) ) {
checkY = true;
}
return (checkX && checkY);
}
If there's something you don't understand, let me know in a comment and I'll be happy to elaborate. Good luck and have fun!
Hi and welcome to stack overflow. One thing to keep in mind when submitting here (or any forum where you're looking for help with code) is to post a minimal reproducible example. You'll be much more likely to get useful responses.
You'll also want to separate out your questions, as they each have multi-step responses.
Your first question is about how to get your sketch to display something when you press the mouse down. Your syntax isn't quite correct there. Here's a minimal example of how to check for a mouse held down.
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
if (mouseIsPressed == true) {
ellipse(100, 100, 100, 100);
}
}
Just a quick note that I tried to make this as 'novice-friendly' as possible. The == true is optional and not usually included.

Categories

Resources