xxxxxxxxxx
145
/*
"Perpetual Rainbow" by Fizza Ahmed
This is a slightly edited version to fit my website. To see the original, please go to https://editor.p5js.org/f51/full/yMPvoZSWH
!READ ME:
-If you would like to save your canvas, press the "s" key at any point.
-If you would like to reset your canvas early, press the "r" key.
-Try different colours! Press '1' for neon (preset colours), '2' for pastel, '3' for white, and '4' for black.
-Try talking to your computer while the code is running!
TROUBLESHOOTING:
-If pressing keys isn't working, click on the screen then try again
-If speaking to the code doesn't do anything, make sure you have allowed access to your microphone and that you have a working microphone (the one on your computer should be fine but if not try plugging in headphones with a mic)
-Check that there is no background noise being constantly picked up that will make it so that not speaking does not create the contrast between speaking
*/
//these are surprise tools that will help us later (the variables)
var points = [];
var pointNum;
var h;
var hueSpeed;
var s = 80;
var mic;
var strokePer = 2;
var holdHue;
var a;
var count = 0;
var count2 = 0;
var b = 100;
function setup() {
createCanvas(windowWidth, windowHeight); //create a canvas of the height and width of the display
make(); //setup the array of points
//to be able to get the volume of the mic for later
mic = new p5.AudioIn();
mic.start();
colorMode(HSB); //set the color type to HSB so that I can cycle through hues instead of doing some weird stuff that might not even work with RGB
background(0); //set the background to a random greyscale background
}
function draw() {
vol = (mic.getLevel() * 100); //get the levels from the microphone
stroke(h, s, b, a); //set the stroke to hue "h" with 80% saturation, 100% brightness, and "a" opacity (to be changed based off volume)
if (count < 6000) { //if less than 6000 lines drawn, then draw more lines
for (j = 0; j < strokePer; j++) { //to get it to draw "j" strokes per frame - useful later when loud noises make it draw more per frame
for (i = 0; i < points.length; i++) { //to get it to run through the entire points array
var p = points[i]; //get the first coordinate
var next = points[(i + 1) % points.length]; //get the next coordinate (while ensuring we don't go out of our array by using remainder)
line(p.x, p.y, next.x, next.y); //draw a line between the two coordinates
p.update(); //update the coordinates of our points
volControl();
count++; //to count the number of lines drawn
}
}
h = (h + hueSpeed) % 360; //to change the hue based off the hueSpeed %360 to keep it in the range
// count++; //to count how long the program has been drawing for
} else { //aka when 15s are over
count2++; //start counting for the pause
if (count2 >= 150) { //once time for the pause (about 5s) is over...
count = 0; //reset the count for the drawing to 0
count2 = 0; //reset the count for the pause to 0
points.length = 0; //clear the array (so that we dont just keep getting more points added to the array, but instead we make a "new" array)
resizeCanvas(windowWidth, 700);
setup(); //rerun setup (so that it refreshes the background, makes the new array, etc.)
}
}
}
function make() { //to make our array of points (called in setup)
pointNum = random(2, 7); //to generate a random number of points
for (i = 0; i < pointNum; i++) { //to create random points (pointNum as the number of points) and push them onto our array
var x = random(width);
var y = random(height);
var xSpeed = random(-2, 2);
var ySpeed = random(-2, 2);
points.push(new Point(x, y, xSpeed, ySpeed));
}
hueSpeed = random(0.25, 1); //set the hueSpeed
h = random(360); //set the original hue to a random colour
holdHue = hueSpeed; //so that I can change hueSpeed but always come back for the original
}
function keyTyped() {
if (key == 's' || key == 'S') saveCanvas('Perpetual Rainbow', 'jpg'); //if you press 's' (or 'S' in case you have capslock on) then you can save your creation
if (key == 'r' || key == 'R'){
count = 0;
count2 = 0;
points.length = 0;
resizeCanvas(windowWidth, 700);
setup();
}
if(key == '1'){
s = 80; //if you press '1', the saturation is set to 80 (more neon colours)
b = 100; //set the brightness back to 100% in case last colour mode was black
}
if(key == '2'){
s = 50; //if you press '2', the saturation is set to 50 (more pastel colours)
b = 100; //set the brightness back to 100% in case last colour mode was black
}
if(key == '3'){
s = 0; //if you press 3, the saturation is set to 0 (no colours - white)
b = 100; //set the brightness back to 100% in case last colour mode was black
}
if(key == '4'){
b = 0; //set brightness to 0, making the colour mode black
}
}
function volControl() { //to control different variables based off the volume
if (vol < 2) { //if the volume isnt loud enough
strokePer = 1.5; //reset the strokePer to normal/original value
hueSpeed = holdHue; //reset the hueSpeed to normal/original value
a = 0.2; //set the alpha of the stroke to 0.2 normally (without the loud noises)
} else { //aka if the volume is loud enough
hueSpeed = 3; //make the hueSpeed go WILD
strokePer = vol / 2; //make the lines go speedy
a = 0.8; //set the alpha of the stroke to 0.8 when there are loud noises
}
}
class Point { //the dreaded yet required object
constructor(x, y, xSpeed, ySpeed) { //to set the variables for each point to be used in the class
this.x = x;
this.y = y;
this.xS = xSpeed;
this.yS = ySpeed;
}
update() { //to update/move the point every time it moves
if (this.x >= width || this.x <= 0) { //checks that the point isnt going off the screen horizontally - if it is, turns it around
this.xS *= -1;
}
if (this.y >= height || this.y <= 0) { //checks that the point isnt going off the screen vertically - if it is, turns it around
this.yS *= -1;
}
//sets the points to the new coordinates (adding the "speed" to it)
this.x += this.xS;
this.y += this.yS;
}
}