I am trying to create an effect where you can hover over the webpage with your mouse and it will have a drawing and when you get to an area, you unveil an image. I thought about doing it this way:
Have an image in the back
Have a rectangle over it (to hide it)
Have an element (your mouse) be able to go over the rectangle and delete the portion that your mouse is hovered over on.
How can I do this with p5.js?
I have it on my screen at the moment:
let img;
// function preload() {
// }
function setup() {
var canvas = createCanvas(
document.getElementById("myCanvas").offsetWidth,
document.getElementById("myCanvas").offsetHeight
);
canvas.parent("myCanvas");
// background(32);
loadImage("../img/monalisa.png", img => {
image(img, 0, 0);
});
}
function draw() {
// monaLisa();
rect(0, 0, 300, 300);
circles();
}
// function monaLisa() {
// image(img, 0, 0);
// }
function circles() {
// fill(255);
ellipse(mouseX, mouseY, 25, 25);
}
Simply push that rectangle to the right by such amount of pixels mouse is positioned from left side.
let img;
let edgeX = 0;
function setup() {
createCanvas(300,400)
img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/300px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg")
}
function draw() {
// variable updates
if (mouseX > edgeX &&
mouseX >= 0 && mouseX <= 300 && // mouse within limits of picture
mouseY >= 0 && mouseY <= 400
) {
edgeX = mouseX;
}
// actual rawing
image(img, 0, 0);
fill('rgba(50,255,150, 0.5)');
rect(edgeX, 0, 300, 400);
}
p5 demo
EDIT
If you want to uncover just a small segment of picture under the mouse position, then algo may be this:
Create 2D rectangle array
Loop through rectangles and draw them on top of image
If mouse intersects with some rectangle - mark it as undrawable
Code:
let canvW = 300
let canvH = 400
let img
let dx = 20
let dy = 40
let diff = 3
let blocks
function setup() {
cursor(CROSS);
mouseX = -10;
mouseY = -10;
createCanvas(canvW,canvH)
img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/300px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg")
blocks = new Array(canvH/dy);
for (var i=0; i < blocks.length; i++) {
blocks[i] = new Array(canvW/dx);
}
}
function draw() {
// variable updates
for (var y=0; y < blocks.length; y++) {
for (var x=0; x < blocks[y].length; x++) {
if (mouseX >= dx*x &&
mouseX <= dx*x+dx &&
mouseY >= dy*y &&
mouseY <= dy*y+dy
) {
blocks[y][x] = false;
}
}
}
// actual drawing
image(img, 0, 0)
stroke(70,127,240, 100)
strokeWeight(3)
for (var y=0; y < blocks.length; y++) {
for (var x=0; x < blocks[y].length; x++) {
if (blocks[y][x] !== false) {
// outer rectangle
fill(`rgba(50,127,240, 0.5)`)
rect(dx*x, dy*y, dx, dy)
// inner rectangle
fill(`rgba(70,127,240, 0.8)`)
rect(dx*x+diff, dy*y+diff, dx-2*diff, dy-2*diff)
}
}
}
}
p5 uncover segment demo
Visuals: partly uncovered Mona Lisa if somebody is lazy to check demo:
Related
Using p5.js / p5.play I'm trying to click a moving sprite, but stuck on how to get the moving sprites coords and position. At the moment when I click anywhere on the canvas a random sprite disappears. I've been trying to use mouseX and mouseY. Very new to coding and just trying to learn fundamentals.
let enemy;
let spawnTimer = 0;
function setup() {
createCanvas(900, 900);
spritegroup = new Group();
clickedgroup = new Group();
}
function draw() {
background(255, 255, 255);
spritegroup.cull(20);
clickedgroup.cull(20);
spawnSprites();
spriteClicked();
drawSprites();
}
function spawnSprites() {
if (spawnTimer === 60) {
for (var i = 0; i < 2; i++) {
var angle = random(360);
var x = random(50, 850);
var y = -5 * sin(radians(angle));
createEnemy(3, x, y);
spawnTimer = 0;
}
}
spawnTimer++;
}
function createEnemy(type, x, y) {
enemy = createSprite(x, y);
enemy[floor(random(0, 4))];
enemy.setSpeed(3.5 - type / 2, 90);
spritegroup.add(enemy);
enemy.setCollider("rectangle", 0, 0, 100, 100);
enemy.debug = true;
return enemy;
}
function spriteClicked() {
if (mouseIsPressed == true)
if (
(mouseX > enemy.position.x,
enemy.position.y && mouseY > enemy.position.x,
enemy.position.y)
) {
enemy.remove();
}
}
The easiest way is to use sprite.mouse :)
https://p5play.org/learn/input_devices.html?page=3
Catbus game
I'm trying to make my cat only jump once until it lands back on the ground. I've tried to add a statement that makes it only go to a certain point, but the velocity keeps working against it. It begins to act like a basketball that has been bounced to much. I wouldn't want to add a collider (even though I have debated it). It would just make it worse...
The code is as follows:
let img; //background
var bgImg; //also the background
var x1 = 0;
var x2;
var scrollSpeed = 4; //how fast background is
let bing; //for music
let cat;
var mode; //determines whether the game has started
let gravity = 0.2; //jumping forces
let velocity = 0.1;
let upForce = 6;
let startY = 730; //where cat bus jumps from
let startX = 70;
var font1; //custom fonts
var font2;
p5.disableFriendlyErrors = true; //avoids errors
function preload() {
bgImg = loadImage("backgwound.png"); //importing background
bing = loadSound("catbus theme song.mp3"); //importing music
font1 = loadFont("Big Font.TTF");
font2 = loadFont("Smaller Font.ttf");
}
function setup() {
createCanvas(1000, 1000); //canvas size
img = loadImage("backgwound.png"); //background in
x2 = width;
bing.loop(); //loops the music
cat = {
//coordinates for catbus
x: startX,
y: startY,
};
catGif = createImg("catgif.gif"); //creates catbus
catGif.position(cat.x, cat.y); //creates position
catGif.size(270, 100); //creates how big
mode = 0; //game start
textSize(50); //text size
}
function draw() {
let time = frameCount; //start background loop
image(img, 0 - time, 0);
image(bgImg, x1, 2, width, height);
image(bgImg, x2, 2, width, height);
x1 -= scrollSpeed;
x2 -= scrollSpeed;
if (x1 <= -width) {
x1 = width;
}
if (x2 <= -width) {
x2 = width;
} //end background loop
fill("white"); //text colour
if (mode == 0) {
textSize(20);
textFont(font1);
text("press SPACE to start the game!", 240, 500); //what text to type
}
if (mode == 0) {
textSize(35);
textFont(font2);
text("CATBUS BIZZARE ADVENTURE", 90, 450); //what text to type
}
cat.y = cat.y + velocity; //code for jumping
velocity = velocity + gravity;
if (cat.y > startY) {
velocity = 0;
// cat.y = startY;
}
catGif.position(cat.x, cat.y);
}
function keyPressed() {
if (keyCode === 32) { //spacebar code
// if ((cat.y = 730)) {
// cat.y > 730;
mode = 1;
velocity += -upForce;
}
// }
}
You can simply do this to the keyPressed function
function keyPressed() {
if (keyCode === 32 && velocity == 0) { //spacebar code
// if ((cat.y = 730)) {
// cat.y > 730;
mode = 1;
velocity += -upForce;
}
}
I am trying to implement a group of objects that will fall from the top of the canvas in random spots, and then when they hit the bottom of the canvas they respawn at the top of the canvas. Ideally, I want to change this code in the future to use sprites that will fall from the top of the canvas and explode when they hit the bottom of the canvas but then respawn again at the top.
I have the bellow code that works when the mouse is pressed but I would like to rewrite this code so the event happens automatically without the mouse needed to be pressed to make the objects fall.
see code below.
var x, y;
var particle = [];
function setup() {
createCanvas(720, 400);
// Starts in the middle
x = width / 2;
y = height;
}
function draw() {
background(0);
if (mouseIsPressed){
stroke(50);
fill(100);
ellipse(x, y, 24, 24);
}
x = x + 0;
// Moving up at a constant speed
y = y + 2;
// Reset to the bottom
if (y >= height) {
y = 0;
}
}
Use the mousePressed() to add new particles to the list. The particles are added at the current mouse position (mouseX, mouseY). Move and draw the particles in a loop:
var particles = [];
function setup() {
createCanvas(720, 400);
}
function mousePressed() {
particles.push([mouseX, mouseY]);
}
function draw() {
background(0);
stroke(50);
for (let i=0; i < particles.length; i++) {
particles[i][1] += 2;
if (particles[i][1] > height) {
particles[i][1] = 0;
}
fill(100);
ellipse(particles[i][0], particles[i][1], 24, 24);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Alternatively, you can spawn the particles with a time interval. Get the number of milliseconds (thousandths of a second) since starting the sketch with millis(). The y-coordinate of a new particle is 0 and the x-coordinate is random():
var particles = [];
function setup() {
createCanvas(720, 400);
}
function mousePressed() {
particles.push([mouseX, mouseY]);
}
function draw() {
let max_no_of_particles = 40;
let expected_no_of_praticles = min(max_no_of_particles, millis() / 100);
if (particles.length < expected_no_of_praticles) {
particles.push([random(12, width-12), 0]);
}
background(0);
stroke(50);
for (let i=0; i < particles.length; i++) {
particles[i][1] += 2;
if (particles[i][1] > height) {
particles[i][1] = 0;
}
fill(100);
ellipse(particles[i][0], particles[i][1], 24, 24);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
I have been working on an internship. The application I need to make needs to have different colors in the intersecting areas. I made a global variable of color. I am changing its values in the buttons I have created. But whenever I press the button it changes color of each intersecting area even though I have pushed it in array with its own color. How can I solve this issue
let squares = [];
let overlappingsquares = []; //variable to hold squares drawn in intersecting area
let dragObject = null; // variable to hold the object being dragged
var myColour = (255);
function setup() {
createCanvas(600, 520);
button1 = createButton("Alpha");
button2 = createButton("Bravo");
button3 = createButton("Charlie");
button4 = createButton("Delta");
button5 = createButton("Echo");
button6 = createButton("Foxtrot");
button7 = createButton("Golf");
button8 = createButton("Hotel");
button9 = createButton("India");
button10 = createButton("Juliet");
button1.mousePressed(fun1);
button2.mousePressed(fun2);
button3.mousePressed(fun3);
button4.mousePressed(fun4);
button5.mousePressed(fun5);
button6.mousePressed(fun6);
button7.mousePressed(fun7);
button8.mousePressed(fun8);
button9.mousePressed(fun9);
button10.mousePressed(fun10);
//frameRate(1);
}
function draw() {
background(135,206,250);
//myColour = (255);
// if a square is being dragged, update its position
if (this.dragObject != null) {
this.dragObject.position.x = mouseX;
this.dragObject.position.y = mouseY;
}
//draw all squares
for (let i = 0; i < squares.length; i++) {
let s = squares[i];
s.show();
}
for (let i = 0; i < squares.length; i++) {
for (let j = i + 1; j < squares.length; j++) {
//block checking collision
if (i != j && squares[i].collides(squares[j])) {
squares[i].changecolor();
//set intersection color
//fill(myColour);
//calculate parameters
newX = Math.max(squares[i].position.x, squares[j].position.x);
newY = Math.max(squares[i].position.y, squares[j].position.y);
newW = Math.min(squares[i].position.x + squares[i].w, squares[j].position.x + squares[j].w) - newX;
newH = Math.min(squares[i].position.y + squares[i].h, squares[j].position.y + squares[j].h) - newY;
//draw rectangle
let col = myColour
let Osquare = new OverlappingSquares(newX, newY, newW, newH, col);
overlappingsquares.push(Osquare);
}
}
}
}
function mousePressed() {
if (this.dragObject == null) {
//ask every square if they are being "hit"
for (let i = 0; i < squares.length; i++) {
let s = squares[i];
if (s.hitTest()) {
//if so, set the drag object as this square and return
this.dragObject = s;
return;
}
}
//no squares are hit, create a new square.
let square = new Square(mouseX, mouseY);
squares.push(square);
}
}
//mouse is released, release the current dragged object if there is one
function mouseReleased() {
this.dragObject = null;
}
class Square {
constructor(InitialX, InitialY) {
this.w = 60;
this.h = 60;
this.position = {
x: InitialX,
y: InitialY
};
}
//basic test of mouse position against square position and if its inside the rectangle
hitTest() {
let x = mouseX - this.position.x;
let y = mouseY - this.position.y;
return (x > 0 && x < this.w) && (y > 0 && y < this.h);
}
show() {
fill(50);
rect(this.position.x, this.position.y, this.w, this.h);
}
collides(sqr) {
if (this.position.x < sqr.position.x + sqr.w &&
this.position.x + this.w > sqr.position.x &&
this.position.y < sqr.position.y + sqr.h &&
this.position.y + this.h > sqr.position.y) {
return true;
}
return false;
}
changecolor() {
for (let i = 0; i < squares.length; i++) {
let s = squares[i];
s.show();
}
for (let i = 0; i < overlappingsquares.length; i++) {
let s = overlappingsquares[i];
s.show();
}
}
}
//Overlapping sqaures class
class OverlappingSquares {
constructor(X, Y, W, H, C) {
this.w = W;
this.h = H;
this.col = C
this.position = {
x: X,
y: Y
};
}
show() {
fill(this.col)
rect(this.position.x, this.position.y, this.w, this.h);
}
}
function fun1() {
myColour = color(0,255, 0); //green
}
function fun2() {
myColour = color(255, 0, 0); //red
}
function fun3() {
myColour = color(0, 0, 200); //blue
}
function fun4() {
myColour = color(250, 0, 150); //pink
}
function fun5() {
myColour = color(128, 0, 128); //purple
}
function fun6() {
myColour = color(255, 255, 0); //yellow
}
function fun7() {
myColour = color(128, 0, 0); //marroon
}
function fun8() {
myColour = color(255, 128, 0); //orange
}
function fun9() {
myColour = color(192, 105, 50); //brown
}
function fun10() {
myColour = color(255,228,196); //bisque
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.dom.js"></script>
I went through your code and spotted this snippet
//draw rectangle
let col = myColour
let Osquare = new OverlappingSquares(newX, newY, newW, newH, col);
overlappingsquares.push(Osquare);
It's within the loop that you are calling on every single cycle. When ever you select a button, it sets the new value for 'myColour', and within the next loop it will color all overlapping elements. You don't really tell in detail what's your goal. But some how you will need to add another color variable and identify which button intersection you want to color which way...
I think it would be better to solve this in a different way. Looping over all elements will make your program lag.
This is in continuation to my previous post here Changing color of intersecting area of squares
I was able to make the intersecting area of the squares change color. The issue was that I wanted multiple intersecting squares and not a single one so I modified the code. Now the problem is that the square is leaving a trail since it is drawing square wherever it moves. And it starts to slow down after a while. How can I overcome this
function draw() {
background(135,206,250);
myColour = (255);
// if a square is being dragged, update its position
if (this.dragObject != null) {
this.dragObject.position.x = mouseX;
this.dragObject.position.y = mouseY;
}
//draw all squares
for (let i = 0; i < squares.length; i++) {
let s = squares[i];
s.show();
}
for (let i = 0; i < squares.length; i++) {
for (let j = i + 1; j < squares.length; j++) {
//block checking collision
if (i != j && squares[i].collides(squares[j])) {
squares[i].changecolor();
//set intersection color
fill(myColour);
//calculate parameters
newX = Math.max(squares[i].position.x, squares[j].position.x);
newY = Math.max(squares[i].position.y, squares[j].position.y);
newW = Math.min(squares[i].position.x + squares[i].w, squares[j].position.x + squares[j].w) - newX;
newH = Math.min(squares[i].position.y + squares[i].h, squares[j].position.y + squares[j].h) - newY;
//draw rectangle
let Osquare = new OverlappingSquares(newX, newY, newW, newH);
overlappingsquares.push(Osquare);
}
}
}
}
changecolor() {
// fill(random(255), random(255), random(255));
// background(200, 255, 100);
for (let i = 0; i < squares.length; i++) {
let s = squares[i];
s.show();
}
for (let i = 0; i < overlappingsquares.length; i++) {
let s = overlappingsquares[i];
s.show();
}
}
//Overlapping sqaures class
class OverlappingSquares {
constructor(X, Y, W, H) {
this.w = W;
this.h = H;
this.position = {
x: X,
y: Y
};
}
show() {
fill(myColour)
rect(this.position.x, this.position.y, this.w, this.h);
}
}