How to spawn a random amount (with limits) of these "stars"(ellipses)? - javascript

function setup() {
createCanvas(5000, 2100);
randomX = random(100, 1000)
randomY = random(100, 1000)
randomSpeed = random(1, 10)
randomSize = random(10, 100)
}
function draw() {
background(0);
fill(255)
ellipse(randomX, randomY, randomSize)
randomX = randomX + randomSpeed
if (randomX > 5000) {
randomX = 0
}
}
In the draw() function, there is an ellipse i need to be drawn on the canvas a random amount of times, WITH A LIMIT, on the canvas to make the starry night effect, how do I do that?

If I understand you right, you want to draw a bunch of ellipses on the canvas in random positions. I've answered assuming that's what you're asking. Apologies if that's not what you want.
What this program does is create two lists that hold data about the ellipses. In setup() we choose a random number of ellipses to draw. We make that many random sizes and positions then put them into the lists. When it comes time to draw the ellipses, we loop through the lists containing information about them and use that to draw a number of ellipses.
const ellipseMinSize = 1;
const ellipseMaxSize = 10;
const ellipseMinAmount = 10;
const ellipseMaxAmount = 100;
// Create some lists so we can remember where the ellipses are and how big they are
var ellipseSizes = [];
var ellipsePositions = [];
function setup() {
createCanvas(500, 500);
// Choose an amount of ellipses to make
var ellipseAmount = random(ellipseMinAmount, ellipseMaxAmount);
for (var i = 0; i < ellipseAmount; i ++) {
// Choose a random size and position, then remember those
var ellipseSize = random(ellipseMinSize, ellipseMaxSize);
var ellipsePosition = createVector(random(0, width), random(0, height));
ellipseSizes.push(ellipseSize);
ellipsePositions.push(ellipsePosition);
}
}
function draw() {
background(0);
fill(255);
// Then loop through the remembered positions and sizes, and draw an ellipse with those parameters
for (var i = 0; i < ellipseSizes.length; i ++) {
var ellipseSize = ellipseSizes[i];
var ellipsePosition = ellipsePositions[i];
ellipse(ellipsePosition.x, ellipsePosition.y, ellipseSize, ellipseSize);
}
}

Related

If noseX is on cnvSection[i], draw img[i] on the canvas

I'm making a sketch with the p5.js library and ml5's poseNet. I have the variable noseX — which indicates the x-coordinate position of the nose on the canvas — and a preloaded array of 60 images. I would like to vertically divide the canvas into 60 sections. For each cnvSection noseX is on, I want the image img[i] corresponding to that cnvSection[i] to to be drawn on the canvas.
So basically if noseX is on cnvSection[5], draw img[5] on the canvas etc.
Here's my function, at the moment I have only been able to draw the vertical lines indicating the canvas sections.
let cnvWidth = 1440;
let cnvHeight = 900;
function nosePosition() {
let sectionWidth = cnvWidth / 60;
let cnvSection = [];
for (let i = 0; i < cnvWidth; i = i + sectionWidth) {
line(i, 0, i, cnvHeight);
}
}
Many thanks!
Try the following:
noseX = 50;
function setup() {
createCanvas(700, 400);
}
function draw() {
background(220);
nosePosition();
fill('red');
ellipse(noseX, height / 2, 6);
}
function nosePosition() {
let sectionWidth = width / 60;
for (let i = 0; i < width; i += sectionWidth) {
line(i, 0, i, height);
}
const noseSection = floor(noseX / sectionWidth);
rect(noseSection * sectionWidth, 0, sectionWidth, height);
}
To simplify I use a hardcoded x value for the nose. In your case that would come from ml5 posenet. You don't need the sections in an array. You can simlpy calculate in which section the nose currently is and then draw the image accordingly. I am drawing a rect - again, to simplify the example.
Maybe copy and paste this into the p5 web editor and play around with the noseX value and see if that works for you.

Creating a sketch to place random images at mouse positions in p5.js

So I am currently working on a sketch for p5.js that places two random images at a location the user clicks on in the canvas. The idea is to create a "paper doll" of a character with a randomized head and a randomized body at any location where the user chooses to click. The random images in question are the image for the head and the image for the body. I decided to name the images with numbers so that I could use string interpolation to randomize the images with the numbers in the name of the images.
I have already managed to successfully display the paper doll without randomization of the images, but I now can't seem to successfully randomize the two different images upon mouse click. How can I randomize the images displayed using this type of string interpolation technique?
let body = [];
let head = [];
let characters = [];
function preload() {
for (let i = 0; i <= 2; i++) {
body[i] = loadImage('Body_' + i + '.png')
console.log(print(body[i]));
}
for (let i = 0; i <= 2; i++) {
head[i] = loadImage('Head_' + i + '.png')
console.log(print(head[i]));
}
}
function setup() {
createCanvas(1000, 1000);
}
function mousePressed() {
let R = random(0, 1);
let c = new pcCharacter(R, mouseX - 150, mouseY - 300)
characters.push(c);
}
function draw() {
background(0);
for (let i = 0; i < characters.length; i++) {
characters[i].characterDraw();
}
}
// a class for the paperdoll
class pcCharacter {
constructor(r, x, y) {
this.r = r;
this.x = x;
this.y = y;
}
characterDraw() {
image(body[this.r], this.x, this.y + 130)
image(head[this.r], this.x + 60, this.y)
}
}
try to make two new variables (say a and b)
assign them random values between 0 and 3
floor the variables
load only the body[a] and face[b]
make the doll using only these images.

How would I add sliders to increase the sides of my Polygons, and draw more of them without refreshing the page?

Currently I'm drawing vertices to create polygons, I would like to add sliders to allow a user to increase or decrease the amount of sides the polygons have and the amount drawn. Also having the canvas update with refreshing.
I've tried adding a slider to control the noOfSides but I've had no luck.
Thanks for your time and help.
let noOfShapes = 3;
let noOfSides;
let rx, ry, drx, dry, rd1, rd2, drd1, drd2;
let threshold = 1000;
let fillColour;
let strokeThick;
let sidesSlider;
function setup() {
createCanvas(1240, 1754);
noLoop();
// background(0, 230)
colorMode(RGB)
rectMode(CENTER);
strokeWeight(3);
//noOfSides = 3;
fillColour = random(0, 255);
sidesSlider = createSlider(4, 12, 3);
sidesSlider.position(width + 20, 0);
sidesSlider.style('width', '150px');
}
function draw() {
background(0, 230)
noOfSides = sidesSlider.value();
for (let x = 0; x < noOfShapes; x++) {
do {
rx = [];
ry = [];
rd1 = [];
rd2 = [];
for (let y = 0; y < noOfSides; y++) {
rx.push(random(10, width - 20));
ry.push(random(10, height - 20));
rd1.push(rx[y] * 1 + ry[y] * 1);
rd2.push(rx[y] * 1 - ry[y] * 1);
}
drx = max(rx) - min(rx);
dry = max(ry) - min(ry);
drd1 = max(rd1) - min(rd1);
drd2 = max(rd2) - min(rd2);
}
while (drx < threshold || dry < threshold || drd1 < threshold || drd2 < threshold)
beginShape();
stroke(255);
fill(random(1, 255), random(1, 255), random(1, 255), 150);
for (let y = 0; y < rx.length; y++) {
vertex(rx[y], ry[y]);
}
endShape(CLOSE);
}
for (let x = 20; x <= width; x = x + 20) {
blendMode(DODGE);
stroke(255);
beginShape();
vertex(x, 0)
vertex(x, height + 20)
endShape();
}
}
First things first, you need to re-draw your shapes whenever slider changes since you are using noLoop().
To do that you can easily define an on change event like this:
sidesSlider.input(sliderChange);
And i suggest you to assign noOfSides variable's value in that function. After that call the draw funtion again.
function sliderChange() {
noOfSides = sidesSlider.value();
draw();
}
Since you would remove assigning the value to noOfSides in draw function you need to set a default value to that variable either on initialization or in `setup function.
...
noOfSides = 3;
...
Then you are almost good to go, only thing that i don't quite understand was you last part of the code. I removed that part and it works as expected at the moment.
Please be aware that you are setting background color with alpha value. That leads: on each rendering of shapes, latest shapes silhouette are still barely visible.
Here is the latest version of your code:
https://editor.p5js.org/darcane/sketches/5wpp6UgXI

Canvas animation with JavaScript. Random coordinates and speed at every initiation

Edited : Thanks to all for valuable time and effort. Finally I made this )) JSfiddle
I was just playing with canvas and made this. Fiddle link here.
... some code here ...
var cords = [];
for(var i = 50; i <= width; i += 100) {
for(var j = 50; j <= height; j += 100) {
cords.push({ cor: i+','+j});
}
}
console.log(cords);
var offset = 15,
speed = 0.01,
angle = 0.01;
cords.forEach(function(e1) {
e1.base = parseInt(Math.random()*25);
e1.rgb = 'rgb('+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+')';
});
setInterval(function() {
cords.forEach(function(e1) {
e1.base = parseInt(Math.random()*25);
e1.rgb = 'rgb('+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+','+parseInt(Math.random()*255)+')';
});
},5000);
function render() {
ctx.clearRect(0,0,width,height);
cords.forEach(function(e1) {
//console.log(e1);
ctx.fillStyle = e1.rgb;
ctx.beginPath();
var r = e1.base + Math.abs(Math.sin(angle)) * offset;
var v = e1.cor.split(',');
ctx.arc(v[0],v[1],r,0,Math.PI * 2, false);
ctx.fill();
});
angle += speed;
requestAnimationFrame(render);
}
render();
Was wondering if -
Coordinates can be made random, now they are fixed as you can see. After 5000 mil, balls will show up in various random cords but even at their fullest they won't touch each other.
Every ball has same speed for changing size, I want that to be different too. Meaning, After 5000 mil, they show up with different animation speeds as well.
Also any suggestion on improving code and making it better/quicker/lighter is much appreciated. Thank you !
TL;DR - See it running here.
Making the coordinates random:
This requires you to add some random displacement to the x and y coordinates. So I added a random value to the coordinates. But then a displacement of less than 1 is not noticeable. So you'd need to magnify that random number by a multiplier. That's where the randomizationFactor comes in. I have set it to 100 since that is the value by which you shift the coordinates in each iteration. So that gives a truly random look to the animation.
Making Speed Random:
This one took me a while to figure out, but the ideal way is to push a value of speed into the array of coordinates. This let's you ensure that for the duration of animation, the speed will remain constant and that gives you a smoother feel. But again multiplying the radius r with a value between 0 and 1 reduces the speed significantly for some of the circles. So I have added a multiplier to 3 to compensate slightly for that.
Ideally I'd put a 2, as the average value of Math.random() is 0.5, so a multiplier of 2 would be adequate to compensate for that. But a little experimentation showed that the multiplier of 3 was much better. You can choose the value as per your preference.
Your logic of generating the coordinates changes as follows:
for(var i = 50; i <= width;i += 100) {
for(var j = 51; j <= height;j += 100) {
var x = i + (Math.random() - 0.5)*randomizationFactor;
var y = j + (Math.random() - 0.5)*randomizationFactor;
cords.push({ cor: x+','+y, speed: Math.random()});
}
}
Your logic of enlarging the circles changes as follows:
function render() {
ctx.clearRect(0,0,width,height);
cords.forEach(function(e1) {
//console.log(e1);
ctx.fillStyle = e1.rgb;
ctx.beginPath();
var r = e1.base + Math.abs(Math.sin(angle)) * offset * e1.speed * 3;
var v = e1.cor.split(',');
ctx.arc(v[0],v[1],r,0,Math.PI * 2, false);
ctx.fill();
});
angle += speed ;
requestAnimationFrame(render);
}
Suggestion: Update the coordinates with color
I'd probably also update the location of circles every 5 seconds along with the colors. It's pretty simple to do as well. Here I've just created a function resetCoordinates that runs every 5 seconds along with the setBaseRgb function.
var cords = [];
function resetCoordinates() {
cords = [];
for(var i = 50; i <= width;i += 100) {
for(var j = 51; j <= height;j += 100) {
var x = i + (Math.random() - 0.5)*randomizationFactor;
var y = j + (Math.random() - 0.5)*randomizationFactor;
cords.push({ cor: x+','+y, speed: Math.random()});
}
}
}
UPDATE I did some fixes in your code that can make your animation more dynamic. Totally rewritten sample.
(sorry for variable name changing, imo now better)
Built in Math.random not really random, and becomes obvious when you meet animations. Try to use this random-js lib.
var randEngine = Random.engines.mt19937().autoSeed();
var rand = function(from, to){
return Random.integer(from, to)(randEngine)
}
Internal base properties to each circle would be better(more dynamic).
var circles = [];
// better to save coords as object neither as string
for(var i = 50; i <= width; i += 100)
for(var j = 50; j <= height; j += 100)
circles.push({
coords: {x:i,y:j}
});
We can adjust animation with new bouncing property.
var offset = 15,
speed = 0.005,
angle = 0.01,
bouncing = 25;
This is how setBaseRgb function may look like
function setBaseRgb(el){
el.base = rand(-bouncing, bouncing);
el.speed = rand(5, 10) * speed;
el.angle = 0;
el.rgb = 'rgb('+rand(0, 255)+','+rand(0, 255)+','+rand(0, 255)+')';
}
All your animations had fixed setInterval timeout. Better with random timeout.
cords.forEach(function(el){
// random timeout for each circle
setInterval(setBaseRgb.bind(null,el), rand(3000, 5000));
})
You forgot to add your base to your circle position
function render() {
ctx.clearRect(0,0,width,height);
circles.forEach(function(el) {
ctx.fillStyle = el.rgb;
ctx.beginPath();
var r = bouncing + el.base + Math.abs(Math.sin(el.angle)) * offset;
var coords = el.coords;
ctx.arc(
coords.x + el.base,
coords.y + el.base,
r, 0, Math.PI * 2, false
);
ctx.fill();
el.angle += el.speed;
});
requestAnimationFrame(render);
}
render();
Effect 1 JSFiddle
Adding this
if(el.angle > 1)
el.angle=0;
Results bubling effect
Effect 2 JSFiddle
Playing with formulas results this
Effect 3 JSFiddle

I need the ellipse to remain centered and move back and forth along the length of the line

The code is a snippet from the program that I am writing for a project, using the processing.js library. I need the ellipse to travel along the entire length of the diagonal line while remaining centered on the line. When complete, there will be a total of eight lines with the ellipse sliding back and forth. This is the fifth line. You will notice that I had to create a special speed variable in order to get the sphere to move down the diagonal (two other diagonal lines in the code work without this).
It works on all other lines in the graphic. This one travels down perfectly, then goes "off-track" on the way up; when it reaches the top, it just bounces in an odd (random-looking) way. Can I fix it without changing the basic format? Thank you!
var x5 = 113;
var y5 = 27;
var speed5 = 1;
var speed5y = speed5 * 2;
draw = function() {
//lineBallFive
line(100, 1, 300, 400);
fill(0, 225, 255);
ellipse(x5, y5, ballSize, ballSize);
if (x5 > 300) {
speed5 = -3;
}
if (x5 < 100) {
speed5 = 3;
}
if (y5 > 400) {
speed5y = 2 * -3;
}
if (y5 < 1) {
speed5y = 3;
}
}
Instead of moving the ellipse relative to itself, you can use the lerp() function to move the ellipse using linear interpolation. This will make it much easier to sync up your lines.
Here's a little example:
var amount = 0;
var speed = .001;
function setup() {
size(500, 500);
}
void draw() {
var startX = 0;
var startY = 0;
var endX = width;
var endY = height;
var currentX = lerp(startX, endX, amount);
var currentY = lerp(startY, endY, amount);
background(0);
ellipse(currentX, currentY, 20, 20);
amount += speed;
}

Categories