How to rotate an arc using trigonomentry p5js? - p5.js

I want to create a spinning arc using trig, nothing fancy, just for it to rotate around the center point as if it was a full rotating circle cut in half. What I'm doing now results in a funky pacman, whereas I want it to remain a semicircle.
let angle = 0;
function setup() {
createCanvas(500, 500);
angleMode(DEGREES);
}
function draw() {
background(200);
let posX = 250;
let posY = 250;
let sizeW = 250;
let sizeH = 250;
let radius = 125 //I don't know what to put as my radius
let x = radius * cos(angle);
let y = radius * sin(angle);
fill(0);
arc(posX, posY , sizeW, sizeH, 270 + x, 90 + y);
angle++;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

You don't need any trigonometry because the arc() function takes care of that for you. You just need to make the start and end angles for the arc change based on the current value of angle. To get a semi-circle shape you want to start the arc ~90 degrees clockwise from angle and end your arc ~90 degrees counter clockwise from angle.
const posX = 250;
const posY = 250;
const sizeW = 250;
const sizeH = 250;
const radius = 125;
let angle = 0;
function setup() {
createCanvas(500, 500);
angleMode(DEGREES);
}
function draw() {
background(200);
fill(0);
arc(posX, posY , sizeW, sizeH, angle + 90, angle - 90);
angle++;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

Related

Trying to use spirals to show an image in p5.js

I have an image which I am trying to show using a spiral with varying thickness depending upon the image pixel. But the thickness of my line/ellipses in spiral is not coming out correctly.
The image I am using:
The image I am getting
As you can see for whatever reason the bottom right quadrant is getting thick and nothing else, this is happening even if I use other images.
My code:
FG = '#222323';
BG = '#f0f6f0';
function preload() {
Img = loadImage('black.png');
}
function setup() {
createCanvas(500, 500);
Img.resize(500, 500);
background(BG);
fill(FG);
colorMode(HSB, 255);
noLoop();
noStroke();
}
function draw() {
var r = width;
var a = 0;
while (r > 1) {
strokeWeight(1);
var x1 = r * cos(a);
var y1 = r * sin(a);
a += 0.01;
r -= 0.03;
var x2 = r * cos(a);
var y2 = r * sin(a);
let c = Img.get(x1, y1);
let b = brightness(c);
const val = map(b, 0, 255, 1, 10);
push();
translate(width/2, height/2);
ellipse(x1, y1, val, val);
pop();
}
}
The coordinates where you're sampling from aren't the same where you're rendering.
Because you use translate(), the ellipses themselves are offset based on the centre (but there's nothing changing where you're sampling from in the image (x1,y1).
You can offset x1,y1 to take the centre of the stage into account and then you sample from the right location (and draw offset to the centre):
FG = '#222323';
BG = '#f0f6f0';
function preload() {
// Img = loadImage('black.png');
Img = loadImage('data:image/png;base64,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');
}
function setup() {
createCanvas(500, 500);
Img.resize(500, 500);
background(BG);
fill(FG);
colorMode(HSB, 255);
noLoop();
noStroke();
}
function draw() {
var r = width;
var a = 0;
const centerX = width * 0.5;
const centerY = height * 0.5;
while (r > 1) {
var x1 = centerX + (r * cos(a));
var y1 = centerX + (r * sin(a));
a += 0.01;
r -= 0.03;
let c = Img.get(x1, y1);
let b = brightness(c);
const val = map(b, 0, 255, 1, 10);
ellipse(x1, y1, val, val);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>
(Notice the central area where the source image has a black circle is what based on your mapping. You can reverse that as well if that's more interesting (const val = map(b, 0, 255, 10, 1);))

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>

What is the best way to add and remove text and shapes?

I am drawing a circle and want to show some text when the mouse is inside the circle and have the text not shown when the mouse is outside.
The code below works to show the text when the mouse goes in but it seems getting rid of the text is much more difficult! I have looked at different p5 functions such as remove() but they do not do what I expect/want.
What is the right way to hide the text in this situation?
I imagine the same method would be used to also hide a shape too? For example if I were to have drawn a rectangle instead of showing some text, or is that handled differently?
var centerX = 400;
var centerY = 400;
var radius = 40;
function setup() {
var canvas = createCanvas(800, 800);
canvas.parent("Example");
background(200);
fill(204, 101, 192, 127);
ellipse(centerX, centerY, radius, radius);
}
function draw() {
mouseOver(radius, centerX, centerY);
}
function mouseOver(radius, centerX, centerY) {
var d = Math.sqrt(((mouseX - centerX) * (mouseX - centerX)) + ((mouseY - centerY) * (mouseY - centerY)));
if (d < radius) {
textSize(12);
text("Hello", 400, 400);
} else {
//remove the text
}
}
To remove part of a drawing it is very common to simply call background in draw and then redraw the entire canvas
Your code could be written like this:
var centerX;
var centerY;
var radius = 40;
function setup() {
var canvas = createCanvas(200, 200);
centerX = width/2;
centerY = height/2
}
function draw() {
background(200);
fill(204, 101, 192, 127);
ellipse(centerX, centerY, radius*2, radius*2);
mouseOver(radius, centerX, centerY);
}
function mouseOver(radius, centerX, centerY) {
var d = Math.sqrt(((mouseX - centerX) * (mouseX - centerX)) + ((mouseY - centerY) * (mouseY - centerY)));
if (d < radius) {
fill(0);
textSize(12);
text("Hello", centerX, centerY);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

How to track sphere with camera in p5.js?

I'm trying to replicate the game "slope" using p5.js web editor because I'm on a school Chromebook and no other way of coding. So far I have the camera following the sphere but it seems that once the sphere goes so far the camera retracts and the sphere disappears. The cube is there as a reference to see if the sphere is moving which it is but then it gets buggy after 10 seconds. Any ideas on how to fix this and have the camera continuously following the sphere as it travels down the z-axis. Once the sphere reaches a certain point the whole thing seems to invert.
let cam;
//let delta = 0.01
var ballX = 0;
var ballY = 0;
var ballZ = 0;
var score = 1;
var speed = 3;
//var speedZ = 2;
function setup() {
createCanvas(500, 500, WEBGL);
translate(0, 0, 0)
cam = createCamera()
}
function draw() {
background(200);
normalMaterial();
//camera
camera(ballX, ballY, ballZ - 500, ballX, ballY, 0, 0, 50, 0);
//test
box(20);
if (keyIsDown(RIGHT_ARROW)) {
ballX -= speed;
} else if (keyIsDown(LEFT_ARROW)) {
ballX += speed;
}
push();
translate(ballX, ballY, ballZ);
sphere(50);
pop();
ballZ += speed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
The fourth, fifth and sixth argument that the camera() function receives, mark the point that the camera is pointing to. In your case, the camera is always pointing to z = 0 which is why when the camera's z coordinate reaches zero, the sphere "disappears" (figuratively, the camera rotates 180 degrees).
Modify the camera's position like this:
camera(ballX, ballY, ballZ - 500, ballX, ballY, ballZ, 0, 50, 0);
so it's set to always point towards the sphere.
Here's your code lightly modified and with a small function that allows to check the "review mirror" when pressing backspace by alternating the cameras z-axis target between the sphere's position and 0
var ballX = 0;
var ballY = 0;
var ballZ = 0;
var speed = 3;
function setup() {
createCanvas(500, 500, WEBGL);
translate(0, 0, 0)
}
function draw() {
background(200);
//camera
camera(ballX, ballY, ballZ -500, ballX, ballY, mirror ? 0 : ballZ, 0, 50, 0);
//test
fill('red');
box(20);
normalMaterial();
if (keyIsDown(RIGHT_ARROW)) {
ballX -= speed;
} else if (keyIsDown(LEFT_ARROW)) {
ballX += speed;
}
push();
translate(ballX, ballY, ballZ);
sphere(50);
pop();
ballZ += speed;
}
let mirror = false;
function keyPressed(){
if(keyCode === BACKSPACE)
mirror =!mirror;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>

How to rotate a line in a circle (radar like) in Processing while also plotting points?

I am trying to rotate a line around in a circle that represents the direction a sensor is facing, while also plotting distance measurements. So I can't use background() in the draw function to clear the screen, because it erases the plotting of the distance readings. I've tried pggraphics and a few others ways, but can't seem to find a way to do it.
This is what I have right now:
void setup() {
background(255,255,255);
size(540, 540);
}
void draw() {
translate(width/2, height/2);
ellipse(0,0,100,100);
newX = x*cos(theta)- y*sin(theta);
newY = x*sin(theta)+ y*cos(theta);
theta = theta + PI/100;
//pushMatrix();
fill(255, 255);
line(0, 0, newX, newY);
rotate(theta);
//popMatrix();
}
I am new to Processing, and coding in general, but can anyone point me in the right direction on how to do this? Thanks
This is what it outputs: http://imgur.com/I825mjE
You can use background(). You just need to redraw the readings on each frame. You could store the readings in an ArrayList, which allows you to add new readings, change them and remove them.
An example:
ArrayList<PVector> readings;
int readingsCount = 15;
void setup() {
size(540, 540);
// create collection of random readings
readings = new ArrayList<PVector>();
for(float angle = 0; angle < TWO_PI; angle += TWO_PI/ readingsCount) {
float distance = random(100, 200);
// the new reading has an angle...
PVector newReading = PVector.fromAngle(angle);
// ... and a distance
newReading.mult(distance);
// Add the new reading to the collection
readings.add(newReading);
}
}
void draw() {
background(255);
// Put (0, 0) in the middle of the screen
translate(width/2, height/2);
float radius = 250;
noFill();
ellipse(0, 0, 2*radius, 2*radius);
// draw spinning line
float angle = frameCount * 0.1;
line(0, 0, radius * cos(angle), radius * sin(angle));
// draw readings
for(PVector p : readings) {
ellipse(p.x, p.y, 20, 20);
}
}

Resources