Week 2 – Assignment

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.

Leave a Reply

Your email address will not be published. Required fields are marked *