how to have steps of actions in p5.js - p5.js

This is the pseudocode I hope to realize in p5.js:
The shape keeps rotating throughout the process.
The shape moves to point A.
The shape stay at point A rotating for 2 seconds.
The shape moves to point B.
The shape stay at point B rotating for 2 seconds.
The shape moves to point C.
The shape stay at point C rotating for 2 seconds.
This is what I have already attempted which didn't work:
var angle=0.0
var x=[20,40,60,320]
var y=[50,70,90,280]
function setup() {
createCanvas(400, 400);
background(220);
}
function draw() {
for (i=0; i<x.length; i++) {
translate(x[i], y[i]);
setTimeout(rotate(angle), 1000);
ellipse(0,0,10,100);
angle+=0.1
pop()}
}

You shouldn't really use the setTimeout() function for logic like this.
Instead, use the timing mechanisms built into P5.js, such as the frameCount variable, the millis() function, and the lerp() function.
Here's a simple example that moves a circle after 2 seconds:
var y = 0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
ellipse(width/2, y, 20, 20);
if(millis() > 2000){
y++;
}
}

Related

Processing 3.0 Question - struggling to implement some code

wondering if anyone can help with this. I have to write some ode using processing 3.0 for college, basically creating a series of circles that appear randomly and change colours etc. Ive got the circles to appear, and they change location on mouse click.
What Im struggling with is, its asked me to have the circles change colour when the mouse button is pressed, where circles to the right are blue and circles to the left of the mouse pointer are yellow? I have no idea how to implement that at all.
Here's what I have so far, any help would be hugely appreciated:
//declaring the variables
float[] circleXs = new float[10];
float[] circleYs = new float[10];
float[] circleSizes = new float[10];
color[] circleColors = new color[10];
void setup() {
size(600, 600);
createCircles();
}
//creation of showCricles function
void draw() {
background(0);
showCircles();
}
//creation of circles of random size greater than 10 but less than 50 - also of white background colour
void createCircles() {
for (int i = 0; i < circleXs.length; i++) {
circleXs[i] = random(width);
circleYs[i] = random(height);
circleSizes[i] = random(10, 50);
circleColors[i] = color(255,255,255);
}
}
void showCircles() {
for (int i = 0; i < circleXs.length; i++) {
fill(circleColors[i]);
circle(circleXs[i], circleYs[i], circleSizes[i]);
}
}
//creating new circles on mouse click
void mouseClicked() {
createCircles();
}
It's not very complicated, you just miss some of the basics. Here are 2 things you have to know to do what you want to do:
You can use mouseX or mouseY to compare coordinates with the current mouse pointer's position.
This would be way cleaner using class, but I am guessing that you are not quite there as you're using a couple arrays to store coordinates instead. But here's the thing with that method: the array's index always refer to the same object. Here your objects are circles, so every array's index n refers to the same circle. If you find a circle which x coordinate is leftward compared to the mouse pointer, you can change that circle's color by modifying the item at the same index but in the circleColors array.
So I added a couple lines to your mouseClicked() method which demonstrate what I just said. Here they are:
void mouseClicked() {
createCircles();
// here is the part that I added
// for each circle's X coordinate:
for( int i = 0; i < circleXs.length; i++) {
// if the X coordinate of the mouse is lower than the circle's...
if( mouseX > circleXs[i]) {
// then set it's color to yellow
circleColors[i] = color(255, 255, 0);
} else {
// else set it's color to blue
circleColors[i] = color(0, 0, 255);
}
}
}
It should show what you described, or close enough for you to clear the gap.
Hope it helps. Have fun!

How to detect collisions between a moving point and the stroke of an arbitrary boundary shape?

I want to draw a circle(for example) and create a couple of points inside that circle. The points are moving randomly, but when they hit the circle's stroke, they should either stop or go inverse or react in some way (it's not that important). I know it would be easy to do with rect-like shapes, but I want to draw inside custom shapes like stars or flower.
To find out if point inside the circle or not you just need to calculate distance from center of circle to point itself. If that distance less then radius - point inside circle.
Fun example:
let c, r;
let points = [];
function setup()
{
createCanvas(200, 200);
r = 50;
c = createVector(100, 100);
let pos = createVector(95, 110);
let v = p5.Vector.random2D();
points.push({p: pos, v: v});
}
function draw()
{
background(0);
points.forEach(point => {
point.p.add(point.v);
if(point.p.dist(c) > r) {
let n = point.p.copy().sub(c).normalize();
let d_n = point.v.dot(n);
point.v = p5.Vector.sub(n.mult(2).mult(d_n), point.v).mult(-1);
//pv.mult(-1);
}
circle(point.p.x,point.p.y,5);
});
noFill();
stroke(255);
circle(c.x,c.y, r*2);
}
function mouseClicked() {
let p = createVector(mouseX, mouseY);
if (p.dist(c) < r) {
points.push({
p: p,
v: p5.Vector.random2D(),
});
}
// prevent default
return false;
}
<script src="https://github.com/processing/p5.js/releases/download/v1.4.0/p5.min.js"></script>
click inside circle
Boring example:
let c, radius;
function setup()
{
createCanvas(200, 200);
c = createVector(100, 100);
radius = 50;
}
function draw()
{
background(0);
let point = createVector(mouseX, mouseY);
let distance = c.dist(point);
if (distance > radius) {
fill("red");
} else {
fill("green");
};
circle(c.x, c.y, radius * 2);
// just rendering text :)
stroke(255);
line(point.x,point.y, c.x,c.y);
stroke(0);
fill(200)
push()
translate(p5.Vector.add(c, p5.Vector.sub(point, c).div(2)));
text(distance.toFixed(2),0,0)
pop()
text("Move your mouse",20,10);
}
<script src="https://github.com/processing/p5.js/releases/download/v1.4.0/p5.min.js"></script>

How do I create a line that recedes as you draw more in p5.js?

Currently working on a site that features some line drawing while hovering. How can I make the line recede naturally as you draw more? Right now I've figured out how to draw a continual line.
var canvas;
var button;
function windowResized() {
console.log('resized');
resizeCanvas(windowWidth, windowHeight);
}
function setup () {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0,0);
canvas.style('z-index', '-1')
background(175);
// button = createButton("Start Your Walk");
}
function draw () {
strokeWeight(4);
console.log('button')
line(pmouseX, pmouseY, mouseX, mouseY)
}
You may store the values of your mouse position in an array and then draw the points of the array in order. When the array is updated, if it is full, you will have to erase the last point of the array, move all the points one position backwards and add the new point. The following would be an example code. I recomend you to consult this page for documentation and also the p5 reference.
var mousePositions = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
v = createVector(mouseX, mouseY);
mousePositions.push(v);
noFill();
beginShape();
for(var i = 0; i < mousePositions.length; i++){
vertex(mousePositions[i].x, mousePositions[i].y);
}
endShape();
if(mousePositions.length > 25){
mousePositions.shift();
}
}

How do I animate a line from my draw() function?

I'm using Processing to create a learning experience project that allows users to join network components together. I have links using standard lines, but I want to be able to show a signal moving through the line if there is a valid connection. Think of the line as a network cable for example. Is there anyway I can animate this line?
void draw(){
pushStyle();
stroke(0);
line(from.x, from.y, to.x, to.y);
popStyle();
}
} //draw function in the 'link' file
Of course you can, but your question is a little broad. You do have a particular type of animation in mind? Endless possibilities ;)
The basic way to handle something like this in processing is to increase some animation-variables every frame (or use time management - though that is beyond the basics).
Because the animation-variables (for instance position or color) are changed every frame, the animation is different every frame. It's animated.
Below I give an example of a small green line traveling over a black 'connection' line. If you read through the code I think you'll figure it out. This should be incorporated in a nice 'connection' class for ease of use on a larger scale.
//set coordinates for connection-line
int fromX = 100;
int toX = 600;
int fromY = 100;
int toY = 200;
//copy start coordinate for animation
int animx = fromX;
int animy = fromY;
//determine animation stepsize
int stepX = (toX-fromX)/10;
int stepY = (toY-fromY)/10;
void setup() {
size(800, 300);
//set framerate so animation is not to fast
frameRate(5);
//draw thick lines
strokeWeight(10);
}
void draw() {
background(255);
// draw connection in black
stroke(0);
line(fromX, fromY, toX, toY);
//draw animation in green
stroke(0, 255, 0);
line(animx, animy, animx+stepX, animy+stepY);
// step animation for next frame
animx = animx+stepX;
animy = animy+stepY;
// check for reset (if the animation on the next frame is drawn outside the line)
if (animx+stepX > toX)
{
animx = fromX;
}
if (animy+stepY > toY)
{
animy = fromY;
}
}

Moving an objects while others stay static in a click controlled sketch

So I'm trying to build an animation that I can step through with mouse clicks. Adding individual objects click by click is easy. Sequence I want is as follows:
One object(a) drawn initially.
First mouse click adds an object(b).
Second mouse click adds an object(c).
Third mouse click, object(c) should move across the screen and disappear.
I'm having a problem on the last part of the sequence. I can't figure out how to make the object move and still maintain the static part of the sketch. The normal way of doing movement is to change the coordinates of the object with each loop through the draw() function, and use the background to cover up the previous objects. Can't do that in this case because I need object(a) and object(b) to be persistent.
Code below. Thanks for your help!
var count = 0;
function setup() {
createCanvas(200, 200);
a = new Object1(20, 40);
b = new Object1(20, 85);
c = new Object1(20, 130);
}
function draw() {
background(200);
a.display();
if (count == 1) {
b.display();
}
if (count == 2) {
b.display();
c.display();
}
if (count == 3) { //this is where I have a problem
}
if (count > 3) {
count = 0;
}
}
function Object1(ix, iy, itext) {
this.x = ix;
this.y = iy;
this.text = itext;
this.display = function() {
fill(160);
rect(this.x, this.y, 40, 40);
}
}
function mousePressed() {
count++;
}
Generally how you'd do this is by drawing the static part of your scene to an off-screen buffer, which you can create using the createGraphics() function. From the reference:
var pg;
function setup() {
createCanvas(100, 100);
pg = createGraphics(100, 100);
}
function draw() {
background(200);
pg.background(100);
pg.noStroke();
pg.ellipse(pg.width/2, pg.height/2, 50, 50);
image(pg, 50, 50);
image(pg, 0, 0, 50, 50);
}
You'd draw the static part to the buffer, then draw the buffer to the screen, then draw the dynamic stuff on top of it each frame.
This has been discussed before, so I'd recommend doing a search for stuff like "processing pgraphics" and "p5.js buffer" to find a bunch more information.

Resources