let snowflake_max_r = 12; let snowflake_min_r = 7; let snowflake_max_count = 500; class Background{ bgColor: p5.Color = p.color(100, 100, 255); snowflakes: Snowflake[] foregroundSnowflakes: Snowflake[] backgroundSnowflakes: Snowflake[] wind_direction: number = 0 ground: Ground = new Ground() constructor() { this.snowflakes = []; for (let i = 0; i < snowflake_max_count; i++){ this.snowflakes.push(this.getNewSnowflake()); } this.snowflakes.sort((a, b) => { if (a.radius < b.radius){ return -1; } if (a.radius > b.radius){ return 1; } return 0; }); this.backgroundSnowflakes = this.snowflakes.slice(0, snowflake_max_count * 2 / 3); this.foregroundSnowflakes = this.snowflakes.slice(snowflake_max_count * 2 / 3, snowflake_max_count); this.updateSettings(); } getNewSnowflake(){ return new Snowflake( p.random(p.width), p.random(-snowflake_max_r, p.height), p.random(snowflake_min_r, snowflake_max_r), ); } updateSettings(){ let allowed_snowflakes_count = $('#snow_intensity').val() as number; let visible_snowflakes = p.shuffle(this.snowflakes.filter(s => !s.hidden)); let hidden_snowflakes = p.shuffle(this.snowflakes.filter(s => s.hidden)); let snowflakes_to_add = allowed_snowflakes_count - visible_snowflakes.length; if (snowflakes_to_add > 0){ for (let i = 0; i < snowflakes_to_add; i++){ hidden_snowflakes[i].hidden = false; } } if (snowflakes_to_add < 0){ for (let i = 0; i < p.abs(snowflakes_to_add); i++){ visible_snowflakes[i].hidden = true; } } this.bgColor.setBlue( p.map( allowed_snowflakes_count, 0, snowflake_max_count, 255, 170 ) ); } update(){ this.ground.update(); this.wind_direction = p.sin(p.frameCount / 1000); this.snowflakes.forEach(s => s.update(this.wind_direction)); } display(asForeground?: boolean){ if (asForeground){ this.foregroundSnowflakes.forEach(s => s.display()); } else { p.background(this.bgColor); this.ground.display(); this.backgroundSnowflakes.forEach(s => s.display()); } } } class Snowflake{ pos: p5.Vector radius: number alpha: number hidden: boolean rotateDir: number rotation: number = 0 peakCount: number constructor(x, y, r) { this.pos = p.createVector(x, y); this.radius = r; this.hidden = false; this.alpha = 0; this.rotateDir = p.random([-1, 1]) * p.random(0.01, 0.03); this.peakCount = p.random([4, 5, 6]); } update(wind_direction: number){ let dir = p.createVector( p.map(this.radius, snowflake_min_r, snowflake_max_r, 0, 1) * wind_direction, p.map(this.radius, snowflake_min_r, snowflake_max_r, 0.5, 1) * 2 ); this.pos.add(dir); this.rotation += this.rotateDir; if (this.pos.y > p.height + this.radius){ this.pos.y = -this.radius; } if (this.pos.x > p.width + this.radius){ this.pos.x = -this.radius; } else if (this.pos.x < -this.radius){ this.pos.x = p.width + this.radius; } if (this.hidden && this.alpha > 0){ this.alpha -= 0.015; } else if (this.alpha < 1){ this.alpha += 0.015; } } display(){ p.push(); p.strokeWeight(1); p.stroke(255, this.alpha * 255); p.fill(255, this.alpha * 255); p.translate(this.pos); p.rotate(this.rotation % p.TWO_PI); for (let rad = 0; rad < p.PI; rad += p.PI / this.peakCount){ let x1 = p.cos(rad) * this.radius; let y1 = p.sin(rad) * this.radius; let x2 = p.cos(rad + p.PI) * this.radius; let y2 = p.sin(rad + p.PI) * this.radius; p.line(x1, y1, x2, y2); } p.pop(); } } class Ground{ points: p5.Vector[] constructor() { this.createPoints(); } createPoints(){ this.points = []; for (let x = 0; x < p.width; x++){ let vector = p.createVector( x, p.noise(x / 300) * 150 ); this.points.push(vector); } } update(){ } display(){ p.push(); p.fill(220, 220, 255); p.stroke(50, 50, 150); p.strokeWeight(2); p.beginShape(); for (let point of this.points){ p.vertex(point.x, point.y + p.height / 2); } p.vertex(p.width, p.height); p.vertex(0, p.height); p.endShape(p.CLOSE); p.pop(); } }