Particles now emit at a specified rate and correctly obey parent positions

This commit is contained in:
Nathan Kunicki 2016-02-13 23:22:21 +00:00
parent 9f53e28f35
commit 2d701de8d1
7 changed files with 198 additions and 43 deletions

70
dist/es5.js vendored
View File

@ -1448,6 +1448,8 @@
this._lastCalculated = 0; this._lastCalculated = 0;
this._game = null; this._game = null;
this._parent = null; this._parent = null;
this._creationTime = +new Date();
} }
(0, _createClass3.default)(Entity, [{ (0, _createClass3.default)(Entity, [{
@ -1550,6 +1552,12 @@
key: "_updateEntity", key: "_updateEntity",
value: function _updateEntity(delta) { value: function _updateEntity(delta) {
if (this.timeToLive) {
if (+new Date() - this._creationTime > this.timeToLive) {
this._parent.detachChildEntity(this);
}
}
// Calculate new position based on velocity and acceleration if there's one set // Calculate new position based on velocity and acceleration if there's one set
if (this.velocity) { if (this.velocity) {
@ -1938,47 +1946,87 @@
var Emitter = function (_Entity) { var Emitter = function (_Entity) {
(0, _inherits3.default)(Emitter, _Entity); (0, _inherits3.default)(Emitter, _Entity);
function Emitter(x, y, velocity, particle) { function Emitter(x, y, rate, velocity, particle) {
(0, _classCallCheck3.default)(this, Emitter); (0, _classCallCheck3.default)(this, Emitter);
var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(Emitter).call(this, x, y)); var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(Emitter).call(this, x, y));
_this.particleVelocity = velocity; _this.particleVelocity = velocity;
_this.particleClass = particle; _this.particleClass = particle;
_this.emitRate = rate;
_this.emitting = false; _this.emitting = false;
_this._lastEmitTime = _this._creationTime;
_this._wasEmitting = false;
_this.particles = []; _this.particles = [];
_this.spread = function () { _this.spread = function () {
return Math.PI / 32; return Math.PI / 1;
}; };
return _this; return _this;
} }
(0, _createClass3.default)(Emitter, [{ (0, _createClass3.default)(Emitter, [{
key: "setParticleParent",
value: function setParticleParent(entity) {
this._particleParent = entity;
}
}, {
key: "_emit", key: "_emit",
value: function _emit() { value: function _emit() {
var ParticleClass = this.particleClass,
parent = this._particleParent || this._parent;
var angle = this.particleVelocity.angle() + this.spread() - Math.random() * this.spread() * 2,
magnitude = this.particleVelocity.length(),
velocity = _vector2d2.default.fromAngle(angle, magnitude);
var particle = new ParticleClass(this._calculatedPos.x, this._calculatedPos.y);
particle.velocity = velocity;
this.particles.push(particle);
parent.addChildEntity(particle);
}
}, {
key: "_triggerEmissions",
value: function _triggerEmissions() {
// We prematurely call preprocess so that child particles can spawn from the emitters permission but be children of a different parent
// NK: This might cause a bug where child renders have an incorrect position because preprocess should normally be called after the update function but before the render, here it is before update. We'll see.
this._preprocess();
if (this.emitting) { if (this.emitting) {
var ParticleClass = this.particleClass; var currentTime = +new Date();
var angle = this.particleVelocity.angle() + this.spread() - Math.random() * this.spread() * 2, if (!this._wasEmitting) {
magnitude = this.particleVelocity.length(), this._wasEmitting = true;
velocity = _vector2d2.default.fromAngle(angle, magnitude); this._lastEmitTime = currentTime;
}
var particle = new ParticleClass(this.pos.x, this.pos.y); // In honour the code of Alex Evans
particle.velocity = velocity; var emitDelta = currentTime - this._lastEmitTime;
if (emitDelta > this.emitRate) {
this.particles.push(particle); var emissions = ~ ~(emitDelta / this.emitRate);
this._parent.addChildEntity(particle);
this._lastEmitTime = currentTime + (emitDelta - this.emitRate * emissions);
for (var i = 0; i < emissions; i++) {
this._emit();
}
}
} else {
this._wasEmitting = false;
} }
} }
}, { }, {
key: "update", key: "update",
value: function update() { value: function update() {
this._emit(); this._triggerEmissions();
} }
}]); }]);
return Emitter; return Emitter;

2
dist/es5.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -101,13 +101,17 @@
var mainScene = new _es2.default.Classes.Rect(0, 0, width, height, black); var mainScene = new _es2.default.Classes.Rect(0, 0, width, height, black);
particles.addChildEntity(mainScene); particles.addChildEntity(mainScene);
var rect = new _es2.default.Classes.Rect(width / 2 - baseSize, height / 2 - baseSize, baseSize * 2, baseSize * 2, red), var rect = new _es2.default.Classes.Rect(width / 10 - baseSize, height - baseSize * 10, baseSize * 2, baseSize * 2, red),
emitter = new _es2.default.Classes.Emitter(0, 0, new _es2.default.Classes.Vector2D(1, 1), BlueParticle); emitter = new _es2.default.Classes.Emitter(baseSize, baseSize, 2, new _es2.default.Classes.Vector2D(1, 1), BlueParticle);
mainScene.addChildEntity(rect); mainScene.addChildEntity(rect);
rect.addChildEntity(emitter); rect.addChildEntity(emitter);
rect.setVelocity(0.01, 0);
rect.setAcceleration(0.01, 0);
emitter.setParticleParent(mainScene);
emitter.emitting = true; emitter.emitting = true;
particles.start(); particles.start();
}; };
@ -1455,6 +1459,8 @@
this._lastCalculated = 0; this._lastCalculated = 0;
this._game = null; this._game = null;
this._parent = null; this._parent = null;
this._creationTime = +new Date();
} }
(0, _createClass3.default)(Entity, [{ (0, _createClass3.default)(Entity, [{
@ -1557,6 +1563,12 @@
key: "_updateEntity", key: "_updateEntity",
value: function _updateEntity(delta) { value: function _updateEntity(delta) {
if (this.timeToLive) {
if (+new Date() - this._creationTime > this.timeToLive) {
this._parent.detachChildEntity(this);
}
}
// Calculate new position based on velocity and acceleration if there's one set // Calculate new position based on velocity and acceleration if there's one set
if (this.velocity) { if (this.velocity) {
@ -1945,47 +1957,87 @@
var Emitter = function (_Entity) { var Emitter = function (_Entity) {
(0, _inherits3.default)(Emitter, _Entity); (0, _inherits3.default)(Emitter, _Entity);
function Emitter(x, y, velocity, particle) { function Emitter(x, y, rate, velocity, particle) {
(0, _classCallCheck3.default)(this, Emitter); (0, _classCallCheck3.default)(this, Emitter);
var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(Emitter).call(this, x, y)); var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(Emitter).call(this, x, y));
_this.particleVelocity = velocity; _this.particleVelocity = velocity;
_this.particleClass = particle; _this.particleClass = particle;
_this.emitRate = rate;
_this.emitting = false; _this.emitting = false;
_this._lastEmitTime = _this._creationTime;
_this._wasEmitting = false;
_this.particles = []; _this.particles = [];
_this.spread = function () { _this.spread = function () {
return Math.PI / 32; return Math.PI / 1;
}; };
return _this; return _this;
} }
(0, _createClass3.default)(Emitter, [{ (0, _createClass3.default)(Emitter, [{
key: "setParticleParent",
value: function setParticleParent(entity) {
this._particleParent = entity;
}
}, {
key: "_emit", key: "_emit",
value: function _emit() { value: function _emit() {
var ParticleClass = this.particleClass,
parent = this._particleParent || this._parent;
var angle = this.particleVelocity.angle() + this.spread() - Math.random() * this.spread() * 2,
magnitude = this.particleVelocity.length(),
velocity = _vector2d2.default.fromAngle(angle, magnitude);
var particle = new ParticleClass(this._calculatedPos.x, this._calculatedPos.y);
particle.velocity = velocity;
this.particles.push(particle);
parent.addChildEntity(particle);
}
}, {
key: "_triggerEmissions",
value: function _triggerEmissions() {
// We prematurely call preprocess so that child particles can spawn from the emitters permission but be children of a different parent
// NK: This might cause a bug where child renders have an incorrect position because preprocess should normally be called after the update function but before the render, here it is before update. We'll see.
this._preprocess();
if (this.emitting) { if (this.emitting) {
var ParticleClass = this.particleClass; var currentTime = +new Date();
var angle = this.particleVelocity.angle() + this.spread() - Math.random() * this.spread() * 2, if (!this._wasEmitting) {
magnitude = this.particleVelocity.length(), this._wasEmitting = true;
velocity = _vector2d2.default.fromAngle(angle, magnitude); this._lastEmitTime = currentTime;
}
var particle = new ParticleClass(this.pos.x, this.pos.y); // In honour the code of Alex Evans
particle.velocity = velocity; var emitDelta = currentTime - this._lastEmitTime;
if (emitDelta > this.emitRate) {
this.particles.push(particle); var emissions = ~ ~(emitDelta / this.emitRate);
this._parent.addChildEntity(particle);
this._lastEmitTime = currentTime + (emitDelta - this.emitRate * emissions);
for (var i = 0; i < emissions; i++) {
this._emit();
}
}
} else {
this._wasEmitting = false;
} }
} }
}, { }, {
key: "update", key: "update",
value: function update() { value: function update() {
this._emit(); this._triggerEmissions();
} }
}]); }]);
return Emitter; return Emitter;

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,7 @@ import MomentumEngine from "../../src/es6";
let white = new MomentumEngine.Classes.Color(255, 255, 255); let white = new MomentumEngine.Classes.Color(255, 255, 255);
class BlueParticle extends MomentumEngine.Classes.Rect { class BlueParticle extends MomentumEngine.Classes.Rect {
constructor (x, y) { constructor (x, y) {
@ -15,11 +16,11 @@ class BlueParticle extends MomentumEngine.Classes.Rect {
window.onload = function () { window.onload = function () {
var width = 640, let width = 640,
height = 360, height = 360,
baseSize = width / 64; baseSize = width / 64;
var particles = new MomentumEngine.Classes.Game({ let particles = new MomentumEngine.Classes.Game({
canvas: document.getElementById("canvas"), canvas: document.getElementById("canvas"),
width: width, width: width,
height: height, height: height,
@ -27,19 +28,23 @@ window.onload = function () {
desiredFps: 60 desiredFps: 60
}); });
var black = new MomentumEngine.Classes.Color(0, 0, 0), let black = new MomentumEngine.Classes.Color(0, 0, 0),
red = new MomentumEngine.Classes.Color(255, 0, 0); red = new MomentumEngine.Classes.Color(255, 0, 0);
var mainScene = new MomentumEngine.Classes.Rect(0, 0, width, height, black); let mainScene = new MomentumEngine.Classes.Rect(0, 0, width, height, black);
particles.addChildEntity(mainScene); particles.addChildEntity(mainScene);
var rect = new MomentumEngine.Classes.Rect(width / 2 - baseSize, height / 2 - baseSize, baseSize * 2, baseSize * 2, red), let rect = new MomentumEngine.Classes.Rect(width / 10 - baseSize, height - (baseSize * 10), baseSize * 2, baseSize * 2, red),
emitter = new MomentumEngine.Classes.Emitter(0, 0, new MomentumEngine.Classes.Vector2D(1, 1), BlueParticle); emitter = new MomentumEngine.Classes.Emitter(baseSize, baseSize, 2, new MomentumEngine.Classes.Vector2D(1, 1), BlueParticle);
mainScene.addChildEntity(rect); mainScene.addChildEntity(rect);
rect.addChildEntity(emitter); rect.addChildEntity(emitter);
rect.setVelocity(0.01, 0);
rect.setAcceleration(0.01, 0);
emitter.setParticleParent(mainScene);
emitter.emitting = true; emitter.emitting = true;
particles.start(); particles.start();
}; };

View File

@ -7,46 +7,88 @@ import Vector2D from "./vector2d.js";
class Emitter extends Entity { class Emitter extends Entity {
constructor (x, y, velocity, particle) { constructor (x, y, rate, velocity, particle) {
super(x, y); super(x, y);
this.particleVelocity = velocity; this.particleVelocity = velocity;
this.particleClass = particle; this.particleClass = particle;
this.emitRate = rate;
this.emitting = false; this.emitting = false;
this._lastEmitTime = this._creationTime;
this._wasEmitting = false;
this.particles = []; this.particles = [];
this.spread = function () { this.spread = function () {
return Math.PI / 32; return Math.PI / 1;
} }
} }
setParticleParent (entity) {
this._particleParent = entity;
}
_emit () { _emit () {
let ParticleClass = this.particleClass,
parent = this._particleParent || this._parent;
let angle = this.particleVelocity.angle() + this.spread() - (Math.random() * this.spread() * 2),
magnitude = this.particleVelocity.length(),
velocity = Vector2D.fromAngle(angle, magnitude);
let particle = new ParticleClass(this._calculatedPos.x, this._calculatedPos.y);
particle.velocity = velocity;
this.particles.push(particle);
parent.addChildEntity(particle);
}
_triggerEmissions () {
// We prematurely call preprocess so that child particles can spawn from the emitters permission but be children of a different parent
// NK: This might cause a bug where child renders have an incorrect position because preprocess should normally be called after the update function but before the render, here it is before update. We'll see.
this._preprocess();
if (this.emitting) { if (this.emitting) {
let ParticleClass = this.particleClass; let currentTime = +(new Date());
let angle = this.particleVelocity.angle() + this.spread() - (Math.random() * this.spread() * 2), if (!this._wasEmitting) {
magnitude = this.particleVelocity.length(), this._wasEmitting = true;
velocity = Vector2D.fromAngle(angle, magnitude); this._lastEmitTime = currentTime;
}
let particle = new ParticleClass(this.pos.x, this.pos.y); // In honour the code of Alex Evans
particle.velocity = velocity; let emitDelta = currentTime - this._lastEmitTime;
if (emitDelta > this.emitRate) {
this.particles.push(particle); let emissions = ~~(emitDelta / this.emitRate);
this._parent.addChildEntity(particle);
this._lastEmitTime = currentTime + (emitDelta - (this.emitRate * emissions));
for (let i = 0; i < emissions; i++) {
this._emit();
}
}
} else {
this._wasEmitting = false;
} }
} }
update () { update () {
this._emit(); this._triggerEmissions();
} }

View File

@ -19,6 +19,8 @@ class Entity {
this._game = null; this._game = null;
this._parent = null; this._parent = null;
this._creationTime = +(new Date());
} }
@ -130,6 +132,12 @@ class Entity {
_updateEntity (delta) { _updateEntity (delta) {
if (this.timeToLive) {
if (+(new Date()) - this._creationTime > this.timeToLive) {
this._parent.detachChildEntity(this);
}
}
// Calculate new position based on velocity and acceleration if there's one set // Calculate new position based on velocity and acceleration if there's one set
if (this.velocity) { if (this.velocity) {