xxxxxxxxxx
127
let spirals = 5; // Number of complete spirals
let pointsPerSpiral = 30; // Points per spiral
let maxRadius = 150; // Maximum radius
let height = 400; // Height of the spiral
let totalPoints = spirals * pointsPerSpiral;
let balls = []; // Array to hold multiple balls
let scale = [261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25]; // Frequencies for C major scale
let usedIndices = []; // Array to track used scale indices
function setup() {
createCanvas(600, 700, WEBGL);
angleMode(DEGREES);
}
function draw() {
background(30);
rotateX(60);
noFill();
stroke(255);
// Draw the triangle spiral
beginShape(TRIANGLE_STRIP);
for (let i = 0; i <= totalPoints; i++) {
let angle = map(i, 0, totalPoints, 0, 360 * spirals);
let rad = map(i, 0, totalPoints, 20, maxRadius);
let z = map(i, 0, totalPoints, -height / 2, height / 2);
let x = rad * cos(angle);
let y = rad * sin(angle);
let r = map(sin(frameCount + z), -1, 1, 100, 200);
let g = map(cos(frameCount + z), -1, 1, 100, 200);
let b = map(sin(frameCount + z), -1, 1, 200, 100);
stroke(r, g, b);
vertex(x, y, z);
// Adjusted triangle offset
let nextRad = rad * 0.95;
let nextZ = z + (height / totalPoints);
let nextX = nextRad * cos(angle + 2);
let nextY = nextRad * sin(angle + 2);
vertex(nextX, nextY, nextZ);
}
endShape();
// Update and display each ball
for (let j = balls.length - 1; j >= 0; j--) {
balls[j].update();
balls[j].display();
if (balls[j].isDone()) {
balls.splice(j, 1); // Remove ball if it has finished the path
}
}
}
function mousePressed() {
if (usedIndices.length >= scale.length) {
usedIndices = []; // Reset if all frequencies have been used
}
let availableIndices = scale.map((_, index) => index).filter(index => !usedIndices.includes(index));
let noteIndex = random(availableIndices);
usedIndices.push(noteIndex); // Mark this index as used
let frequency = scale[noteIndex];
let newBall = new Ball(0, 0, -height / 2, 10, frequency);
newBall.startMoving();
balls.push(newBall);
}
class Ball {
constructor(x, y, z, r, frequency) {
this.x = x;
this.y = y;
this.z = z;
this.r = r;
this.frequency = frequency;
this.moving = false;
this.pathIndex = 0;
this.osc = new p5.Oscillator('sine');
this.osc.freq(frequency);
this.osc.start();
this.osc.amp(0);
}
update() {
if (this.moving) {
if (this.pathIndex < totalPoints) {
let angle = map(this.pathIndex, 0, totalPoints, 0, 360 * spirals);
this.x = map(this.pathIndex, 0, totalPoints, 20, maxRadius) * cos(angle);
this.y = map(this.pathIndex, 0, totalPoints, 20, maxRadius) * sin(angle);
this.z = map(this.pathIndex, 0, totalPoints, -height / 2, height / 2);
this.pathIndex++;
this.osc.amp(0.5, 0.1);
} else {
this.stopMoving();
}
}
}
display() {
push();
translate(this.x, this.y, this.z);
fill(200, 0, 0);
sphere(this.r);
pop();
}
startMoving() {
this.moving = true;
this.pathIndex = 0;
}
stopMoving() {
this.moving = false;
this.osc.amp(0, 0.5);
this.osc.stop(0.5);
}
isDone() {
return !this.moving && this.pathIndex >= totalPoints;
}
}