Let There Be Snow!
I’ll admit I’m not anywhere near snow while writing this, but I love it as an effect in a game, and since it is seasonal to Christmas time, I was inspired to put this together.
The original code
Originally I had placed several flakes, which was a simple Phaser graphic and looping through the group with a forEach
this.snowGroup.forEach(function(flake){
flake.y++;
}.bind(this))
This worked fine at first, but the problem came when I tried to increase the number of flakes from 50 to 200, and then as a test up to 500. The code started going sluggish, and then I remembered an old interview question about a starfield. I have to admit I failed that interview question but looked the answer up later after becoming obsessed with the problem.
A linked list
A linked list works by each child of a group having a reference to the child before or after it, or sometimes both. Once you have the reference you call a function of the first or last child in the group, and that function then calls the same function in the next or previous child, and it starts a chain reaction. This can be incredibly fast! I implement this in the move function of the flake class below.
Click the image to see the result
How to use
//change width and height if you only want to use a //small area var snow=new Snow(game.width,game.height);
The Code
The Snow Class
class Snow extends Phaser.Group {
constructor(w = 200, h = 200) {
super(game);
this.w = w;
this.h = h;
this.lastFlake = null;
//
//
//
this.makeFlakes();
}
makeFlakes() {
for (var i = 0; i < 250; i++) {
var flake = new Flake(this.w, this.h);
//if the last flake exists
//place it as the prev flake
if (this.lastFlake != null) {
flake.prevFlake = this.lastFlake;
}
this.lastFlake = flake;
}
}
update() {
//move the last flake
//this will start a chain reaction
this.lastFlake.move();
}
}
The Flake Class
class Flake extends Phaser.Group {
constructor(w, h) {
super(game);
//make the graphic
var f = game.add.graphics();
f.beginFill(0xffffff, 1);
f.drawCircle(0, 0, 10);
f.endFill();
this.add(f);
//
//
this.w=w;
this.h=h;
//
//
//init properties
this.y = game.rnd.integerInRange(0, h);
this.reset();
}
reset()
{
//re-init properites
this.x = game.rnd.integerInRange(0, this.w);
this.drift = game.rnd.integerInRange(-1, 1) * (.05 + Math.random() * .1);
this.fallSpeed = 1 + Math.random() * 10;
this.scale.x = .1 + Math.random();
this.scale.y = this.scale.x;
this.alpha = .1 + Math.random();
}
move()
{
this.x+=this.drift;
this.y+=this.fallSpeed;
if (this.y>this.h)
{
//take back to top
this.y=-10;
this.reset();
}
if (this.prevFlake)
{
//move the previous flake
this.prevFlake.move();
}
}
}
Happy Holidays Looking forward to more Phaser in 2018!
