entity-spawner
Version:
A time determinist 2D entity emitter for your entity/particle system
137 lines (115 loc) • 4.94 kB
JavaScript
var PIXI = require("pixi.js");
var requestAnimFrame = require("raf");
var Spawner = require("../../");
var viewport = { x:0, y:0, width:800, height:600 };
function collideRectangle (r1, r2) {
return !(r2.x > (r1.x + r1.width) ||
(r2.x + r2.width) < r1.x ||
r2.y > (r1.y + r1.height) ||
(r2.y + r2.height) < r1.y);
}
function Particle (draw, random) {
PIXI.DisplayObjectContainer.call(this);
draw.call(this, random);
this.velocity = new PIXI.Point();
}
Particle.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
Particle.prototype.constructor = Particle;
Particle.prototype.update = function (t, dt) {
this.x += this.velocity.x * dt;
this.y += this.velocity.y * dt;
if (!collideRectangle(this, viewport)) {
this.parent.removeChild(this);
}
};
var particles = new PIXI.DisplayObjectContainer();
function spawnGen (draw) {
return function (o) {
var particle = new Particle(draw, o.random);
particle.position.set.apply(particle.position, o.position);
particle.velocity.set.apply(particle.velocity, o.velocity);
particle.rotation = o.angle;
particle.blendMode = PIXI.blendModes.MULTIPLY;
particles.addChild(particle);
};
}
var spawnCircle = spawnGen(function (random) {
var clr = ~~((0.2 * random()) * 0xFF) << 16 | ~~(random() * 0xFF) << 8 | ~~(0.3*random() * 0xFF);
var radius = ~~(2 + random() * 2);
var g = new PIXI.Graphics();
g.beginFill(clr);
g.drawCircle(0, 0, radius);
g.endFill();
this.addChild(g);
});
var spawnSquare = spawnGen(function (random) {
var clr = ~~((0.5+0.5*random()) * 0xFF) << 16 | ~~(0.8*random() * 0xFF) << 8 | ~~(0.8*random() * 0xFF);
var g = new PIXI.Graphics();
g.beginFill(clr);
g.drawRect(0, 0, 20, 20);
g.endFill();
this.addChild(g);
});
var bunnyTexture = PIXI.Texture.fromImage("./bunny.png");
var spawnBunny = spawnGen(function (random) {
var bunny = new PIXI.Sprite(bunnyTexture);
if (random()<0.1) {
bunny.tint = ~~(random() * 0xFF) << 16 | ~~(random() * 0xFF) << 8 | ~~(random() * 0xFF);
}
this.addChild(bunny);
});
var PARAMS = [
{ seed: "a", spawn: spawnBunny, pos: [50, 50], vel: 0.1, speed: 500, pattern: [ 5, -1, 3, -4 ] },
{ seed: "b", spawn: spawnCircle, pos: [150, 300], rot: 3, vel: 0.05, speed: 10, pattern: [20, -80, 50, -100, 50, -150, 100, -200, 200, -200] },
{ seed: "c", spawn: spawnSquare, pos: [650, 400], rot: Math.PI/8, count: 16, vel: 0.08, speed: 1000, front: 40 },
{ seed: "d", spawn: spawnBunny, pos: [50, 500], vel: 0.2, speed: 100, randPos: 50, randAng: 0.1, randVel: 0.2 }
];
var spawners = PARAMS.map(function (spawnerParams) {
var spawner = new Spawner(spawnerParams);
spawner.init(Date.now()-5000);
return spawner;
});
var spawnernames = new PIXI.DisplayObjectContainer();
PARAMS.forEach(function (spawnerParams) {
var name = new PIXI.Text(spawnerParams.seed, { fill: "#000", font: "normal 20px monospace" });
name.position.set.apply(name.position, spawnerParams.pos);
spawnernames.addChild(name);
});
var renderer = PIXI.autoDetectRenderer(viewport.width, viewport.height);
var stage = new PIXI.Stage(0xFFFFFF);
stage.addChild(particles);
stage.addChild(spawnernames);
var lastT;
function loop () {
requestAnimFrame(loop);
var t = Date.now();
if (!lastT) lastT = t;
var dt = t - lastT;
lastT = t;
var i;
// Update spawners
for (i=0; i<spawners.length; ++i) {
spawners[i].update(t, dt);
}
// Update particles
for (i=0; i<particles.children.length; ++i) {
particles.children[i].update(t, dt);
}
renderer.render(stage);
}
requestAnimFrame(loop);
var title = document.createElement("div");
title.style.font = "normal 20px sans-serif";
title.style.color = "#444";
title.innerHTML = '<h1>PIXI.js example of <a href="http://github.com/gre/entity-spawner">entity-spawner</a>.</h1>The spawned entities are determinist for the current time: it means you can open 2 window of this page and you will see exactly the same result. This occurs even if you open the windows at different instants: the particle system is able to catchup past-events (in this example, we will catchup entities created at most 5 seconds ago). For multiplayer purpose, you just have to synchronize the time! <a href="https://github.com/calvinfo/socket-ntp">socket-ntp</a> is a simple way to get that done with socket.io. There is even randomness in the spawner! the determinism is guaranteed by the use of <a href="https://github.com/davidbau/seedrandom">seedrandom</a>.';
var footer = document.createElement("div");
footer.style.font = "normal 10px monospace";
var descHTML = '<h2>Example Parameters:</h2><ul>';
PARAMS.forEach(function (spawnerParams) {
descHTML += '<li><pre>'+spawnerParams.seed+': '+JSON.stringify(spawnerParams)+'</pre></li>';
});
descHTML += "</ul>";
footer.innerHTML = descHTML;
document.body.appendChild(title);
document.body.appendChild(renderer.view);
document.body.appendChild(footer);