xxxxxxxxxx
/*
[Sky][Muse]
"Compass"
Visual music experience made for people waiting at the airport (or elsewhere).
Several visual music pieces will be released over the next few months around different travel
themes: map, gradations, movement, circ diem.
Length: 1:42
Visual design, programming, and music composition by [Margaret Noble] [2020]
Special thanks to Processing Forum and many others!
https://www.margaretnoble.com/
*/
'use strict';
//sound
var song;
var fft;
var button;
var smoothing = 0.9; // Smoothing of audio data
var binCount = 256; // Binning parameter (256/512/1024/2048)
let rsize = 32; //scale of N,S,E,W letters
var a = ['somewhere', 'nowhere', 'anywhere', 'everywhere'];
var index;
let shrink;
let shrink2;
let shrink3;
let shrink4;
let shrink5;
let fade = 255;
let timer = 0;
let startProgram = false;
let loaded = false;
function setup() {
song = loadSound('CompassNo1.mp3', () => {
loaded = true;
beginButton()
});
//createCanvas (320,480); //mobile size
createCanvas(windowWidth, windowHeight);
//ellipse animation variables
shrink = height * 1.5;
shrink2 = height * 1.5;
shrink3 = height * 1.5;
shrink4 = height * 1.5;
shrink5 = height * 1.5;
strokeCap(ROUND);
frameRate(10); //for this particular project
console.time('time')
noSmooth(); //does this improve running?
console.timeEnd('time')
}
function beginButton() {
let col = color(255);
let col2 = color(0);
button = createButton("begin");
button.mousePressed(beginExperience);
button.position(width / 2 - 30, height - 40);
button.size(60, 25);
button.style('background-color', col);
button.style("color", col2);
}
function draw() {
background(0);
if (startProgram == false || loaded == false) {
showLoading();
}
//start automations & sound when button pressed
else {
//start timer
// //background color changer BOTTOM RIGHT SIDE
if ((mouseX > width / 2) && (mouseY > height / 2)) { //white shade
noStroke();
fill(255);
rect(width / 4, height / 2, width / 2, height);
fill(255, 255, 0); //yellow opaque
//color timer change
if (timer > 30) { //30 seconds
fill(0, 255, 0, 200); //green sheer overlay
}
if (timer > 40) { //40 seconds
fill(245, 154, 17, 200); //orange sheer overlay
}
if (timer > 50) { //50 seconds
fill(0, 0, 255, 200); //blue sheer overlay
}
if (timer > 70) { //70 seconds
fill(0, 255, 255, 200); //cyan sheer overlay
}
if (timer > 80) { //80 seconds
fill(255, 0, 255, 200); //magenta sheer overlay
}
let bigyellow = map(mouseX, width / 2, width, 0, width * 4);
rect(width, height / 2, bigyellow, height);
}
// //"center" word at center upper left
if ((mouseX > width / 2 - 50) && (mouseX < width / 2 + 50) && (mouseY < height / 2) && (mouseY > height / 4)) {
fill(255, 150);
stroke(255);
strokeWeight(5);
line(0, height / 2 + 5, width, height / 2 + 5);
line(width / 2, 0, width / 2, height);
let grow2 = map(mouseX, width / 2 - 50, width / 2 + 50, 0, height / 6 * 4);
rect(width / 2, height / 2, grow2, grow2);
fill(0);
if (timer < 90) { //27 seconds
let grow = map(mouseX, width / 2 - 10, width / 2 + 10, 0, 40);
textSize(grow);
noStroke();
text("center", width / 2, height / 2);
}
}
//generative shape art settings
translate(width / 2, height / 2);
rectMode(CENTER);
strokeWeight(1);
var circleResolution = int(map(mouseY, 0, height, 2, width / 4));
var radius = mouseX - width / 2;
var angle = TAU / circleResolution;
//black rectgrid - LEFT SIDE OF SCREEN
if ((mouseX < width / 2)) {
stroke(255, 100);
for (var i = 0; i <= circleResolution; i++) {
var x = cos(angle * i) * radius * 4; //radius controls scale of circle
var y = sin(angle * i) * radius * 4;
rect(0, 0, y, x);
//bottom corner black diamond makes things lag
// if ((mouseX > 0) && (mouseX < width / 4) && (mouseY < height) && (mouseY > height - height / 6)) {
// fill(0, 5); //black
// stroke(255, random(100)); //flikery
// if (timer > 60) { //60 seconds
// fill(255, 5); //white
// stroke(0, random(100)); //flikery
// }
// ellipse(0, 0, y, x);
// }
}
}
// //top left half
if ((mouseY < height / 2) && (mouseX < width / 2)) {
fill(255, 0, 0, 30);
if ((timer > 25) && (timer < 54)) {
fill(255, 255, 0, 30);
}
if (timer > 550) {
fill(0, 255, 0, 30);
}
rect(0, 0, width, height);
stroke(0);
if ((timer > 10) && (timer < 30)) { //between 10 and 30 seconds
stroke(255);
}
clear();
for (var i = 0; i <= circleResolution; i++) {
var x = cos(angle * i) * radius * 4;
var y = sin(angle * i) * radius * 4;
rect(0, 0, y, x);
}
}
// //RIGHT SIDE lower
if ((mouseX > width / 2) && (mouseX < width) && (mouseY > height / 2) && (mouseY < height)) {
stroke(0);
strokeWeight(1);
let m1 = map(mouseX, width - width / 4, width, 0, 255);
fill(0, m1);
for (var i = 0; i <= circleResolution; i++) {
var x = sin(angle * i) * radius * 2;
var y = cos(angle * i) * radius * 2;
stroke(0);
fill(0);
line(x, y, 0, 0);
rect(x, y, 10, 10);
}
}
// compass pointer RIGHT SIDE TOP
push();
if ((mouseX > width / 2 + 10) && (mouseX < width) && (mouseY > 0) && (mouseY < height / 2)) {
let m2 = map(mouseY, 0, width / 2, 0, 360);
if (m2 < 180) {
fill(255, 0, 0);
}
if (m2 > 180) {
fill(0, 0, 255);
}
rotate(radians(m2)); //rotate pixel grid system with mouseX
rect(0, 0, width, 10); //spinner
ellipse(0, 0, 20, 20);
pop();
}
// compass pointer RIGHT SIDE Bottom
push();
if ((mouseX > width / 2 + 10) && (mouseX < width) && (mouseY < height) && (mouseY > height / 2)) {
let m2 = map(mouseX, 0, width / 2, 0, 360);
fill(0);
rotate(radians(m2)); //rotate pixel grid system with mouseX
rect(0, 0, width, 10); //spinner
ellipse(0, 0, 20, 20);
pop();
}
//text N, W, E, S RIGHT SIDE
if (timer < 20) { //20 seconds
push();
if ((mouseX > width / 2)) {
let m4 = map(mouseY, 0, width / 2, 0, 360);
rotate(radians(m4)); //rotate pixel grid system with mouseX
noStroke();
fill(0, 0);
textSize(rsize);
textAlign(CENTER, CENTER);
let r = 0; //randmize of letter positions in upper right side
if ((mouseX > width - width / 2 + 50) && (mouseY < height / 2)) {
r = random(0, 50)
noStroke();
fill(255, 255, 0);
rsize = random(0, 100);
}
text('N', 0 + r, -130);
text('S', 0 - r, 130);
text('W', -130, 0 + r);
text('E', 130, 0 - r);
pop();
}
}
//text: < > < > RIGHT SIDE
if ((timer > 25) && (timer < 50)) { //between 25 and 50 seconds
push();
if ((mouseX > width / 2)) {
let m4 = map(mouseY, 0, width / 2, 0, 360);
rotate(radians(m4)); //rotate pixel grid system with mouseX
noStroke();
fill(0, 0);
textSize(rsize);
textAlign(CENTER, CENTER);
let r = 0; //randmize of letter positions in upper right side
if ((mouseX > width - width / 2 + 50) && (mouseY < height / 2)) {
r = random(0, 50)
noStroke();
fill(255);
rsize = random(0, 100);
}
text('<', 0 + r, -130);
text('>', 0 - r, 90);
text('<', -130, 0 + r);
text('>', 130, 0 - r);
pop();
}
}
//array of words about place
index = round(random(0, 3));
if ((timer < 30) || (timer > 45)) { //between 30 and 60 seconds
if ((mouseX > width / 2 - 50) && (mouseX < width / 2 + 50) && (mouseY > 0) && (mouseY < height / 4)) {
textAlign(CENTER, CENTER);
noStroke();
fill(255, 200);
textSize(20);
text(a[index], random(-width / 20, width / 20), mouseY / 4 - height / 3);
}
}
//timed automation circle frames
strokeWeight(height / 5);
stroke(0);
fill(0, 0);
if (timer > 27) {
ellipse(0, 0, shrink, shrink);
shrink = shrink - 5;
shrink = constrain(shrink, 0, 2.5 * height);
}
if (timer > 45) { //45 seconds
stroke(255, 100);
ellipse(0, 0, shrink2 + height / 5, shrink2 + height / 5);
shrink2 = shrink2 - 5;
shrink2 = constrain(shrink2, height / 5, 2.5 * height);
}
if (timer > 63) { //63 seconds
stroke(0);
ellipse(0, 0, shrink3 + height / 5, shrink3 + height / 5);
shrink3 = shrink3 - 5;
shrink3 = constrain(shrink3, height / 5 * 2, 2.5 * height);
}
if (timer > 81) { //81 seconds
stroke(255, 100);
ellipse(0, 0, shrink4 + height / 5, shrink4 + height / 5);
shrink4 = shrink4 - 5;
shrink4 = constrain(shrink4, height / 5 * 3, 2.5 * height);
}
if (timer > 90) { //90 seconds
stroke(0);
ellipse(0, 0, shrink5 + height / 5, shrink5 + height / 5);
shrink5 = shrink5 - 5;
shrink5 = constrain(shrink5, height / 5 * 4, 2.5 * height);
}
if (timer > 97) { //97 seconds
strokeWeight(1);
noStroke();
fill(fade);
ellipse(0, 0, width / 3, width / 3);
rect(0, 0, width, height / 8);
fade = fade - 25;
fill(255);
textSize(40);
textAlign(CENTER, CENTER);
text('bon voyage', 0, 0);
}
} //close timed events/experience screen
} //close draw
function beginExperience() {
setInterval(() => {
timer++;
}, 1000)
button.remove();
if (song.isPlaying()) {
// song.isPlaying() returns a boolean
song.jump();
} else {
song.play();
}
startProgram = true;
}
function touchMoved() {
return false; //this prevents dragging screen around on mobile
}
function showLoading() {
background(0);
textAlign(CENTER, CENTER);
rectMode(CENTER);
stroke(255, 0, 0);
fill(255, 0, 0);
rect(width / 2, height / 2, 1, height / 2);
rect(width / 2, height / 2, height / 2, 1);
noStroke();
fill(255);
textSize(40);
text('[Sky]', width / 4, height / 2 - 120);
text('[Muse]', width / 4, height / 2 - 80);
textSize(25);
text('Compass no.1', width / 2 + width / 4, height / 2 + 80);
textSize(14);
text('Directions: Move the visuals in response to the sounds.', width / 2, height - height / 7);
fill(255);
rect(width / 2, height - 30, 58, 20);
textSize(10);
fill(0);
text('loading...', width / 2, height - 30);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
button.position(width / 2 - 30, height - 40);
}