xxxxxxxxxx
164
let clouds = [];
let drips = [];
let words = ["Hope", "Love", "Joy", "Peace", "Kindness", "Inspire"];
function setup() {
createCanvas(windowWidth, windowHeight);
smooth();
textFont('Georgia');
textAlign(CENTER, CENTER);
// Create clouds with assigned words
let numClouds = words.length;
for (let i = 0; i < numClouds; i++) {
// Evenly distribute clouds across the top area
let x = map(i, 0, numClouds - 1, width * 0.1, width * 0.9);
let y = random(height * 0.1, height * 0.3);
let size = random(120, 200);
clouds.push(new Cloud(x, y, size, words[i]));
}
}
function draw() {
drawSky();
// Update and display drifting clouds
for (let c of clouds) {
c.update();
c.display();
}
// Emit a dripping letter from each cloud at intervals
if (frameCount % 80 === 0) {
for (let c of clouds) {
let letter = c.getNextLetter();
if (letter) {
// Emit drip from a point near the lower edge of the cloud
let dripX = c.x + random(-c.size * 0.3, c.size * 0.3);
let dripY = c.y + c.size * 0.2;
drips.push(new Drip(letter, dripX, dripY));
}
}
}
// Update and display dripping letters
for (let i = drips.length - 1; i >= 0; i--) {
drips[i].update();
drips[i].display();
if (drips[i].y > height) {
drips.splice(i, 1);
}
}
}
// Draw a dynamic gradient sky with a subtle sun glow
function drawSky() {
// Background gradient from deep blue at the top to a soft warm hue near the horizon
for (let y = 0; y < height; y++) {
let inter = map(y, 0, height, 0, 1);
let c = lerpColor(color(20, 30, 80), color(250, 200, 150), inter);
stroke(c);
line(0, y, width, y);
}
// Draw a soft glowing sun near the horizon
noStroke();
let sunX = width * 0.8;
let sunY = height * 0.8;
for (let r = 150; r > 0; r -= 10) {
let alpha = map(r, 0, 150, 0, 80);
fill(255, 230, 180, alpha);
ellipse(sunX, sunY, r * 2);
}
}
// Cloud class: creates a luminous, drifting cloud with organic edges
class Cloud {
constructor(x, y, size, word) {
this.x = x;
this.y = y;
this.size = size; // Approximate radius
this.word = word;
this.letterIndex = 0; // Drip letters sequentially
this.noiseOffset = random(1000);
this.driftSpeed = random(0.1, 0.3);
}
// Return the next letter of the word, or null if finished
getNextLetter() {
if (this.letterIndex < this.word.length) {
let letter = this.word.charAt(this.letterIndex);
this.letterIndex++;
return letter;
} else {
// Option: reset to loop the word
// this.letterIndex = 0;
// return this.word.charAt(this.letterIndex++);
return null;
}
}
update() {
// Slow horizontal drift
this.x += this.driftSpeed;
if (this.x > width + this.size) {
this.x = -this.size;
}
// Optionally, add slight vertical oscillation for more life
this.y += sin(frameCount * 0.005) * 0.5;
}
display() {
noStroke();
fill(255, 240);
beginShape();
let detail = 40;
for (let a = 0; a < TWO_PI; a += TWO_PI / detail) {
// Perlin noise for organic variation in cloud edge
let n = noise(cos(a) + this.noiseOffset, sin(a) + this.noiseOffset);
let r = this.size * (0.8 + 0.4 * n);
let xOff = r * cos(a);
let yOff = r * sin(a);
vertex(this.x + xOff, this.y + yOff);
}
endShape(CLOSE);
// Optional: add a soft inner glow to the cloud
fill(255, 200);
ellipse(this.x, this.y, this.size * 1.1, this.size * 0.8);
}
}
// Drip class: elegant letter dripping with gravity and soft shadow
class Drip {
constructor(letter, x, y) {
this.letter = letter;
this.x = x;
this.y = y;
this.speedY = 0;
this.acceleration = 0.1; // Gravity effect
this.alpha = 255;
}
update() {
this.speedY += this.acceleration;
this.y += this.speedY;
// Fade the letter gently as it falls
this.alpha = max(this.alpha - 1, 0);
}
display() {
// Draw drop shadow for a luminous effect
textSize(32);
fill(0, 0, 0, this.alpha * 0.3);
text(this.letter, this.x + 2, this.y + 2);
// Draw main letter
fill(30, this.alpha);
text(this.letter, this.x, this.y);
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}