Moved relative calculation from preprocessing to on-demand via a getter

This commit is contained in:
Nathan Kunicki 2016-03-02 13:09:27 -05:00
parent d0eec1412e
commit 6936f97933
6 changed files with 54 additions and 35 deletions

View File

@ -52,18 +52,18 @@ class FireParticle extends MomentumEngine.Classes.Entity {
render () { render () {
var gradient = this._game.context.createRadialGradient( var gradient = this._game.context.createRadialGradient(
this._calculatedPos.x + fireParticleWidth / 2, this._relativePos.x + fireParticleWidth / 2,
this._calculatedPos.y + fireParticleHeight / 2, this._relativePos.y + fireParticleHeight / 2,
fireParticleWidth / 10, fireParticleWidth / 10,
this._calculatedPos.x + fireParticleWidth / 2, this._relativePos.x + fireParticleWidth / 2,
this._calculatedPos.y + fireParticleHeight / 2, this._relativePos.y + fireParticleHeight / 2,
fireParticleWidth / 2 fireParticleWidth / 2
); );
gradient.addColorStop(0, this.startColor.toString()); gradient.addColorStop(0, this.startColor.toString());
gradient.addColorStop(1, "rgba(0, 0, 0, 0)"); gradient.addColorStop(1, "rgba(0, 0, 0, 0)");
this._game.context.fillStyle = gradient; this._game.context.fillStyle = gradient;
this._game.context.fillRect(this._calculatedPos.x, this._calculatedPos.y, fireParticleWidth, fireParticleHeight); this._game.context.fillRect(this._relativePos.x, this._relativePos.y, fireParticleWidth, fireParticleHeight);
return true; return true;

View File

@ -42,7 +42,8 @@ class Emitter extends Entity {
magnitude = this.particleVelocity.length(), magnitude = this.particleVelocity.length(),
velocity = Vector2D.fromAngle(angle, magnitude); velocity = Vector2D.fromAngle(angle, magnitude);
let particle = new ParticleClass(this._calculatedPos.x, this._calculatedPos.y); // 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.
let particle = new ParticleClass(this.relativeX, this.relativeY);
particle.velocity = velocity; particle.velocity = velocity;
Utils.mergeIntoArray(particle.fields, this.particleFields); Utils.mergeIntoArray(particle.fields, this.particleFields);
@ -54,10 +55,6 @@ class Emitter extends Entity {
_triggerEmissions () { _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 currentTime = +(new Date()); let currentTime = +(new Date());

View File

@ -16,7 +16,7 @@ class Entity {
this.state = {}; this.state = {};
this.children = []; this.children = [];
this._calculatedPos = this.pos.clone(); this._relativePos = this.pos.clone();
this._lastCalculated = 0; this._lastCalculated = 0;
this._game = null; this._game = null;
this._parent = null; this._parent = null;
@ -26,6 +26,34 @@ class Entity {
} }
get x () {
return this.pos.x;
}
set x (val) {
return this.pos.x = val;
}
get y () {
return this.pos.y;
}
set y (val) {
return this.pos.y = val;
}
get relativeX () {
return this._calculateRelativePos().x;
}
get relativeY () {
return this._calculateRelativePos().y;
}
setVelocity (x, y) { setVelocity (x, y) {
if (x instanceof Vector2D) { if (x instanceof Vector2D) {
@ -90,33 +118,31 @@ class Entity {
} }
_preprocess () { _calculateRelativePos () {
// NK: The purpose of this function is to calculate the true position of the entity relative to all its parents. It does this recursively, calling the _preprocess method all the way back up the tree and continuously adding the results together. // NK: The purpose of this function is to calculate the true position of the entity relative to all its parents. It does this recursively, calling the _calculateRelativePos method all the way back up the tree and continuously adding the results together.
// Note there is a limiter, where the last calculated frame is stored, so that if the position has already been calculated for that node in this particular frame, the cached result is used rather than recalculating. // Note there is a limiter, where the last calculated frame is stored, so that if the position has already been calculated for that node in this particular frame, the cached result is used rather than recalculating.
// When rendering, the draw calls should use this._calculatedPos rather than this.pos in order for the position to be correct. // When rendering, the draw calls should use this._relativePos rather than this.pos in order for the position to be correct.
if (this._game && this._lastCalculated < this._game.frameCounter) { if (this._game && this._lastCalculated < this._game.frameCounter) {
if (this._parent) { if (this._parent) {
let parentPos = this._parent._preprocess(); this._relativePos.x = this.x + this._parent.relativeX;
this._relativePos.y = this.y + this._parent.relativeY;
this._calculatedPos.x = this.pos.x + parentPos.x;
this._calculatedPos.y = this.pos.y + parentPos.y;
} else { } else {
this._calculatedPos.x = this.pos.x; this._relativePos.x = this.x;
this._calculatedPos.y = this.pos.y; this._relativePos.y = this.y;
} }
this._lastCalculated = this._game.frameCounter; this._lastCalculated = this._game.frameCounter;
} }
return this._calculatedPos; return this._relativePos;
} }
@ -134,18 +160,16 @@ class Entity {
_calculateFields (delta) { _calculateFields (delta) {
this._preprocess(); // NK: I don't like calling preprocess everywhere outside of the render method...
let acceleration = new Vector2D(0, 0); let acceleration = new Vector2D(0, 0);
for (let i = 0; i < this.fields.length; i++) { for (let i = 0; i < this.fields.length; i++) {
let field = this.fields[i]; let field = this.fields[i];
field._preprocess();
// NK: These call _relativePos, I don't like using this outside of the render method...
let vector = new Vector2D( let vector = new Vector2D(
field._calculatedPos.x - this._calculatedPos.x, field.relativeX - this.relativeX,
field._calculatedPos.y - this._calculatedPos.y field.relativeY - this.relativeY
); );
let force = field.mass / Math.pow(vector.dot(vector), 1.5); let force = field.mass / Math.pow(vector.dot(vector), 1.5);
@ -191,8 +215,6 @@ class Entity {
_renderEntity () { _renderEntity () {
this._preprocess();
let rendered = this.render && this.render(); let rendered = this.render && this.render();
if (rendered) { if (rendered) {

View File

@ -33,7 +33,7 @@ class Rect extends Entity {
if (this._game) { if (this._game) {
this._game.context.fillStyle = this.color.toString(); this._game.context.fillStyle = this.color.toString();
this._game.context.fillRect(this._calculatedPos.x, this._calculatedPos.y, this.size.x, this.size.y); this._game.context.fillRect(this.relativeX, this.relativeY, this.size.x, this.size.y);
return true; return true;

View File

@ -57,8 +57,8 @@ class Sprite extends Entity {
this._imagePos.y, this._imagePos.y,
this._imageSize.x || subWidth, this._imageSize.x || subWidth,
this._imageSize.y || subHeight, this._imageSize.y || subHeight,
this._calculatedPos.x, this.relativeX,
this._calculatedPos.y, this.relativeY,
this.size.x || subWidth, this.size.x || subWidth,
this.size.y || subHeight this.size.y || subHeight
); );

View File

@ -9,10 +9,10 @@ class CollisionMethods {
throw new Error("AABB collisions can only be checked on these entity types: Rect"); throw new Error("AABB collisions can only be checked on these entity types: Rect");
} }
return (entity1.pos.x < entity2.pos.x + entity2.size.x && return (entity1.x < entity2.x + entity2.size.x &&
entity1.pos.x + entity1.size.x > entity2.pos.x && entity1.x + entity1.size.x > entity2.x &&
entity1.pos.y < entity2.pos.y + entity2.size.y && entity1.y < entity2.y + entity2.size.y &&
entity1.size.y + entity1.pos.y > entity2.pos.y); entity1.size.y + entity1.y > entity2.y);
} }