Concept:
For this week’s assigment, I have decided to get inspired by my favorite season: WINTER (kind of ironic giving the fact that we live in Abu Dhabi). I found myself reminiscing about the snowflakes that I get to see outside my window every time I go back home.
I found this YouTube video for inspiration:
After working for a bit on it, this was the final result:
This is the code:
//SNOWFLAKES ASSIGNMENT 2
//by SP
let snowflakes = [];
let panePadding = 20;
function setup() {
createCanvas(400, 400);
noStroke();
}
function draw() {
setGradient(0, 0, width, height, color(20, 29, 68), color(100, 150, 255));
// new snowflakes
let t = frameCount / 60;
if (random() < 0.05) {
snowflakes.push(new Snowflake());
}
for (let flake of snowflakes) {
flake.update(t);
flake.display();
}
// remove snowflakes that are off the screen
snowflakes = snowflakes.filter((flake) => !flake.offScreen());
drawWindowFrame();
}
class Snowflake {
constructor() {
this.posX = random(width);
this.posY = random(-50, 0); // start slightly off-screen
this.size = random(5, 12); // size of the snowflake
this.speed = random(1, 3); // falling speed
this.drift = random(-0.5, 0.5); // slight drift left or right
this.angle = random(TWO_PI); // random rotation angle
this.rotationSpeed = random(-0.01, 0.01); // slight rotation
}
update(time) {
this.posY += this.speed;
this.posX += this.drift;
this.angle += this.rotationSpeed;
}
display() {
push();
translate(this.posX, this.posY);
rotate(this.angle);
drawSnowflake(this.size);
pop();
}
offScreen() {
return this.posY > height;
}
}
function drawSnowflake(size) {
stroke(255);
strokeWeight(2);
noFill();
// star-like shapes with lines to represent a snowflakes
beginShape();
for (let i = 0; i < 6; i++) {
let x = cos((TWO_PI * i) / 6) * size;
let y = sin((TWO_PI * i) / 6) * size;
line(0, 0, x, y);
// small branches for each main line
for (let j = 0.4; j < 1; j += 0.4) {
let branchX = cos((TWO_PI * i) / 6) * size * j;
let branchY = sin((TWO_PI * i) / 6) * size * j;
line(
branchX,
branchY,
branchX + cos((TWO_PI * (i + 0.5)) / 6) * size * 0.2,
branchY + sin((TWO_PI * (i + 0.5)) / 6) * size * 0.2
);
line(
branchX,
branchY,
branchX + cos((TWO_PI * (i - 0.5)) / 6) * size * 0.2,
branchY + sin((TWO_PI * (i - 0.5)) / 6) * size * 0.2
);
}
}
endShape(CLOSE);
}
// a vertical gradient
function setGradient(x, y, w, h, c1, c2) {
for (let i = y; i <= y + h; i++) {
let inter = map(i, y, y + h, 0, 1);
let c = lerpColor(c1, c2, inter);
stroke(c);
line(x, i, x + w, i);
}
}
// draw the window frame
function drawWindowFrame() {
fill(80, 60, 40);
noStroke();
let paneWidth = (width - panePadding * 3) / 2;
let paneHeight = (height - panePadding * 3) / 2;
rect(0, height / 2 - panePadding / 2, width, panePadding);
rect(width / 2 - panePadding / 2, 0, panePadding, height);
rect(0, 0, panePadding, height); // left
rect(width - panePadding, 0, panePadding, height); // right
rect(0, 0, width, panePadding); // top
rect(0, height - panePadding, width, panePadding); // bottom
}
The code that I am most proud of is the one for the snowflakes. In the beginning, I just created small circles but then I decided to make them look more realistic. It took me a long time but it was worth it because it all worked out in the end.
Reflection and ideas for future work or improvements:
Overall, I think I did a good job. Of course it is not super realistic but we are slowly getting there. For the future, I would like to recreate the entire scene and add a table next to the window.