xxxxxxxxxx
380
let roses = [];
let petals = [];
let spawnInterval = 40;
let frameCounter = 0;
let boyX = 270, boyY = 300;
let girlX = 330, girlY = 300;
let angle = 0;
let clouds = [];
let walkwayStones = [];
let fallenBlossoms = [];
let realisticTrees = [];
function setup() {
createCanvas(600, 400);
generateClouds();
generateWalkwayDetails();
generateCherryBlossomTrees();
for (let i = 0; i < 40; i++) {
let c = random(1) < 0.5 ? color(255, 180, 200) : color(255, 240, 245);
petals.push({
x: random(width),
y: random(height),
size: random(6, 12),
speedY: random(0.3, 1),
driftX: random(-0.3, 0.3),
col: c
});
}
noStroke();
}
function draw() {
drawSunriseSky();
drawClouds();
drawForestFloor();
drawWalkway();
drawToriiGate();
drawWalkwayStones();
drawFallenBlossoms();
drawAllRealisticTrees();
updateAndDrawPetals();
fill(200,0,0);
textAlign(CENTER, CENTER);
textSize(30);
text("Happy Rose Day", width / 2, 50);
angle += 0.02;
drawBoy(boyX, boyY, angle);
drawGirl(girlX, girlY, angle);
frameCounter++;
if (frameCounter % spawnInterval === 0) spawnRose();
for (let i = roses.length - 1; i >= 0; i--) {
roses[i].update();
roses[i].display();
if (roses[i].x < -30) roses.splice(i, 1);
}
}
function drawSunriseSky() {
let topColor = color(255, 150, 100);
let bottomColor = color(255, 220, 180);
let skyHeight = 200;
setGradient(0, 0, width, skyHeight, topColor, bottomColor);
}
function setGradient(x, y, w, h, c1, c2) {
noFill();
for (let i = y; i <= y + h; i++) {
let inter = map(i, y, y + h, 0, 1);
let col = lerpColor(c1, c2, inter);
stroke(col);
line(x, i, x + w, i);
}
noStroke();
}
function generateClouds() {
for (let i = 0; i < 8; i++) {
clouds.push({ x: random(width), y: random(20, 120), size: random(40, 80) });
}
}
function drawClouds() {
fill(255, 255, 255, 240);
noStroke();
for (let c of clouds) {
push();
translate(c.x, c.y);
ellipse(0, 0, c.size, c.size * 0.6);
ellipse(c.size * 0.3, -c.size * 0.2, c.size * 0.8, c.size * 0.6);
ellipse(-c.size * 0.3, -c.size * 0.2, c.size * 0.8, c.size * 0.6);
pop();
}
}
function drawForestFloor() {
fill(180, 240, 180);
rect(0, 200, width, 200);
}
function drawWalkway() {
fill(220, 220, 210);
noStroke();
beginShape();
for (let py = 200; py <= 400; py += 10) {
let wave = 12 * sin(py * 0.03);
vertex(210 + wave, py);
}
for (let py = 400; py >= 200; py -= 10) {
let wave = 12 * sin(py * 0.03 + 50);
vertex(390 + wave, py);
}
endShape(CLOSE);
stroke(140);
strokeWeight(2);
noFill();
beginShape();
for (let py = 200; py <= 400; py += 10) {
let wave = 12 * sin(py * 0.03);
vertex(210 + wave, py);
}
endShape();
beginShape();
for (let py = 200; py <= 400; py += 10) {
let wave = 12 * sin(py * 0.03 + 50);
vertex(390 + wave, py);
}
endShape();
noStroke();
}
function drawToriiGate() {
push();
translate(400, 220);
fill(200, 0, 0);
rectMode(CENTER);
rect(0, -30, 120, 12, 3);
rect(0, -40, 140, 8, 4);
fill(220, 0, 0);
rect(-40, 0, 15, 60);
rect(40, 0, 15, 60);
fill(180, 0, 0);
rect(0, -10, 90, 6);
pop();
}
function generateWalkwayDetails() {
let numStones = 30;
for (let i = 0; i < numStones; i++) {
let sx = random(210, 390);
let sy = random(200, 400);
let w = random(10, 20);
let h = random(8, 14);
walkwayStones.push({ x: sx, y: sy, w, h });
}
let numFallen = 40;
for (let i = 0; i < numFallen; i++) {
let fx = random(210, 390);
let fy = random(200, 400);
let size = random(5, 10);
fallenBlossoms.push({ x: fx, y: fy, r: size });
}
}
function drawWalkwayStones() {
fill(200, 200, 190);
noStroke();
for (let st of walkwayStones) {
push();
translate(st.x, st.y);
ellipse(0, 0, st.w, st.h);
pop();
}
}
function drawFallenBlossoms() {
noStroke();
fill(255, 180, 200);
for (let fb of fallenBlossoms) {
ellipse(fb.x, fb.y, fb.r, fb.r);
}
}
function generateCherryBlossomTrees() {
let numTrees = 6;
for (let i = 0; i < numTrees; i++) {
let tx = random(width);
while (tx > 190 && tx < 410) tx = random(width);
let ty = random(230, 385);
let s = random(0.8, 1.4);
let t = createFractalCherryTree(tx, ty, s);
realisticTrees.push(t);
}
}
function createFractalCherryTree(x, y, scaleFactor) {
let tree = { x, y, scale: scaleFactor, branches: [], flowers: [] };
let trunkLen = random(35, 50);
let trunkThickness = random(5, 8);
let depth = 3;
growBranches(tree, 0, 0, -PI/2, trunkLen, trunkThickness, depth);
return tree;
}
function growBranches(tree, x1, y1, angle, length, thick, depth) {
let x2 = x1 + length * cos(angle);
let y2 = y1 + length * sin(angle);
tree.branches.push({ x1, y1, x2, y2, thick });
if (depth <= 0) {
addFlowerCluster(tree, x2, y2);
return;
}
let branchCount = floor(random(2, 3));
for (let i = 0; i < branchCount; i++) {
let newAngle = angle + random(-0.6, 0.6);
let newLen = length * random(0.6, 0.8);
let newThick = thick * random(0.6, 0.8);
growBranches(tree, x2, y2, newAngle, newLen, newThick, depth - 1);
}
}
function addFlowerCluster(tree, xCenter, yCenter) {
let numFlowers = floor(random(4, 8));
for (let i = 0; i < numFlowers; i++) {
let offsetX = random(-20, 20);
let offsetY = random(-20, 20);
let size = random(6, 10);
let rot = random(TWO_PI);
tree.flowers.push({
x: xCenter + offsetX,
y: yCenter + offsetY,
size,
angle: rot
});
}
}
function drawAllRealisticTrees() {
for (let t of realisticTrees) drawFractalCherryTree(t);
}
function drawFractalCherryTree(tree) {
push();
translate(tree.x, tree.y);
scale(tree.scale);
stroke(100, 60, 20);
strokeCap(ROUND);
for (let b of tree.branches) {
strokeWeight(b.thick);
line(b.x1, b.y1, b.x2, b.y2);
}
noStroke();
fill(255, 180, 200);
for (let f of tree.flowers) drawFivePetalFlower(f.x, f.y, f.size, f.angle);
pop();
}
function drawFivePetalFlower(cx, cy, size, rot) {
push();
translate(cx, cy);
rotate(rot);
fill(255, 180, 200);
for (let i = 0; i < 5; i++) {
ellipse(0, -size * 0.3, size * 0.45, size);
rotate(TWO_PI / 5);
}
fill(255, 230, 240);
ellipse(0, 0, size * 0.4);
pop();
}
function updateAndDrawPetals() {
for (let i = 0; i < petals.length; i++) {
petals[i].y += petals[i].speedY;
petals[i].x += petals[i].driftX;
if (petals[i].y > height + 10) {
petals[i].y = -10;
petals[i].x = random(width);
}
fill(petals[i].col);
noStroke();
ellipse(petals[i].x, petals[i].y, petals[i].size, petals[i].size * 0.7);
}
}
function spawnRose() {
roses.push(new Rose(girlX + 25, girlY - 12));
}
class Rose {
constructor(x, y) {
this.x = x;
this.y = y;
this.speed = random(2, 3);
this.offsetY = random(-1, 1);
}
update() {
this.x -= this.speed;
this.y += this.offsetY;
}
display() {
push();
translate(this.x, this.y);
fill(255, 0, 100);
ellipse(0, 0, 10, 10);
fill(0, 150, 0);
rect(-1, 0, 2, 10);
pop();
}
}
function drawBoy(x, y, armWave) {
push();
translate(x, y);
fill(255, 210, 180);
ellipse(0, -40, 30, 36);
fill(100, 60, 20);
arc(0, -45, 32, 20, PI, 0);
ellipse(0, -50, 8, 6);
fill(0);
ellipse(-5, -42, 3, 3);
ellipse(5, -42, 3, 3);
stroke(0);
strokeWeight(1);
noFill();
arc(0, -35, 7, 4, 0, PI);
noStroke();
fill(130, 200, 255);
rect(-13, -25, 26, 35, 5);
push();
translate(-13, -25);
rotate(sin(armWave) * 0.2);
rect(-5, 0, 8, 22, 5);
pop();
push();
translate(13, -25);
rotate(cos(armWave) * 0.1);
rect(-3, 0, 8, 22, 5);
pop();
fill(80, 80, 80);
rect(-10, 10, 8, 25, 3);
rect(2, 10, 8, 25, 3);
pop();
}
function drawGirl(x, y, armWave) {
push();
translate(x, y);
fill(150, 80, 20);
ellipse(0, -42, 42, 48);
fill(255, 220, 200);
ellipse(0, -40, 30, 36);
fill(150, 80, 20);
arc(0, -46, 35, 26, PI, 0);
rect(-15, -48, 30, 5, 3);
fill(0);
ellipse(-5, -42, 3, 3);
ellipse(5, -42, 3, 3);
stroke(0);
strokeWeight(1);
noFill();
arc(0, -35, 7, 4, 0, PI);
noStroke();
fill(255, 170, 200);
rect(-13, -25, 26, 35, 5);
push();
translate(-13, -25);
rotate(cos(armWave) * 0.1);
rect(-5, 0, 8, 22, 5);
pop();
push();
translate(13, -25);
rotate(sin(armWave) * 0.2);
rect(-3, 0, 8, 22, 5);
pop();
fill(100, 90, 150);
rect(-10, 10, 8, 25, 3);
rect(2, 10, 8, 25, 3);
pop();
}