xxxxxxxxxx
// set variable for noise, larger number has better results to move across the screen
var noiseScale = 500;
// set variable if particles are following mouseX and mouseY
var isFollowing = false;
// set variable for total number of particles
var total = 0;
// Pastel colors
var colors = [
{r: 221, g: 160, b: 221}, // Lilac
{r: 152, g: 251, b: 152}, // Pastel Green
{r: 255, g: 182, b: 193}, // Light Pink
{r: 240, g: 234, b: 214}, // Ecru
{r: 173, g: 216, b: 230} // Pastel Blue
];
var song; // Variable to store the song
var fft; // Variable to store the FFT analyzer
var isPlaying = false; // Variable to track if the song is playing
function preload() {
// Load the sound file
song = loadSound('Innerbloom.mp3');
}
class Particle {
constructor(position, color, speed) {
this.position = position;
this.color = color;
this.speed = speed;
this.size = 15;
this.alpha = 0; // set alpha to 0 to create ease in for new particles
this.direction = createVector(0, 0);
this.lifespan = Math.floor(random(100, 255)); // use random so that particles 'die' at different times
}
move(amp) {
// increase alpha as particle moves
this.alpha ++
// decrease lifespan as particle moves
if (this.lifespan > 0) {
this.lifespan--
}
// if particles are following mouseX and mouseY
if (isFollowing) {
// assign mouseX and mouseY as target
var target = createVector(mouseX, mouseY);
// calculate the distance between target and current position
var distance = target.dist(this.position);
// map the distance between positions to speed and 0
var mappedDistance = map(distance, 100, 0, this.speed, 0);
// calculate the direction of your target towards position
target = createVector(target.x - this.position.x, target.y - this.position.y);
// normalize sets the length of the vector to 1
target.normalize();
// add the target vector to position
this.position = createVector(this.position.x + target.x * mappedDistance, this.position.y + target.y * mappedDistance)
} else {
// create angles with noiseScale
this.angle = noise(this.position.x / noiseScale, this.position.y / noiseScale) * TWO_PI;
// use cos and sin curves to mimic shapes of the swirls in van Gogh's painting
this.direction.x = -cos(this.angle);
this.direction.y = sin(this.angle);
// add the direction to the current position of the particle, scaled by amplitude
this.position = createVector(this.position.x + this.direction.x * this.speed * amp, this.position.y + this.direction.y * this.speed * amp)
}
}
}
var particles = []
var particle
function setup() {
noStroke();
createCanvas(windowWidth, windowHeight);
// using width and height to determine number of particles we want on screen
total = windowWidth / 25 * windowHeight / 25
// create and store particles in an array
for (var i = 0; i < total; i++) {
particles.push(new Particle(createVector(random(width), random(height)), colors[Math.floor(random(colors.length))], random(0.5, 1)));
}
// Initialize FFT
fft = new p5.FFT();
}
function draw() {
// instead of a background fill
// use a filled rectangle with alpha value in order to create disappearing "tail"
fill(18, 63, 119, 10)
rect(0, 0, width, height)
// Get the amplitude spectrum from FFT
var spectrum = fft.analyze();
// Get the average amplitude (energy) of the spectrum
var amp = fft.getEnergy(20, 200);
for (var i = 0; i < particles.length; i++) {
// destructure data, position & color of each particle
const {position, size, color} = particles[i]
const {r, g, b} = color
const {x, y} = position
// map amplitude to alpha value
const alpha = map(amp, 0, 255, 50, 255);
// fill each ellipse with rgb value and alpha value
fill(r, g, b, alpha)
ellipse(x, y, size);
// call move function with amplitude
particles[i].move(amp / 255.0)
// if particles have reached the end of their lifespan
// or are at the edges of the window,
// remove them from the array and create a replacement partcile
if (particles[i].lifespan === 0 || x < 0 || x > width || y > height || y < 0) {
particles.splice(i, 1)
particles.push(new Particle(createVector(random(width), random(height)), colors[Math.floor(random(colors.length))], random(0.5, 1)));
}
}
}
// if mousepressed, set the particles to follow/!follow mouseX and mouseY
function mousePressed() {
isFollowing = !isFollowing
}
function keyPressed() {
// Check if the space key is pressed
if (key === ' ') {
if (song.isPlaying()) {
song.pause();
isPlaying = false;
} else {
song.play();
isPlaying = true;
}
}
}