UNPKG

proton-engine

Version:

Proton is a simple and powerful javascript particle animation engine.

122 lines (108 loc) 3.53 kB
import Util from "../utils/Util"; import Vector2D from "../math/Vector2D"; import Behaviour from "./Behaviour"; export default class Collision extends Behaviour { /** * The callback after collision * * @callback Callback * * @param {Proton.Particle} particle * @param {Proton.Paritcle} otherParticle */ /** * @memberof! Proton# * @augments Proton.Behaviour * @constructor * @alias Proton.Collision * * @todo add description to mass * * @param {Proton.Emitter} [emitter=null] the attraction point coordinates * @param {Boolean} [mass=true] * @param {Callback} [callback=null] the callback after the collision * @param {Number} [life=Infinity] this behaviour's life * @param {String} [easing=ease.easeLinear] this behaviour's easing * * @property {String} name The Behaviour name */ constructor(emitter, mass, callback, life, easing) { super(life, easing); this.reset(emitter, mass, callback); this.newPool = []; this.pool = []; this.name = "Collision"; } /** * Reset this behaviour's parameters * * @memberof Proton#Proton.Collision * @method reset * @instance * * @todo add description to mass * * @param {Proton.Emitter} [emitter=null] the attraction point coordinates * @param {Boolean} [mass=true] * @param {Callback} [callback=null] the callback after the collision * @param {Number} [life=Infinity] this behaviour's life * @param {String} [easing=ease.easeLinear] this behaviour's easing */ reset(emitter, mass, callback, life, easing) { this.emitter = Util.initValue(emitter, null); this.mass = Util.initValue(mass, true); this.callback = Util.initValue(callback, null); this.collisionPool = []; this.delta = new Vector2D(); life && super.reset(life, easing); } /** * Apply this behaviour for all particles every time * * @memberof Proton#Proton.Collision * @method applyBehaviour * @instance * * @param {Proton.Particle} particle * @param {Number} time the integrate time 1/ms * @param {Int} index the particle index */ applyBehaviour(particle, time, index) { if (this.emitter) { Util.sliceArray(this.emitter.particles, index, this.newPool); } else { Util.sliceArray(this.pool, index, this.newPool); } const length = this.newPool.length; let otherParticle; let lengthSq; let overlap; let totalMass; let averageMass1, averageMass2; let i; for (i = 0; i < length; i++) { otherParticle = this.newPool[i]; if (otherParticle !== particle) { this.delta.copy(otherParticle.p); this.delta.sub(particle.p); lengthSq = this.delta.lengthSq(); const distance = particle.radius + otherParticle.radius; if (lengthSq <= distance * distance) { overlap = distance - Math.sqrt(lengthSq); overlap += 0.5; totalMass = particle.mass + otherParticle.mass; averageMass1 = this.mass ? otherParticle.mass / totalMass : 0.5; averageMass2 = this.mass ? particle.mass / totalMass : 0.5; particle.p.add( this.delta .clone() .normalize() .multiplyScalar(overlap * -averageMass1) ); otherParticle.p.add(this.delta.normalize().multiplyScalar(overlap * averageMass2)); this.callback && this.callback(particle, otherParticle); } } } } }