/// destroy()
on class members if necessary.
* Don't forget to call super.destroy()
!
*/
function () {
};
Basic.prototype.preUpdate = /**
* Pre-update is called right before update()
on each object in the game loop.
*/
function () {
};
Basic.prototype.update = /**
* Override this to update your class's position and appearance.
* This is where most of your game rules and behavioral code will go.
*/
function (forceUpdate) {
if (typeof forceUpdate === "undefined") { forceUpdate = false; }
};
Basic.prototype.postUpdate = /**
* Post-update is called right after update()
on each object in the game loop.
*/
function () {
};
Basic.prototype.render = function (camera, cameraOffsetX, cameraOffsetY, forceRender) {
if (typeof forceRender === "undefined") { forceRender = false; }
};
Basic.prototype.kill = /**
* Handy for "killing" game objects.
* Default behavior is to flag them as nonexistent AND dead.
* However, if you want the "corpse" to remain in the game,
* like to animate an effect or whatever, you should override this,
* setting only alive to false, and leaving exists true.
*/
function () {
this.alive = false;
this.exists = false;
};
Basic.prototype.revive = /**
* Handy for bringing game objects "back to life". Just sets alive and exists back to true.
* In practice, this is most often called by Object.reset()
.
*/
function () {
this.alive = true;
this.exists = true;
};
Basic.prototype.toString = /**
* Convert object to readable string name. Useful for debugging, save games, etc.
*/
function () {
return "";
};
return Basic;
})();
Phaser.Basic = Basic;
})(Phaser || (Phaser = {}));
///
- This is an internal constructor and shouldn't be called by regular users.
*
- inspired by Joa Ebert AS3 SignalBinding and Robert Penner's Slot classes.
* @author Miller Medeiros
* @constructor
* @internal
* @name SignalBinding
* @param {Signal} signal Reference to Signal object that listener is currently bound to.
* @param {Function} listener Handler function bound to the signal.
* @param {boolean} isOnce If binding should be executed just once.
* @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @param {Number} [priority] The priority level of the event listener. (default = 0).
*/
function SignalBinding(signal, listener, isOnce, listenerContext, priority) {
if (typeof priority === "undefined") { priority = 0; }
/**
* If binding is active and should be executed.
* @type boolean
*/
this.active = true;
/**
* Default parameters passed to listener during `Signal.dispatch` and `SignalBinding.execute`. (curried parameters)
* @type Array|null
*/
this.params = null;
this._listener = listener;
this._isOnce = isOnce;
this.context = listenerContext;
this._signal = signal;
this.priority = priority || 0;
}
SignalBinding.prototype.execute = /**
* Call listener passing arbitrary parameters.
*
If binding was added using `Signal.addOnce()` it will be automatically removed from signal dispatch queue, this method is used internally for the signal dispatch.
* @param {Array} [paramsArr] Array of parameters that should be passed to the listener * @return {*} Value returned by the listener. */ function (paramsArr) { var handlerReturn; var params; if(this.active && !!this._listener) { params = this.params ? this.params.concat(paramsArr) : paramsArr; handlerReturn = this._listener.apply(this.context, params); if(this._isOnce) { this.detach(); } } return handlerReturn; }; SignalBinding.prototype.detach = /** * Detach binding from signal. * - alias to: mySignal.remove(myBinding.getListener()); * @return {Function|null} Handler function bound to the signal or `null` if binding was previously detached. */ function () { return this.isBound() ? this._signal.remove(this._listener, this.context) : null; }; SignalBinding.prototype.isBound = /** * @return {Boolean} `true` if binding is still bound to the signal and have a listener. */ function () { return (!!this._signal && !!this._listener); }; SignalBinding.prototype.isOnce = /** * @return {boolean} If SignalBinding will only be executed once. */ function () { return this._isOnce; }; SignalBinding.prototype.getListener = /** * @return {Function} Handler function bound to the signal. */ function () { return this._listener; }; SignalBinding.prototype.getSignal = /** * @return {Signal} Signal that listener is currently bound to. */ function () { return this._signal; }; SignalBinding.prototype._destroy = /** * Delete instance properties * @private */ function () { delete this._signal; delete this._listener; delete this.context; }; SignalBinding.prototype.toString = /** * @return {string} String representation of the object. */ function () { return '[SignalBinding isOnce:' + this._isOnce + ', isBound:' + this.isBound() + ', active:' + this.active + ']'; }; return SignalBinding; })(); Phaser.SignalBinding = SignalBinding; })(Phaser || (Phaser = {})); ///IMPORTANT: Setting this property during a dispatch will only affect the next dispatch, if you want to stop the propagation of a signal use `halt()` instead.
* @type boolean */ this.active = true; } Signal.VERSION = '1.0.0'; Signal.prototype.validateListener = /** * * @method validateListener * @param {Any} listener * @param {Any} fnName */ function (listener, fnName) { if(typeof listener !== 'function') { throw new Error('listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName)); } }; Signal.prototype._registerListener = /** * @param {Function} listener * @param {boolean} isOnce * @param {Object} [listenerContext] * @param {Number} [priority] * @return {SignalBinding} * @private */ function (listener, isOnce, listenerContext, priority) { var prevIndex = this._indexOfListener(listener, listenerContext); var binding; if(prevIndex !== -1) { binding = this._bindings[prevIndex]; if(binding.isOnce() !== isOnce) { throw new Error('You cannot add' + (isOnce ? '' : 'Once') + '() then add' + (!isOnce ? '' : 'Once') + '() the same listener without removing the relationship first.'); } } else { binding = new Phaser.SignalBinding(this, listener, isOnce, listenerContext, priority); this._addBinding(binding); } if(this.memorize && this._prevParams) { binding.execute(this._prevParams); } return binding; }; Signal.prototype._addBinding = /** * * @method _addBinding * @param {SignalBinding} binding * @private */ function (binding) { //simplified insertion sort var n = this._bindings.length; do { --n; }while(this._bindings[n] && binding.priority <= this._bindings[n].priority); this._bindings.splice(n + 1, 0, binding); }; Signal.prototype._indexOfListener = /** * * @method _indexOfListener * @param {Function} listener * @return {number} * @private */ function (listener, context) { var n = this._bindings.length; var cur; while(n--) { cur = this._bindings[n]; if(cur.getListener() === listener && cur.context === context) { return n; } } return -1; }; Signal.prototype.has = /** * Check if listener was attached to Signal. * @param {Function} listener * @param {Object} [context] * @return {boolean} if Signal has the specified listener. */ function (listener, context) { if (typeof context === "undefined") { context = null; } return this._indexOfListener(listener, context) !== -1; }; Signal.prototype.add = /** * Add a listener to the signal. * @param {Function} listener Signal handler function. * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0) * @return {SignalBinding} An Object representing the binding between the Signal and listener. */ function (listener, listenerContext, priority) { if (typeof listenerContext === "undefined") { listenerContext = null; } if (typeof priority === "undefined") { priority = 0; } this.validateListener(listener, 'add'); return this._registerListener(listener, false, listenerContext, priority); }; Signal.prototype.addOnce = /** * Add listener to the signal that should be removed after first execution (will be executed only once). * @param {Function} listener Signal handler function. * @param {Object} [listenerContext] Context on which listener will be executed (object that should represent the `this` variable inside listener function). * @param {Number} [priority] The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0) * @return {SignalBinding} An Object representing the binding between the Signal and listener. */ function (listener, listenerContext, priority) { if (typeof listenerContext === "undefined") { listenerContext = null; } if (typeof priority === "undefined") { priority = 0; } this.validateListener(listener, 'addOnce'); return this._registerListener(listener, true, listenerContext, priority); }; Signal.prototype.remove = /** * Remove a single listener from the dispatch queue. * @param {Function} listener Handler function that should be removed. * @param {Object} [context] Execution context (since you can add the same handler multiple times if executing in a different context). * @return {Function} Listener handler function. */ function (listener, context) { if (typeof context === "undefined") { context = null; } this.validateListener(listener, 'remove'); var i = this._indexOfListener(listener, context); if(i !== -1) { this._bindings[i]._destroy(); this._bindings.splice(i, 1); } return listener; }; Signal.prototype.removeAll = /** * Remove all listeners from the Signal. */ function () { if(this._bindings) { var n = this._bindings.length; while(n--) { this._bindings[n]._destroy(); } this._bindings.length = 0; } }; Signal.prototype.getNumListeners = /** * @return {number} Number of listeners attached to the Signal. */ function () { return this._bindings.length; }; Signal.prototype.halt = /** * Stop propagation of the event, blocking the dispatch to next listeners on the queue. *IMPORTANT: should be called only during signal dispatch, calling it before/after dispatch won't affect signal broadcast.
* @see Signal.prototype.disable */ function () { this._shouldPropagate = false; }; Signal.prototype.dispatch = /** * Dispatch/Broadcast Signal to all listeners added to the queue. * @param {...*} [params] Parameters that should be passed to each handler. */ function () { var paramsArr = []; for (var _i = 0; _i < (arguments.length - 0); _i++) { paramsArr[_i] = arguments[_i + 0]; } if(!this.active) { return; } var n = this._bindings.length; var bindings; if(this.memorize) { this._prevParams = paramsArr; } if(!n) { //should come after memorize return; } bindings = this._bindings.slice(0)//clone array in case add/remove items during dispatch ; this._shouldPropagate = true//in case `halt` was called before dispatch or during the previous dispatch. ; //execute all callbacks until end of the list or until a callback returns `false` or stops propagation //reverse loop since listeners with higher priority will be added at the end of the list do { n--; }while(bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false); }; Signal.prototype.forget = /** * Forget memorized arguments. * @see Signal.memorize */ function () { this._prevParams = null; }; Signal.prototype.dispose = /** * Remove all bindings from signal and destroy any reference to external objects (destroy Signal object). *IMPORTANT: calling any method on the signal instance after calling dispose will throw errors.
*/ function () { this.removeAll(); delete this._bindings; delete this._prevParams; }; Signal.prototype.toString = /** * @return {string} String representation of the object. */ function () { return '[Signal active:' + this.active + ' numListeners:' + this.getNumListeners() + ']'; }; return Signal; })(); Phaser.Signal = Signal; })(Phaser || (Phaser = {})); ///CollisionMask
for the given GameObject.
*
* @param game {Phaser.Game} Current game instance.
* @param parent {Phaser.GameObject} The GameObject this CollisionMask belongs to.
* @param x {number} The initial x position of the CollisionMask.
* @param y {number} The initial y position of the CollisionMask.
* @param width {number} The width of the CollisionMask.
* @param height {number} The height of the CollisionMask.
*/
function CollisionMask(game, parent, x, y, width, height) {
/**
* Geom type of this sprite. (available: QUAD, POINT, CIRCLE, LINE, RECTANGLE, POLYGON)
* @type {number}
*/
this.type = 0;
this._game = game;
this._parent = parent;
// By default the CollisionMask is a quad
this.type = CollisionMask.QUAD;
this.quad = new Phaser.Quad(this._parent.x, this._parent.y, this._parent.width, this._parent.height);
this.offset = new Phaser.MicroPoint(0, 0);
this.last = new Phaser.MicroPoint(0, 0);
this._ref = this.quad;
return this;
}
CollisionMask.QUAD = 0;
CollisionMask.POINT = 1;
CollisionMask.CIRCLE = 2;
CollisionMask.LINE = 3;
CollisionMask.RECTANGLE = 4;
CollisionMask.POLYGON = 5;
CollisionMask.prototype.createCircle = /**
* Create a circle shape with specific diameter.
* @param diameter {number} Diameter of the circle.
* @return {CollisionMask} This
*/
function (diameter) {
this.type = CollisionMask.CIRCLE;
this.circle = new Phaser.Circle(this.last.x, this.last.y, diameter);
this._ref = this.circle;
return this;
};
CollisionMask.prototype.preUpdate = /**
* Pre-update is called right before update() on each object in the game loop.
*/
function () {
this.last.x = this.x;
this.last.y = this.y;
};
CollisionMask.prototype.update = function () {
this._ref.x = this._parent.x + this.offset.x;
this._ref.y = this._parent.y + this.offset.y;
};
CollisionMask.prototype.render = /**
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
* @param camera {Camera} Camera the bound will be rendered to.
* @param cameraOffsetX {number} X offset of bound to the camera.
* @param cameraOffsetY {number} Y offset of bound to the camera.
*/
function (camera, cameraOffsetX, cameraOffsetY) {
var _dx = cameraOffsetX + (this.x - camera.worldView.x);
var _dy = cameraOffsetY + (this.y - camera.worldView.y);
this._parent.context.fillStyle = this._parent.renderDebugColor;
if(this.type == CollisionMask.QUAD) {
this._parent.context.fillRect(_dx, _dy, this.width, this.height);
} else if(this.type == CollisionMask.CIRCLE) {
this._parent.context.beginPath();
this._parent.context.arc(_dx, _dy, this.circle.radius, 0, Math.PI * 2);
this._parent.context.fill();
this._parent.context.closePath();
}
};
CollisionMask.prototype.destroy = /**
* Destroy all objects and references belonging to this CollisionMask
*/
function () {
this._game = null;
this._parent = null;
this._ref = null;
this.quad = null;
this.point = null;
this.circle = null;
this.rect = null;
this.line = null;
this.offset = null;
};
CollisionMask.prototype.intersectsRaw = function (left, right, top, bottom) {
//if ((objBounds.x + objBounds.width > x) && (objBounds.x < x + width) && (objBounds.y + objBounds.height > y) && (objBounds.y < y + height))
return true;
};
CollisionMask.prototype.intersectsVector = function (vector) {
if(this.type == CollisionMask.QUAD) {
return this.quad.contains(vector.x, vector.y);
}
};
CollisionMask.prototype.intersects = /**
* Gives a basic boolean response to a geometric collision.
* If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
* @param source {GeomSprite} Sprite you want to check.
* @return {boolean} Whether they overlaps or not.
*/
function (source) {
// Quad vs. Quad
if(this.type == CollisionMask.QUAD && source.type == CollisionMask.QUAD) {
return this.quad.intersects(source.quad);
}
// Circle vs. Circle
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.CIRCLE) {
return Phaser.Collision.circleToCircle(this.circle, source.circle).result;
}
// Circle vs. Rect
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.RECTANGLE) {
return Phaser.Collision.circleToRectangle(this.circle, source.rect).result;
}
// Circle vs. Point
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.POINT) {
return Phaser.Collision.circleContainsPoint(this.circle, source.point).result;
}
// Circle vs. Line
if(this.type == CollisionMask.CIRCLE && source.type == CollisionMask.LINE) {
return Phaser.Collision.lineToCircle(source.line, this.circle).result;
}
// Rect vs. Rect
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.RECTANGLE) {
return Phaser.Collision.rectangleToRectangle(this.rect, source.rect).result;
}
// Rect vs. Circle
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.CIRCLE) {
return Phaser.Collision.circleToRectangle(source.circle, this.rect).result;
}
// Rect vs. Point
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.POINT) {
return Phaser.Collision.pointToRectangle(source.point, this.rect).result;
}
// Rect vs. Line
if(this.type == CollisionMask.RECTANGLE && source.type == CollisionMask.LINE) {
return Phaser.Collision.lineToRectangle(source.line, this.rect).result;
}
// Point vs. Point
if(this.type == CollisionMask.POINT && source.type == CollisionMask.POINT) {
return this.point.equals(source.point);
}
// Point vs. Circle
if(this.type == CollisionMask.POINT && source.type == CollisionMask.CIRCLE) {
return Phaser.Collision.circleContainsPoint(source.circle, this.point).result;
}
// Point vs. Rect
if(this.type == CollisionMask.POINT && source.type == CollisionMask.RECTANGLE) {
return Phaser.Collision.pointToRectangle(this.point, source.rect).result;
}
// Point vs. Line
if(this.type == CollisionMask.POINT && source.type == CollisionMask.LINE) {
return source.line.isPointOnLine(this.point.x, this.point.y);
}
// Line vs. Line
if(this.type == CollisionMask.LINE && source.type == CollisionMask.LINE) {
return Phaser.Collision.lineSegmentToLineSegment(this.line, source.line).result;
}
// Line vs. Circle
if(this.type == CollisionMask.LINE && source.type == CollisionMask.CIRCLE) {
return Phaser.Collision.lineToCircle(this.line, source.circle).result;
}
// Line vs. Rect
if(this.type == CollisionMask.LINE && source.type == CollisionMask.RECTANGLE) {
return Phaser.Collision.lineSegmentToRectangle(this.line, source.rect).result;
}
// Line vs. Point
if(this.type == CollisionMask.LINE && source.type == CollisionMask.POINT) {
return this.line.isPointOnLine(source.point.x, source.point.y);
}
return false;
};
CollisionMask.prototype.checkHullIntersection = function (mask) {
if((this.hullX + this.hullWidth > mask.hullX) && (this.hullX < mask.hullX + mask.width) && (this.hullY + this.hullHeight > mask.hullY) && (this.hullY < mask.hullY + mask.hullHeight)) {
return true;
} else {
return false;
}
};
Object.defineProperty(CollisionMask.prototype, "hullWidth", {
get: function () {
if(this.deltaX > 0) {
return this.width + this.deltaX;
} else {
return this.width - this.deltaX;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "hullHeight", {
get: function () {
if(this.deltaY > 0) {
return this.height + this.deltaY;
} else {
return this.height - this.deltaY;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "hullX", {
get: function () {
if(this.x < this.last.x) {
return this.x;
} else {
return this.last.x;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "hullY", {
get: function () {
if(this.y < this.last.y) {
return this.y;
} else {
return this.last.y;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "deltaXAbs", {
get: function () {
return (this.deltaX > 0 ? this.deltaX : -this.deltaX);
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "deltaYAbs", {
get: function () {
return (this.deltaY > 0 ? this.deltaY : -this.deltaY);
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "deltaX", {
get: function () {
return this.x - this.last.x;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "deltaY", {
get: function () {
return this.y - this.last.y;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "x", {
get: function () {
return this._ref.x;
//return this.quad.x;
},
set: function (value) {
this._ref.x = value;
//this.quad.x = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "y", {
get: function () {
return this._ref.y;
//return this.quad.y;
},
set: function (value) {
this._ref.y = value;
//this.quad.y = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "width", {
get: function () {
//return this.quad.width;
return this._ref.width;
},
set: //public get rotation(): number {
// return this._angle;
//}
//public set rotation(value: number) {
// this._angle = this._game.math.wrap(value, 360, 0);
//}
//public get angle(): number {
// return this._angle;
//}
//public set angle(value: number) {
// this._angle = this._game.math.wrap(value, 360, 0);
//}
function (value) {
//this.quad.width = value;
this._ref.width = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "height", {
get: function () {
//return this.quad.height;
return this._ref.height;
},
set: function (value) {
//this.quad.height = value;
this._ref.height = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "left", {
get: function () {
return this.x;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "right", {
get: function () {
return this.x + this.width;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "top", {
get: function () {
return this.y;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "bottom", {
get: function () {
return this.y + this.height;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "halfWidth", {
get: function () {
return this.width / 2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CollisionMask.prototype, "halfHeight", {
get: function () {
return this.height / 2;
},
enumerable: true,
configurable: true
});
return CollisionMask;
})();
Phaser.CollisionMask = CollisionMask;
})(Phaser || (Phaser = {}));
var __extends = this.__extends || function (d, b) {
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
/// GameObject
object at specific position with specific width and height.
*
* @param [x] {number} The x position of the object.
* @param [y] {number} The y position of the object.
* @param [width] {number} The width of the object.
* @param [height] {number} The height of the object.
*/
function GameObject(game, x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof width === "undefined") { width = 16; }
if (typeof height === "undefined") { height = 16; }
_super.call(this, game);
/**
* Angle of this object.
* @type {number}
*/
this._angle = 0;
/**
* What action will be performed when object is out of the worldBounds.
* This will default to GameObject.OUT_OF_BOUNDS_STOP.
* @type {number}
*/
this.outOfBoundsAction = 0;
/**
* Z-order value of the object.
*/
this.z = 0;
/**
* This value is added to the angle of the GameObject.
* For example if you had a sprite drawn facing straight up then you could set
* rotationOffset to 90 and it would correspond correctly with Phasers rotation system
* @type {number}
*/
this.rotationOffset = 0;
/**
* Controls if the GameObject is rendered rotated or not.
* If renderRotation is false then the object can still rotate but it will never be rendered rotated.
* @type {boolean}
*/
this.renderRotation = true;
/**
* Set this to false if you want to skip the automatic motion/movement stuff
* (see updateMotion()).
* @type {boolean}
*/
this.moves = true;
// Input
this.inputEnabled = false;
this._inputOver = false;
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this.frameBounds = new Phaser.Rectangle(x, y, width, height);
this.exists = true;
this.active = true;
this.visible = true;
this.alive = true;
this.isGroup = false;
this.alpha = 1;
this.scale = new Phaser.MicroPoint(1, 1);
this.last = new Phaser.MicroPoint(x, y);
this.align = GameObject.ALIGN_TOP_LEFT;
this.mass = 1;
this.elasticity = 0;
this.health = 1;
this.immovable = false;
this.moves = true;
this.worldBounds = null;
this.touching = Phaser.Collision.NONE;
this.wasTouching = Phaser.Collision.NONE;
this.allowCollisions = Phaser.Collision.ANY;
this.velocity = new Phaser.MicroPoint();
this.acceleration = new Phaser.MicroPoint();
this.drag = new Phaser.MicroPoint();
this.maxVelocity = new Phaser.MicroPoint(10000, 10000);
this.angle = 0;
this.angularVelocity = 0;
this.angularAcceleration = 0;
this.angularDrag = 0;
this.maxAngular = 10000;
this.cameraBlacklist = [];
this.scrollFactor = new Phaser.MicroPoint(1, 1);
this.collisionMask = new Phaser.CollisionMask(game, this, x, y, width, height);
}
GameObject.ALIGN_TOP_LEFT = 0;
GameObject.ALIGN_TOP_CENTER = 1;
GameObject.ALIGN_TOP_RIGHT = 2;
GameObject.ALIGN_CENTER_LEFT = 3;
GameObject.ALIGN_CENTER = 4;
GameObject.ALIGN_CENTER_RIGHT = 5;
GameObject.ALIGN_BOTTOM_LEFT = 6;
GameObject.ALIGN_BOTTOM_CENTER = 7;
GameObject.ALIGN_BOTTOM_RIGHT = 8;
GameObject.OUT_OF_BOUNDS_STOP = 0;
GameObject.OUT_OF_BOUNDS_KILL = 1;
GameObject.prototype.preUpdate = /**
* Pre-update is called right before update() on each object in the game loop.
*/
function () {
this.last.x = this.frameBounds.x;
this.last.y = this.frameBounds.y;
this.collisionMask.preUpdate();
};
GameObject.prototype.update = /**
* Override this function to update your class's position and appearance.
*/
function () {
};
GameObject.prototype.postUpdate = /**
* Automatically called after update() by the game loop.
*/
function () {
if(this.moves) {
this.updateMotion();
}
if(this.worldBounds != null) {
if(this.outOfBoundsAction == GameObject.OUT_OF_BOUNDS_KILL) {
if(this.x < this.worldBounds.x || this.x > this.worldBounds.right || this.y < this.worldBounds.y || this.y > this.worldBounds.bottom) {
this.kill();
}
} else {
if(this.x < this.worldBounds.x) {
this.x = this.worldBounds.x;
} else if(this.x > this.worldBounds.right) {
this.x = this.worldBounds.right;
}
if(this.y < this.worldBounds.y) {
this.y = this.worldBounds.y;
} else if(this.y > this.worldBounds.bottom) {
this.y = this.worldBounds.bottom;
}
}
}
this.collisionMask.update();
if(this.inputEnabled) {
this.updateInput();
}
this.wasTouching = this.touching;
this.touching = Phaser.Collision.NONE;
};
GameObject.prototype.updateInput = /**
* Update input.
*/
function () {
};
GameObject.prototype.updateMotion = /**
* Internal function for updating the position and speed of this object.
*/
function () {
var delta;
var velocityDelta;
velocityDelta = (this._game.motion.computeVelocity(this.angularVelocity, this.angularAcceleration, this.angularDrag, this.maxAngular) - this.angularVelocity) / 2;
this.angularVelocity += velocityDelta;
this._angle += this.angularVelocity * this._game.time.elapsed;
this.angularVelocity += velocityDelta;
velocityDelta = (this._game.motion.computeVelocity(this.velocity.x, this.acceleration.x, this.drag.x, this.maxVelocity.x) - this.velocity.x) / 2;
this.velocity.x += velocityDelta;
delta = this.velocity.x * this._game.time.elapsed;
this.velocity.x += velocityDelta;
this.frameBounds.x += delta;
velocityDelta = (this._game.motion.computeVelocity(this.velocity.y, this.acceleration.y, this.drag.y, this.maxVelocity.y) - this.velocity.y) / 2;
this.velocity.y += velocityDelta;
delta = this.velocity.y * this._game.time.elapsed;
this.velocity.y += velocityDelta;
this.frameBounds.y += delta;
};
GameObject.prototype.overlaps = /**
* Checks to see if some GameObject
overlaps this GameObject
or Group
.
* If the group has a LOT of things in it, it might be faster to use Collision.overlaps()
.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param objectOrGroup {object} The object or group being tested.
* @param inScreenSpace {boolean} Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether or not the objects overlap this.
*/
function (objectOrGroup, inScreenSpace, camera) {
if (typeof inScreenSpace === "undefined") { inScreenSpace = false; }
if (typeof camera === "undefined") { camera = null; }
if(objectOrGroup.isGroup) {
var results = false;
var i = 0;
var members = objectOrGroup.members;
while(i < length) {
if(this.overlaps(members[i++], inScreenSpace, camera)) {
results = true;
}
}
return results;
}
if(!inScreenSpace) {
return (objectOrGroup.x + objectOrGroup.width > this.x) && (objectOrGroup.x < this.x + this.width) && (objectOrGroup.y + objectOrGroup.height > this.y) && (objectOrGroup.y < this.y + this.height);
}
if(camera == null) {
camera = this._game.camera;
}
var objectScreenPos = objectOrGroup.getScreenXY(null, camera);
this.getScreenXY(this._point, camera);
return (objectScreenPos.x + objectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) && (objectScreenPos.y + objectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
};
GameObject.prototype.overlapsAt = /**
* Checks to see if this GameObject
were located at the given position, would it overlap the GameObject
or Group
?
* This is distinct from overlapsPoint(), which just checks that point, rather than taking the object's size numbero account.
* WARNING: Currently tilemaps do NOT support screen space overlap checks!
*
* @param X {number} The X position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param Y {number} The Y position you want to check. Pretends this object (the caller, not the parameter) is located here.
* @param objectOrGroup {object} The object or group being tested.
* @param inScreenSpace {boolean} Whether to take scroll factors numbero account when checking for overlap. Default is false, or "only compare in world space."
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether or not the two objects overlap.
*/
function (X, Y, objectOrGroup, inScreenSpace, camera) {
if (typeof inScreenSpace === "undefined") { inScreenSpace = false; }
if (typeof camera === "undefined") { camera = null; }
if(objectOrGroup.isGroup) {
var results = false;
var basic;
var i = 0;
var members = objectOrGroup.members;
while(i < length) {
if(this.overlapsAt(X, Y, members[i++], inScreenSpace, camera)) {
results = true;
}
}
return results;
}
if(!inScreenSpace) {
return (objectOrGroup.x + objectOrGroup.width > X) && (objectOrGroup.x < X + this.width) && (objectOrGroup.y + objectOrGroup.height > Y) && (objectOrGroup.y < Y + this.height);
}
if(camera == null) {
camera = this._game.camera;
}
var objectScreenPos = objectOrGroup.getScreenXY(null, Phaser.Camera);
this._point.x = X - camera.scroll.x * this.scrollFactor.x//copied from getScreenXY()
;
this._point.y = Y - camera.scroll.y * this.scrollFactor.y;
this._point.x += (this._point.x > 0) ? 0.0000001 : -0.0000001;
this._point.y += (this._point.y > 0) ? 0.0000001 : -0.0000001;
return (objectScreenPos.x + objectOrGroup.width > this._point.x) && (objectScreenPos.x < this._point.x + this.width) && (objectScreenPos.y + objectOrGroup.height > this._point.y) && (objectScreenPos.y < this._point.y + this.height);
};
GameObject.prototype.overlapsPoint = /**
* Checks to see if a point in 2D world space overlaps this GameObject
.
*
* @param point {Point} The point in world space you want to check.
* @param inScreenSpace {boolean} Whether to take scroll factors into account when checking for overlap.
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return Whether or not the point overlaps this object.
*/
function (point, inScreenSpace, camera) {
if (typeof inScreenSpace === "undefined") { inScreenSpace = false; }
if (typeof camera === "undefined") { camera = null; }
if(!inScreenSpace) {
return (point.x > this.x) && (point.x < this.x + this.width) && (point.y > this.y) && (point.y < this.y + this.height);
}
if(camera == null) {
camera = this._game.camera;
}
var X = point.x - camera.scroll.x;
var Y = point.y - camera.scroll.y;
this.getScreenXY(this._point, camera);
return (X > this._point.x) && (X < this._point.x + this.width) && (Y > this._point.y) && (Y < this._point.y + this.height);
};
GameObject.prototype.onScreen = /**
* Check and see if this object is currently on screen.
*
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {boolean} Whether the object is on screen or not.
*/
function (camera) {
if (typeof camera === "undefined") { camera = null; }
if(camera == null) {
camera = this._game.camera;
}
this.getScreenXY(this._point, camera);
return (this._point.x + this.width > 0) && (this._point.x < camera.width) && (this._point.y + this.height > 0) && (this._point.y < camera.height);
};
GameObject.prototype.getScreenXY = /**
* Call this to figure out the on-screen position of the object.
*
* @param point {Point} Takes a MicroPoint
object and assigns the post-scrolled X and Y values of this object to it.
* @param camera {Camera} Specify which game camera you want. If null getScreenXY() will just grab the first global camera.
*
* @return {MicroPoint} The MicroPoint
you passed in, or a new Point
if you didn't pass one, containing the screen X and Y position of this object.
*/
function (point, camera) {
if (typeof point === "undefined") { point = null; }
if (typeof camera === "undefined") { camera = null; }
if(point == null) {
point = new Phaser.MicroPoint();
}
if(camera == null) {
camera = this._game.camera;
}
point.x = this.x - camera.scroll.x * this.scrollFactor.x;
point.y = this.y - camera.scroll.y * this.scrollFactor.y;
point.x += (point.x > 0) ? 0.0000001 : -0.0000001;
point.y += (point.y > 0) ? 0.0000001 : -0.0000001;
return point;
};
Object.defineProperty(GameObject.prototype, "solid", {
get: /**
* Whether the object collides or not. For more control over what directions
* the object will collide from, use collision constants (like LEFT, FLOOR, etc)
* to set the value of allowCollisions directly.
*/
function () {
return (this.allowCollisions & Phaser.Collision.ANY) > Phaser.Collision.NONE;
},
set: function (value) {
if(value) {
this.allowCollisions = Phaser.Collision.ANY;
} else {
this.allowCollisions = Phaser.Collision.NONE;
}
},
enumerable: true,
configurable: true
});
GameObject.prototype.getMidpoint = /**
* Retrieve the midpoint of this object in world coordinates.
*
* @param point {Point} Allows you to pass in an existing Point
object if you're so inclined. Otherwise a new one is created.
*
* @return {MicroPoint} A Point
object containing the midpoint of this object in world coordinates.
*/
function (point) {
if (typeof point === "undefined") { point = null; }
if(point == null) {
point = new Phaser.MicroPoint();
}
point.copyFrom(this.frameBounds.center);
return point;
};
GameObject.prototype.reset = /**
* Handy for reviving game objects.
* Resets their existence flags and position.
*
* @param x {number} The new X position of this object.
* @param y {number} The new Y position of this object.
*/
function (x, y) {
this.revive();
this.touching = Phaser.Collision.NONE;
this.wasTouching = Phaser.Collision.NONE;
this.x = x;
this.y = y;
this.last.x = x;
this.last.y = y;
this.velocity.x = 0;
this.velocity.y = 0;
};
GameObject.prototype.isTouching = /**
* Handy for checking if this object is touching a particular surface.
* For slightly better performance you can just & the value directly into touching
.
* However, this method is good for readability and accessibility.
*
* @param Direction {number} Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @return {boolean} Whether the object is touching an object in (any of) the specified direction(s) this frame.
*/
function (direction) {
return (this.touching & direction) > Phaser.Collision.NONE;
};
GameObject.prototype.justTouched = /**
* Handy function for checking if this object just landed on a particular surface.
*
* @param Direction {number} Any of the collision flags (e.g. LEFT, FLOOR, etc).
*
* @returns {boolean} Whether the object just landed on any specicied surfaces.
*/
function (direction) {
return ((this.touching & direction) > Phaser.Collision.NONE) && ((this.wasTouching & direction) <= Phaser.Collision.NONE);
};
GameObject.prototype.hurt = /**
* Reduces the "health" variable of this sprite by the amount specified in Damage.
* Calls kill() if health drops to or below zero.
*
* @param Damage {number} How much health to take away (use a negative number to give a health bonus).
*/
function (damage) {
this.health = this.health - damage;
if(this.health <= 0) {
this.kill();
}
};
GameObject.prototype.setBounds = /**
* Set the world bounds that this GameObject can exist within. By default a GameObject can exist anywhere
* in the world. But by setting the bounds (which are given in world dimensions, not screen dimensions)
* it can be stopped from leaving the world, or a section of it.
*
* @param x {number} x position of the bound
* @param y {number} y position of the bound
* @param width {number} width of its bound
* @param height {number} height of its bound
*/
function (x, y, width, height) {
this.worldBounds = new Phaser.Quad(x, y, width, height);
};
GameObject.prototype.setBoundsFromWorld = /**
* Set the world bounds that this GameObject can exist within based on the size of the current game world.
*
* @param action {number} The action to take if the object hits the world bounds, either OUT_OF_BOUNDS_KILL or OUT_OF_BOUNDS_STOP
*/
function (action) {
if (typeof action === "undefined") { action = GameObject.OUT_OF_BOUNDS_STOP; }
this.setBounds(this._game.world.bounds.x, this._game.world.bounds.y, this._game.world.bounds.width, this._game.world.bounds.height);
this.outOfBoundsAction = action;
};
GameObject.prototype.hideFromCamera = /**
* If you do not wish this object to be visible to a specific camera, pass the camera here.
*
* @param camera {Camera} The specific camera.
*/
function (camera) {
if(this.cameraBlacklist.indexOf(camera.ID) == -1) {
this.cameraBlacklist.push(camera.ID);
}
};
GameObject.prototype.showToCamera = /**
* Make this object only visible to a specific camera.
*
* @param camera {Camera} The camera you wish it to be visible.
*/
function (camera) {
if(this.cameraBlacklist.indexOf(camera.ID) !== -1) {
this.cameraBlacklist.slice(this.cameraBlacklist.indexOf(camera.ID), 1);
}
};
GameObject.prototype.clearCameraList = /**
* This clears the camera black list, making the GameObject visible to all cameras.
*/
function () {
this.cameraBlacklist.length = 0;
};
GameObject.prototype.destroy = /**
* Clean up memory.
*/
function () {
};
GameObject.prototype.setPosition = function (x, y) {
this.x = x;
this.y = y;
};
Object.defineProperty(GameObject.prototype, "x", {
get: function () {
return this.frameBounds.x;
},
set: function (value) {
this.frameBounds.x = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GameObject.prototype, "y", {
get: function () {
return this.frameBounds.y;
},
set: function (value) {
this.frameBounds.y = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GameObject.prototype, "rotation", {
get: function () {
return this._angle;
},
set: function (value) {
this._angle = this._game.math.wrap(value, 360, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GameObject.prototype, "angle", {
get: function () {
return this._angle;
},
set: function (value) {
this._angle = this._game.math.wrap(value, 360, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GameObject.prototype, "width", {
get: function () {
return this.frameBounds.width;
},
set: function (value) {
this.frameBounds.width = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GameObject.prototype, "height", {
get: function () {
return this.frameBounds.height;
},
set: function (value) {
this.frameBounds.height = value;
},
enumerable: true,
configurable: true
});
return GameObject;
})(Phaser.Basic);
Phaser.GameObject = GameObject;
})(Phaser || (Phaser = {}));
/// Sprite
.
*
* @param game {Phaser.Game} Current game instance.
* @param [x] {number} the initial x position of the sprite.
* @param [y] {number} the initial y position of the sprite.
* @param [key] {string} Key of the graphic you want to load for this sprite.
*/
function Sprite(game, x, y, key) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof key === "undefined") { key = null; }
_super.call(this, game, x, y);
/**
* Texture of this sprite is DynamicTexture? (default to false)
* @type {boolean}
*/
this._dynamicTexture = false;
// local rendering related temp vars to help avoid gc spikes
this._sx = 0;
this._sy = 0;
this._sw = 0;
this._sh = 0;
this._dx = 0;
this._dy = 0;
this._dw = 0;
this._dh = 0;
/**
* Render bound of this sprite for debugging? (default to false)
* @type {boolean}
*/
this.renderDebug = false;
/**
* Color of the Sprite when no image is present. Format is a css color string.
* @type {string}
*/
this.fillColor = 'rgb(255,255,255)';
/**
* Color of bound when render debug. (see renderDebug) Format is a css color string.
* @type {string}
*/
this.renderDebugColor = 'rgba(0,255,0,0.5)';
/**
* Color of points when render debug. (see renderDebug) Format is a css color string.
* @type {string}
*/
this.renderDebugPointColor = 'rgba(255,255,255,1)';
/**
* Flip the graphic horizontally? (defaults to false)
* @type {boolean}
*/
this.flipped = false;
this._texture = null;
this.animations = new Phaser.AnimationManager(this._game, this);
if(key !== null) {
this.cacheKey = key;
this.loadGraphic(key);
} else {
this.frameBounds.width = 16;
this.frameBounds.height = 16;
}
}
Sprite.prototype.loadGraphic = /**
* Load graphic for this sprite. (graphic can be SpriteSheet or Texture)
* @param key {string} Key of the graphic you want to load for this sprite.
* @param clearAnimations {boolean} If this Sprite has a set of animation data already loaded you can choose to keep or clear it with this boolean
* @return {Sprite} Sprite instance itself.
*/
function (key, clearAnimations) {
if (typeof clearAnimations === "undefined") { clearAnimations = true; }
if(clearAnimations && this.animations.frameData !== null) {
this.animations.destroy();
}
if(this._game.cache.getImage(key) !== null) {
if(this._game.cache.isSpriteSheet(key) == false) {
this._texture = this._game.cache.getImage(key);
this.frameBounds.width = this._texture.width;
this.frameBounds.height = this._texture.height;
this.collisionMask.width = this._texture.width;
this.collisionMask.height = this._texture.height;
} else {
this._texture = this._game.cache.getImage(key);
this.animations.loadFrameData(this._game.cache.getFrameData(key));
this.collisionMask.width = this.animations.currentFrame.width;
this.collisionMask.height = this.animations.currentFrame.height;
}
this._dynamicTexture = false;
}
return this;
};
Sprite.prototype.loadDynamicTexture = /**
* Load a DynamicTexture as its texture.
* @param texture {DynamicTexture} The texture object to be used by this sprite.
* @return {Sprite} Sprite instance itself.
*/
function (texture) {
this._texture = texture;
this.frameBounds.width = this._texture.width;
this.frameBounds.height = this._texture.height;
this._dynamicTexture = true;
return this;
};
Sprite.prototype.makeGraphic = /**
* This function creates a flat colored square image dynamically.
* @param width {number} The width of the sprite you want to generate.
* @param height {number} The height of the sprite you want to generate.
* @param [color] {number} specifies the color of the generated block. (format is 0xAARRGGBB)
* @return {Sprite} Sprite instance itself.
*/
function (width, height, color) {
if (typeof color === "undefined") { color = 'rgb(255,255,255)'; }
this._texture = null;
this.width = width;
this.height = height;
this.fillColor = color;
this._dynamicTexture = false;
return this;
};
Sprite.prototype.inCamera = /**
* Check whether this object is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
function (camera) {
// Object fixed in place regardless of the camera scrolling? Then it's always visible
if(this.scrollFactor.x == 0 && this.scrollFactor.y == 0) {
return true;
}
// Otherwise, if it's scrolling perfectly in sync with the camera (1 to 1) then it's a simple bounds check on world coordinates
if(this.scrollFactor.x == 1 && this.scrollFactor.y == 1) {
return camera.intersects(this.frameBounds, this.frameBounds.length);
} else {
// Else apply the offsets
this._dx = (this.frameBounds.x - camera.x) * this.scrollFactor.x;
this._dy = (this.frameBounds.y - camera.y) * this.scrollFactor.y;
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
}
};
Sprite.prototype.postUpdate = /**
* Automatically called after update() by the game loop, this function just updates animations.
*/
function () {
this.animations.update();
_super.prototype.postUpdate.call(this);
};
Object.defineProperty(Sprite.prototype, "frame", {
get: function () {
return this.animations.frame;
},
set: function (value) {
this.animations.frame = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Sprite.prototype, "frameName", {
get: function () {
return this.animations.frameName;
},
set: function (value) {
this.animations.frameName = value;
},
enumerable: true,
configurable: true
});
Sprite.prototype.render = /**
* Render this sprite to specific camera. Called by game loop after update().
* @param camera {Camera} Camera this sprite will be rendered to.
* @cameraOffsetX {number} X offset to the camera.
* @cameraOffsetY {number} Y offset to the camera.
* @return {boolean} Return false if not rendered, otherwise return true.
*/
function (camera, cameraOffsetX, cameraOffsetY) {
// Render checks
if(this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView) == false) {
return false;
}
// Alpha
if(this.alpha !== 1) {
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._sx = 0;
this._sy = 0;
this._sw = this.frameBounds.width;
this._sh = this.frameBounds.height;
this._dx = (cameraOffsetX * this.scrollFactor.x) + this.frameBounds.topLeft.x - (camera.worldView.x * this.scrollFactor.x);
this._dy = (cameraOffsetY * this.scrollFactor.y) + this.frameBounds.topLeft.y - (camera.worldView.y * this.scrollFactor.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
if(this.align == Phaser.GameObject.ALIGN_TOP_CENTER) {
this._dx -= this.frameBounds.halfWidth * this.scale.x;
} else if(this.align == Phaser.GameObject.ALIGN_TOP_RIGHT) {
this._dx -= this.frameBounds.width * this.scale.x;
} else if(this.align == Phaser.GameObject.ALIGN_CENTER_LEFT) {
this._dy -= this.frameBounds.halfHeight * this.scale.y;
} else if(this.align == Phaser.GameObject.ALIGN_CENTER) {
this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
} else if(this.align == Phaser.GameObject.ALIGN_CENTER_RIGHT) {
this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.frameBounds.halfHeight * this.scale.y;
} else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_LEFT) {
this._dy -= this.frameBounds.height * this.scale.y;
} else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_CENTER) {
this._dx -= this.frameBounds.halfWidth * this.scale.x;
this._dy -= this.frameBounds.height * this.scale.y;
} else if(this.align == Phaser.GameObject.ALIGN_BOTTOM_RIGHT) {
this._dx -= this.frameBounds.width * this.scale.x;
this._dy -= this.frameBounds.height * this.scale.y;
}
if(this._dynamicTexture == false && this.animations.currentFrame !== null) {
this._sx = this.animations.currentFrame.x;
this._sy = this.animations.currentFrame.y;
if(this.animations.currentFrame.trimmed) {
this._dx += this.animations.currentFrame.spriteSourceSizeX;
this._dy += this.animations.currentFrame.spriteSourceSizeY;
}
}
// Apply camera difference
if(this.scrollFactor.x !== 1 || this.scrollFactor.y !== 1) {
//this._dx -= (camera.worldView.x * this.scrollFactor.x);
//this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
// Rotation - needs to work from origin point really, but for now from center
if(this.angle !== 0 || this.rotationOffset !== 0 || this.flipped == true) {
this.context.save();
this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if(this.renderRotation == true && (this.angle !== 0 || this.rotationOffset !== 0)) {
this.context.rotate((this.rotationOffset + this.angle) * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
if(this.flipped == true) {
this.context.scale(-1, 1);
}
}
this._sx = Math.round(this._sx);
this._sy = Math.round(this._sy);
this._sw = Math.round(this._sw);
this._sh = Math.round(this._sh);
this._dx = Math.round(this._dx);
this._dy = Math.round(this._dy);
this._dw = Math.round(this._dw);
this._dh = Math.round(this._dh);
if(this._texture != null) {
if(this._dynamicTexture) {
this.context.drawImage(this._texture.canvas, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh);
// Destination Height (always same as Source Height unless scaled)
} else {
this.context.drawImage(this._texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh);
// Destination Height (always same as Source Height unless scaled)
}
} else {
this.context.fillStyle = this.fillColor;
this.context.fillRect(this._dx, this._dy, this._dw, this._dh);
}
if(this.flipped === true || this.rotation !== 0 || this.rotationOffset !== 0) {
//this.context.translate(0, 0);
this.context.restore();
}
if(this.renderDebug) {
//this.renderBounds(camera, cameraOffsetX, cameraOffsetY);
this.collisionMask.render(camera, cameraOffsetX, cameraOffsetY);
}
if(globalAlpha > -1) {
this.context.globalAlpha = globalAlpha;
}
return true;
};
Sprite.prototype.renderBounds = /**
* Renders the bounding box around this Sprite and the contact points. Useful for visually debugging.
* @param camera {Camera} Camera the bound will be rendered to.
* @param cameraOffsetX {number} X offset of bound to the camera.
* @param cameraOffsetY {number} Y offset of bound to the camera.
*/
function (camera, cameraOffsetX, cameraOffsetY) {
//this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
//this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._dx = cameraOffsetX + (this.collisionMask.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.collisionMask.y - camera.worldView.y);
this.context.fillStyle = this.renderDebugColor;
this.context.fillRect(this._dx, this._dy, this.collisionMask.width, this.collisionMask.height);
//this.context.fillStyle = this.renderDebugPointColor;
//var hw = this.frameBounds.halfWidth * this.scale.x;
//var hh = this.frameBounds.halfHeight * this.scale.y;
//var sw = (this.frameBounds.width * this.scale.x) - 1;
//var sh = (this.frameBounds.height * this.scale.y) - 1;
//this.context.fillRect(this._dx, this._dy, 1, 1); // top left
//this.context.fillRect(this._dx + hw, this._dy, 1, 1); // top center
//this.context.fillRect(this._dx + sw, this._dy, 1, 1); // top right
//this.context.fillRect(this._dx, this._dy + hh, 1, 1); // left center
//this.context.fillRect(this._dx + hw, this._dy + hh, 1, 1); // center
//this.context.fillRect(this._dx + sw, this._dy + hh, 1, 1); // right center
//this.context.fillRect(this._dx, this._dy + sh, 1, 1); // bottom left
//this.context.fillRect(this._dx + hw, this._dy + sh, 1, 1); // bottom center
//this.context.fillRect(this._dx + sw, this._dy + sh, 1, 1); // bottom right
};
Sprite.prototype.renderDebugInfo = /**
* Render debug infos. (including name, bounds info, position and some other properties)
* @param x {number} X position of the debug info to be rendered.
* @param y {number} Y position of the debug info to be rendered.
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
*/
function (x, y, color) {
if (typeof color === "undefined") { color = 'rgb(255,255,255)'; }
this.context.fillStyle = color;
this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
this.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
this.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
};
return Sprite;
})(Phaser.GameObject);
Phaser.Sprite = Sprite;
})(Phaser || (Phaser = {}));
/// Animation
.
*
* @param parent {Sprite} Owner sprite of this animation.
* @param frameData {FrameData} The FrameData object contains animation data.
* @param name {string} Unique name of this animation.
* @param frames {number[]/string[]} An array of numbers or strings indicating what frames to play in what order.
* @param delay {number} Time between frames in ms.
* @param looped {boolean} Whether or not the animation is looped or just plays once.
*/
function Animation(game, parent, frameData, name, frames, delay, looped) {
this._game = game;
this._parent = parent;
this._frames = frames;
this._frameData = frameData;
this.name = name;
this.delay = 1000 / delay;
this.looped = looped;
this.isFinished = false;
this.isPlaying = false;
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
}
Object.defineProperty(Animation.prototype, "frameTotal", {
get: function () {
return this._frames.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Animation.prototype, "frame", {
get: function () {
if(this.currentFrame !== null) {
return this.currentFrame.index;
} else {
return this._frameIndex;
}
},
set: function (value) {
this.currentFrame = this._frameData.getFrame(value);
if(this.currentFrame !== null) {
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = value;
}
},
enumerable: true,
configurable: true
});
Animation.prototype.play = /**
* Play this animation.
* @param frameRate {number} FrameRate you want to specify instead of using default.
* @param loop {boolean} Whether or not the animation is looped or just plays once.
*/
function (frameRate, loop) {
if (typeof frameRate === "undefined") { frameRate = null; }
if(frameRate !== null) {
this.delay = 1000 / frameRate;
}
if(loop !== undefined) {
this.looped = loop;
}
this.isPlaying = true;
this.isFinished = false;
this._timeLastFrame = this._game.time.now;
this._timeNextFrame = this._game.time.now + this.delay;
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
};
Animation.prototype.restart = /**
* Play this animation from the first frame.
*/
function () {
this.isPlaying = true;
this.isFinished = false;
this._timeLastFrame = this._game.time.now;
this._timeNextFrame = this._game.time.now + this.delay;
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
};
Animation.prototype.stop = /**
* Stop playing animation and set it finished.
*/
function () {
this.isPlaying = false;
this.isFinished = true;
};
Animation.prototype.update = /**
* Update animation frames.
*/
function () {
if(this.isPlaying == true && this._game.time.now >= this._timeNextFrame) {
this._frameIndex++;
if(this._frameIndex == this._frames.length) {
if(this.looped) {
this._frameIndex = 0;
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
} else {
this.onComplete();
}
} else {
this.currentFrame = this._frameData.getFrame(this._frames[this._frameIndex]);
}
this._timeLastFrame = this._game.time.now;
this._timeNextFrame = this._game.time.now + this.delay;
return true;
}
return false;
};
Animation.prototype.destroy = /**
* Clean up animation memory.
*/
function () {
this._game = null;
this._parent = null;
this._frames = null;
this._frameData = null;
this.currentFrame = null;
this.isPlaying = false;
};
Animation.prototype.onComplete = /**
* Animation complete callback method.
*/
function () {
this.isPlaying = false;
this.isFinished = true;
// callback
};
return Animation;
})();
Phaser.Animation = Animation;
})(Phaser || (Phaser = {}));
/// Frame
with specific position, size and name.
*
* @param x {number} X position within the image to cut from.
* @param y {number} Y position within the image to cut from.
* @param width {number} Width of the frame.
* @param height {number} Height of the frame.
* @param name {string} Name of this frame.
*/
function Frame(x, y, width, height, name) {
/**
* Useful for Texture Atlas files. (is set to the filename value)
*/
this.name = '';
/**
* Rotated? (not yet implemented)
*/
this.rotated = false;
/**
* Either cw or ccw, rotation is always 90 degrees.
*/
this.rotationDirection = 'cw';
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.name = name;
this.rotated = false;
this.trimmed = false;
}
Frame.prototype.setRotation = /**
* Set rotation of this frame. (Not yet supported!)
*/
function (rotated, rotationDirection) {
// Not yet supported
};
Frame.prototype.setTrim = /**
* Set trim of the frame.
* @param trimmed {boolean} Whether this frame trimmed or not.
* @param actualWidth {number} Actual width of this frame.
* @param actualHeight {number} Actual height of this frame.
* @param destX {number} Destiny x position.
* @param destY {number} Destiny y position.
* @param destWidth {number} Destiny draw width.
* @param destHeight {number} Destiny draw height.
*/
function (trimmed, actualWidth, actualHeight, destX, destY, destWidth, destHeight) {
this.trimmed = trimmed;
this.sourceSizeW = actualWidth;
this.sourceSizeH = actualHeight;
this.spriteSourceSizeX = destX;
this.spriteSourceSizeY = destY;
this.spriteSourceSizeW = destWidth;
this.spriteSourceSizeH = destHeight;
};
return Frame;
})();
Phaser.Frame = Frame;
})(Phaser || (Phaser = {}));
/// AnimationManager
.
*
* @param parent {Sprite} Owner sprite of this manager.
*/
function AnimationManager(game, parent) {
/**
* Data contains animation frames.
* @type {FrameData}
*/
this._frameData = null;
/**
* Keeps track of the current frame of animation.
*/
this.currentFrame = null;
this._game = game;
this._parent = parent;
this._anims = {
};
}
AnimationManager.prototype.loadFrameData = /**
* Load animation frame data.
* @param frameData Data to be loaded.
*/
function (frameData) {
this._frameData = frameData;
this.frame = 0;
};
AnimationManager.prototype.add = /**
* Add a new animation.
* @param name {string} What this animation should be called (e.g. "run").
* @param frames {any[]} An array of numbers/strings indicating what frames to play in what order (e.g. [1, 2, 3] or ['run0', 'run1', run2]).
* @param frameRate {number} The speed in frames per second that the animation should play at (e.g. 60 fps).
* @param loop {boolean} Whether or not the animation is looped or just plays once.
* @param useNumericIndex {boolean} Use number indexes instead of string indexes?
* @return {Animation} The Animation that was created
*/
function (name, frames, frameRate, loop, useNumericIndex) {
if (typeof frames === "undefined") { frames = null; }
if (typeof frameRate === "undefined") { frameRate = 60; }
if (typeof loop === "undefined") { loop = false; }
if (typeof useNumericIndex === "undefined") { useNumericIndex = true; }
if(this._frameData == null) {
return;
}
if(frames == null) {
frames = this._frameData.getFrameIndexes();
} else {
if(this.validateFrames(frames, useNumericIndex) == false) {
throw Error('Invalid frames given to Animation ' + name);
return;
}
}
if(useNumericIndex == false) {
frames = this._frameData.getFrameIndexesByName(frames);
}
this._anims[name] = new Phaser.Animation(this._game, this._parent, this._frameData, name, frames, frameRate, loop);
this.currentAnim = this._anims[name];
this.currentFrame = this.currentAnim.currentFrame;
return this._anims[name];
};
AnimationManager.prototype.validateFrames = /**
* Check whether the frames is valid.
* @param frames {any[]} Frames to be validated.
* @param useNumericIndex {boolean} Does these frames use number indexes or string indexes?
* @return {boolean} True if they're valid, otherwise return false.
*/
function (frames, useNumericIndex) {
for(var i = 0; i < frames.length; i++) {
if(useNumericIndex == true) {
if(frames[i] > this._frameData.total) {
return false;
}
} else {
if(this._frameData.checkFrameName(frames[i]) == false) {
return false;
}
}
}
return true;
};
AnimationManager.prototype.play = /**
* Play animation with specific name.
* @param name {string} The string name of the animation you want to play.
* @param frameRate {number} FrameRate you want to specify instead of using default.
* @param loop {boolean} Whether or not the animation is looped or just plays once.
*/
function (name, frameRate, loop) {
if (typeof frameRate === "undefined") { frameRate = null; }
if(this._anims[name]) {
if(this.currentAnim == this._anims[name]) {
if(this.currentAnim.isPlaying == false) {
this.currentAnim.play(frameRate, loop);
}
} else {
this.currentAnim = this._anims[name];
this.currentAnim.play(frameRate, loop);
}
}
};
AnimationManager.prototype.stop = /**
* Stop animation by name.
* Current animation will be automatically set to the stopped one.
*/
function (name) {
if(this._anims[name]) {
this.currentAnim = this._anims[name];
this.currentAnim.stop();
}
};
AnimationManager.prototype.update = /**
* Update animation and parent sprite's bounds.
*/
function () {
if(this.currentAnim && this.currentAnim.update() == true) {
this.currentFrame = this.currentAnim.currentFrame;
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
}
};
Object.defineProperty(AnimationManager.prototype, "frameData", {
get: function () {
return this._frameData;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AnimationManager.prototype, "frameTotal", {
get: function () {
if(this._frameData) {
return this._frameData.total;
} else {
return -1;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(AnimationManager.prototype, "frame", {
get: function () {
return this._frameIndex;
},
set: function (value) {
if(this._frameData.getFrame(value) !== null) {
this.currentFrame = this._frameData.getFrame(value);
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(AnimationManager.prototype, "frameName", {
get: function () {
return this.currentFrame.name;
},
set: function (value) {
if(this._frameData.getFrameByName(value) !== null) {
this.currentFrame = this._frameData.getFrameByName(value);
this._parent.frameBounds.width = this.currentFrame.width;
this._parent.frameBounds.height = this.currentFrame.height;
this._frameIndex = this.currentFrame.index;
}
},
enumerable: true,
configurable: true
});
AnimationManager.prototype.destroy = /**
* Removes all related references
*/
function () {
this._anims = {
};
this._frameData = null;
this._frameIndex = 0;
this.currentAnim = null;
this.currentFrame = null;
};
return AnimationManager;
})();
Phaser.AnimationManager = AnimationManager;
})(Phaser || (Phaser = {}));
/// Camera
with position and size.
*
* @param x {number} X Position of the created camera.
* @param y {number} y Position of the created camera.
* @param width {number} Width of the created camera.
* @param height {number} Height of the created camera.
*/
function CameraManager(game, x, y, width, height) {
/**
* Local helper stores index of next created camera.
*/
this._cameraInstance = 0;
this._game = game;
this._cameras = [];
this.current = this.addCamera(x, y, width, height);
}
CameraManager.prototype.getAll = /**
* Get all the cameras.
*
* @returns {Camera[]} An array contains all the cameras.
*/
function () {
return this._cameras;
};
CameraManager.prototype.update = /**
* Update cameras.
*/
function () {
this._cameras.forEach(function (camera) {
return camera.update();
});
};
CameraManager.prototype.render = /**
* Render cameras.
*/
function () {
this._cameras.forEach(function (camera) {
return camera.render();
});
};
CameraManager.prototype.addCamera = /**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
function (x, y, width, height) {
var newCam = new Phaser.Camera(this._game, this._cameraInstance, x, y, width, height);
this._cameras.push(newCam);
this._cameraInstance++;
return newCam;
};
CameraManager.prototype.removeCamera = /**
* Remove a new camera with its id.
*
* @param id {number} ID of the camera you want to remove.
* @returns {boolean} True if successfully removed the camera, otherwise return false.
*/
function (id) {
for(var c = 0; c < this._cameras.length; c++) {
if(this._cameras[c].ID == id) {
if(this.current.ID === this._cameras[c].ID) {
this.current = null;
}
this._cameras.splice(c, 1);
return true;
}
}
return false;
};
CameraManager.prototype.destroy = /**
* Clean up memory.
*/
function () {
this._cameras.length = 0;
this.current = this.addCamera(0, 0, this._game.stage.width, this._game.stage.height);
};
return CameraManager;
})();
Phaser.CameraManager = CameraManager;
})(Phaser || (Phaser = {}));
/// object
and next
to null
.
*/
function LinkedList() {
this.object = null;
this.next = null;
}
LinkedList.prototype.destroy = /**
* Clean up memory.
*/
function () {
this.object = null;
if(this.next != null) {
this.next.destroy();
}
this.next = null;
};
return LinkedList;
})();
Phaser.LinkedList = LinkedList;
})(Phaser || (Phaser = {}));
/// myFunction(Object1:GameObject,Object2:GameObject)
that is called whenever two objects are found to overlap in world space, and either no processCallback is specified, or the processCallback returns true.
* @param {Function} processCallback A function with the form myFunction(Object1:GameObject,Object2:GameObject):bool
that is called whenever two objects are found to overlap in world space. The notifyCallback is only called if this function returns true. See GameObject.separate().
* @param context The context in which the callbacks will be called
*/
function (objectOrGroup1, objectOrGroup2, notifyCallback, processCallback, context) {
if (typeof objectOrGroup2 === "undefined") { objectOrGroup2 = null; }
if (typeof notifyCallback === "undefined") { notifyCallback = null; }
if (typeof processCallback === "undefined") { processCallback = null; }
if (typeof context === "undefined") { context = null; }
this.add(objectOrGroup1, QuadTree.A_LIST);
if(objectOrGroup2 != null) {
this.add(objectOrGroup2, QuadTree.B_LIST);
QuadTree._useBothLists = true;
} else {
QuadTree._useBothLists = false;
}
QuadTree._notifyCallback = notifyCallback;
QuadTree._processingCallback = processCallback;
QuadTree._callbackContext = context;
};
QuadTree.prototype.add = /**
* Call this function to add an object to the root of the tree.
* This function will recursively add all group members, but
* not the groups themselves.
*
* @param {Basic} objectOrGroup GameObjects are just added, Groups are recursed and their applicable members added accordingly.
* @param {Number} list A uint
flag indicating the list to which you want to add the objects. Options are QuadTree.A_LIST
and QuadTree.B_LIST
.
*/
function (objectOrGroup, list) {
QuadTree._list = list;
if(objectOrGroup.isGroup == true) {
var i = 0;
var basic;
var members = objectOrGroup['members'];
var l = objectOrGroup['length'];
while(i < l) {
basic = members[i++];
if((basic != null) && basic.exists) {
if(basic.isGroup) {
this.add(basic, list);
} else {
QuadTree._object = basic;
if(QuadTree._object.exists && QuadTree._object.allowCollisions) {
this.addObject();
}
}
}
}
} else {
QuadTree._object = objectOrGroup;
if(QuadTree._object.exists && QuadTree._object.allowCollisions) {
this.addObject();
}
}
};
QuadTree.prototype.addObject = /**
* Internal function for recursively navigating and creating the tree
* while adding objects to the appropriate nodes.
*/
function () {
//If this quad (not its children) lies entirely inside this object, add it here
if(!this._canSubdivide || ((this._leftEdge >= QuadTree._object.collisionMask.x) && (this._rightEdge <= QuadTree._object.collisionMask.right) && (this._topEdge >= QuadTree._object.collisionMask.y) && (this._bottomEdge <= QuadTree._object.collisionMask.bottom))) {
this.addToList();
return;
}
//See if the selected object fits completely inside any of the quadrants
if((QuadTree._object.collisionMask.x > this._leftEdge) && (QuadTree._object.collisionMask.right < this._midpointX)) {
if((QuadTree._object.collisionMask.y > this._topEdge) && (QuadTree._object.collisionMask.bottom < this._midpointY)) {
if(this._northWestTree == null) {
this._northWestTree = new QuadTree(this._leftEdge, this._topEdge, this._halfWidth, this._halfHeight, this);
}
this._northWestTree.addObject();
return;
}
if((QuadTree._object.collisionMask.y > this._midpointY) && (QuadTree._object.collisionMask.bottom < this._bottomEdge)) {
if(this._southWestTree == null) {
this._southWestTree = new QuadTree(this._leftEdge, this._midpointY, this._halfWidth, this._halfHeight, this);
}
this._southWestTree.addObject();
return;
}
}
if((QuadTree._object.collisionMask.x > this._midpointX) && (QuadTree._object.collisionMask.right < this._rightEdge)) {
if((QuadTree._object.collisionMask.y > this._topEdge) && (QuadTree._object.collisionMask.bottom < this._midpointY)) {
if(this._northEastTree == null) {
this._northEastTree = new QuadTree(this._midpointX, this._topEdge, this._halfWidth, this._halfHeight, this);
}
this._northEastTree.addObject();
return;
}
if((QuadTree._object.collisionMask.y > this._midpointY) && (QuadTree._object.collisionMask.bottom < this._bottomEdge)) {
if(this._southEastTree == null) {
this._southEastTree = new QuadTree(this._midpointX, this._midpointY, this._halfWidth, this._halfHeight, this);
}
this._southEastTree.addObject();
return;
}
}
//If it wasn't completely contained we have to check out the partial overlaps
if((QuadTree._object.collisionMask.right > this._leftEdge) && (QuadTree._object.collisionMask.x < this._midpointX) && (QuadTree._object.collisionMask.bottom > this._topEdge) && (QuadTree._object.collisionMask.y < this._midpointY)) {
if(this._northWestTree == null) {
this._northWestTree = new QuadTree(this._leftEdge, this._topEdge, this._halfWidth, this._halfHeight, this);
}
this._northWestTree.addObject();
}
if((QuadTree._object.collisionMask.right > this._midpointX) && (QuadTree._object.collisionMask.x < this._rightEdge) && (QuadTree._object.collisionMask.bottom > this._topEdge) && (QuadTree._object.collisionMask.y < this._midpointY)) {
if(this._northEastTree == null) {
this._northEastTree = new QuadTree(this._midpointX, this._topEdge, this._halfWidth, this._halfHeight, this);
}
this._northEastTree.addObject();
}
if((QuadTree._object.collisionMask.right > this._midpointX) && (QuadTree._object.collisionMask.x < this._rightEdge) && (QuadTree._object.collisionMask.bottom > this._midpointY) && (QuadTree._object.collisionMask.y < this._bottomEdge)) {
if(this._southEastTree == null) {
this._southEastTree = new QuadTree(this._midpointX, this._midpointY, this._halfWidth, this._halfHeight, this);
}
this._southEastTree.addObject();
}
if((QuadTree._object.collisionMask.right > this._leftEdge) && (QuadTree._object.collisionMask.x < this._midpointX) && (QuadTree._object.collisionMask.bottom > this._midpointY) && (QuadTree._object.collisionMask.y < this._bottomEdge)) {
if(this._southWestTree == null) {
this._southWestTree = new QuadTree(this._leftEdge, this._midpointY, this._halfWidth, this._halfHeight, this);
}
this._southWestTree.addObject();
}
};
QuadTree.prototype.addToList = /**
* Internal function for recursively adding objects to leaf lists.
*/
function () {
var ot;
if(QuadTree._list == QuadTree.A_LIST) {
if(this._tailA.object != null) {
ot = this._tailA;
this._tailA = new Phaser.LinkedList();
ot.next = this._tailA;
}
this._tailA.object = QuadTree._object;
} else {
if(this._tailB.object != null) {
ot = this._tailB;
this._tailB = new Phaser.LinkedList();
ot.next = this._tailB;
}
this._tailB.object = QuadTree._object;
}
if(!this._canSubdivide) {
return;
}
if(this._northWestTree != null) {
this._northWestTree.addToList();
}
if(this._northEastTree != null) {
this._northEastTree.addToList();
}
if(this._southEastTree != null) {
this._southEastTree.addToList();
}
if(this._southWestTree != null) {
this._southWestTree.addToList();
}
};
QuadTree.prototype.execute = /**
* QuadTree
's other main function. Call this after adding objects
* using QuadTree.load()
to compare the objects that you loaded.
*
* @return {Boolean} Whether or not any overlaps were found.
*/
function () {
var overlapProcessed = false;
var iterator;
if(this._headA.object != null) {
iterator = this._headA;
while(iterator != null) {
QuadTree._object = iterator.object;
if(QuadTree._useBothLists) {
QuadTree._iterator = this._headB;
} else {
QuadTree._iterator = iterator.next;
}
if(QuadTree._object.exists && (QuadTree._object.allowCollisions > 0) && (QuadTree._iterator != null) && (QuadTree._iterator.object != null) && QuadTree._iterator.object.exists && this.overlapNode()) {
overlapProcessed = true;
}
iterator = iterator.next;
}
}
//Advance through the tree by calling overlap on each child
if((this._northWestTree != null) && this._northWestTree.execute()) {
overlapProcessed = true;
}
if((this._northEastTree != null) && this._northEastTree.execute()) {
overlapProcessed = true;
}
if((this._southEastTree != null) && this._southEastTree.execute()) {
overlapProcessed = true;
}
if((this._southWestTree != null) && this._southWestTree.execute()) {
overlapProcessed = true;
}
return overlapProcessed;
};
QuadTree.prototype.overlapNode = /**
* A private for comparing an object against the contents of a node.
*
* @return {Boolean} Whether or not any overlaps were found.
*/
function () {
//Walk the list and check for overlaps
var overlapProcessed = false;
var checkObject;
while(QuadTree._iterator != null) {
if(!QuadTree._object.exists || (QuadTree._object.allowCollisions <= 0)) {
break;
}
checkObject = QuadTree._iterator.object;
if((QuadTree._object === checkObject) || !checkObject.exists || (checkObject.allowCollisions <= 0)) {
QuadTree._iterator = QuadTree._iterator.next;
continue;
}
if(QuadTree._object.collisionMask.checkHullIntersection(checkObject.collisionMask)) {
//Execute callback functions if they exist
if((QuadTree._processingCallback == null) || QuadTree._processingCallback(QuadTree._object, checkObject)) {
overlapProcessed = true;
}
if(overlapProcessed && (QuadTree._notifyCallback != null)) {
if(QuadTree._callbackContext !== null) {
QuadTree._notifyCallback.call(QuadTree._callbackContext, QuadTree._object, checkObject);
} else {
QuadTree._notifyCallback(QuadTree._object, checkObject);
}
}
}
QuadTree._iterator = QuadTree._iterator.next;
}
return overlapProcessed;
};
return QuadTree;
})(Phaser.Rectangle);
Phaser.QuadTree = QuadTree;
})(Phaser || (Phaser = {}));
/// DynamicTexture
.
*
* @param game {Phaser.Game} Current game instance.
* @param width {number} Init width of this texture.
* @param height {number} Init height of this texture.
*/
function DynamicTexture(game, width, height) {
this._sx = 0;
this._sy = 0;
this._sw = 0;
this._sh = 0;
this._dx = 0;
this._dy = 0;
this._dw = 0;
this._dh = 0;
this._game = game;
this.canvas = document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
this.context = this.canvas.getContext('2d');
this.bounds = new Phaser.Rectangle(0, 0, width, height);
}
DynamicTexture.prototype.getPixel = /**
* Get a color of a specific pixel.
* @param x {number} X position of the pixel in this texture.
* @param y {number} Y position of the pixel in this texture.
* @return {number} A native color value integer (format: 0xRRGGBB)
*/
function (x, y) {
//r = imageData.data[0];
//g = imageData.data[1];
//b = imageData.data[2];
//a = imageData.data[3];
var imageData = this.context.getImageData(x, y, 1, 1);
return this.getColor(imageData.data[0], imageData.data[1], imageData.data[2]);
};
DynamicTexture.prototype.getPixel32 = /**
* Get a color of a specific pixel (including alpha value).
* @param x {number} X position of the pixel in this texture.
* @param y {number} Y position of the pixel in this texture.
* @return A native color value integer (format: 0xAARRGGBB)
*/
function (x, y) {
var imageData = this.context.getImageData(x, y, 1, 1);
return this.getColor32(imageData.data[3], imageData.data[0], imageData.data[1], imageData.data[2]);
};
DynamicTexture.prototype.getPixels = /**
* Get pixels in array in a specific rectangle.
* @param rect {Rectangle} The specific rectangle.
* @returns {array} CanvasPixelArray.
*/
function (rect) {
return this.context.getImageData(rect.x, rect.y, rect.width, rect.height);
};
DynamicTexture.prototype.setPixel = /**
* Set color of a specific pixel.
* @param x {number} X position of the target pixel.
* @param y {number} Y position of the target pixel.
* @param color {number} Native integer with color value. (format: 0xRRGGBB)
*/
function (x, y, color) {
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
};
DynamicTexture.prototype.setPixel32 = /**
* Set color (with alpha) of a specific pixel.
* @param x {number} X position of the target pixel.
* @param y {number} Y position of the target pixel.
* @param color {number} Native integer with color value. (format: 0xAARRGGBB)
*/
function (x, y, color) {
this.context.fillStyle = color;
this.context.fillRect(x, y, 1, 1);
};
DynamicTexture.prototype.setPixels = /**
* Set image data to a specific rectangle.
* @param rect {Rectangle} Target rectangle.
* @param input {object} Source image data.
*/
function (rect, input) {
this.context.putImageData(input, rect.x, rect.y);
};
DynamicTexture.prototype.fillRect = /**
* Fill a given rectangle with specific color.
* @param rect {Rectangle} Target rectangle you want to fill.
* @param color {number} A native number with color value. (format: 0xRRGGBB)
*/
function (rect, color) {
this.context.fillStyle = color;
this.context.fillRect(rect.x, rect.y, rect.width, rect.height);
};
DynamicTexture.prototype.pasteImage = /**
*
*/
function (key, frame, destX, destY, destWidth, destHeight) {
if (typeof frame === "undefined") { frame = -1; }
if (typeof destX === "undefined") { destX = 0; }
if (typeof destY === "undefined") { destY = 0; }
if (typeof destWidth === "undefined") { destWidth = null; }
if (typeof destHeight === "undefined") { destHeight = null; }
var texture = null;
var frameData;
this._sx = 0;
this._sy = 0;
this._dx = destX;
this._dy = destY;
// TODO - Load a frame from a sprite sheet, otherwise we'll draw the whole lot
if(frame > -1) {
//if (this._game.cache.isSpriteSheet(key))
//{
// texture = this._game.cache.getImage(key);
//this.animations.loadFrameData(this._game.cache.getFrameData(key));
//}
} else {
texture = this._game.cache.getImage(key);
this._sw = texture.width;
this._sh = texture.height;
this._dw = texture.width;
this._dh = texture.height;
}
if(destWidth !== null) {
this._dw = destWidth;
}
if(destHeight !== null) {
this._dh = destHeight;
}
if(texture != null) {
this.context.drawImage(texture, // Source Image
this._sx, // Source X (location within the source image)
this._sy, // Source Y
this._sw, // Source Width
this._sh, // Source Height
this._dx, // Destination X (where on the canvas it'll be drawn)
this._dy, // Destination Y
this._dw, // Destination Width (always same as Source Width unless scaled)
this._dh);
// Destination Height (always same as Source Height unless scaled)
}
};
DynamicTexture.prototype.copyPixels = // TODO - Add in support for: alphaBitmapData: BitmapData = null, alphaPoint: Point = null, mergeAlpha: bool = false
/**
* Copy pixel from another DynamicTexture to this texture.
* @param sourceTexture {DynamicTexture} Source texture object.
* @param sourceRect {Rectangle} The specific region rectangle to be copied to this in the source.
* @param destPoint {Point} Top-left point the target image data will be paste at.
*/
function (sourceTexture, sourceRect, destPoint) {
// Swap for drawImage if the sourceRect is the same size as the sourceTexture to avoid a costly getImageData call
if(sourceRect.equals(this.bounds) == true) {
this.context.drawImage(sourceTexture.canvas, destPoint.x, destPoint.y);
} else {
this.context.putImageData(sourceTexture.getPixels(sourceRect), destPoint.x, destPoint.y);
}
};
DynamicTexture.prototype.assignCanvasToGameObjects = /**
* Given an array of GameObjects it will update each of them so that their canvas/contexts reference this DynamicTexture
* @param objects {Array} An array of GameObjects, or objects that inherit from it such as Sprites
*/
function (objects) {
for(var i = 0; i < objects.length; i++) {
objects[i].canvas = this.canvas;
objects[i].context = this.context;
}
};
DynamicTexture.prototype.clear = /**
* Clear the whole canvas.
*/
function () {
this.context.clearRect(0, 0, this.bounds.width, this.bounds.height);
};
DynamicTexture.prototype.render = /**
* Renders this DynamicTexture to the Stage at the given x/y coordinates
*
* @param x {number} The X coordinate to render on the stage to (given in screen coordinates, not world)
* @param y {number} The Y coordinate to render on the stage to (given in screen coordinates, not world)
*/
function (x, y) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
this._game.stage.context.drawImage(this.canvas, x, y);
};
Object.defineProperty(DynamicTexture.prototype, "width", {
get: function () {
return this.bounds.width;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DynamicTexture.prototype, "height", {
get: function () {
return this.bounds.height;
},
enumerable: true,
configurable: true
});
DynamicTexture.prototype.getColor32 = /**
* Given an alpha and 3 color values this will return an integer representation of it
*
* @param alpha {number} The Alpha value (between 0 and 255)
* @param red {number} The Red channel value (between 0 and 255)
* @param green {number} The Green channel value (between 0 and 255)
* @param blue {number} The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xAARRGGBB)
*/
function (alpha, red, green, blue) {
return alpha << 24 | red << 16 | green << 8 | blue;
};
DynamicTexture.prototype.getColor = /**
* Given 3 color values this will return an integer representation of it
*
* @param red {number} The Red channel value (between 0 and 255)
* @param green {number} The Green channel value (between 0 and 255)
* @param blue {number} The Blue channel value (between 0 and 255)
*
* @return A native color value integer (format: 0xRRGGBB)
*/
function (red, green, blue) {
return red << 16 | green << 8 | blue;
};
return DynamicTexture;
})();
Phaser.DynamicTexture = DynamicTexture;
})(Phaser || (Phaser = {}));
/// * Returns true or false based on the chance value (default 50%). For example if you wanted a player to have a 30% chance * of getting a bonus, call chanceRoll(30) - true means the chance passed, false means it failed. *
* @param chance The chance of receiving the value. A number between 0 and 100 (effectively 0% to 100%) * @return true if the roll passed, or false */ function (chance) { if (typeof chance === "undefined") { chance = 50; } if(chance <= 0) { return false; } else if(chance >= 100) { return true; } else { if(Math.random() * 100 >= chance) { return false; } else { return true; } } }; GameMath.prototype.maxAdd = /** * Adds the given amount to the value, but never lets the value go over the specified maximum * * @param value The value to add the amount to * @param amount The amount to add to the value * @param max The maximum the value is allowed to be * @return The new value */ function (value, amount, max) { value += amount; if(value > max) { value = max; } return value; }; GameMath.prototype.minSub = /** * Subtracts the given amount from the value, but never lets the value go below the specified minimum * * @param value The base value * @param amount The amount to subtract from the base value * @param min The minimum the value is allowed to be * @return The new value */ function (value, amount, min) { value -= amount; if(value < min) { value = min; } return value; }; GameMath.prototype.wrapValue = /** * Adds value to amount and ensures that the result always stays between 0 and max, by wrapping the value around. *Values must be positive integers, and are passed through Math.abs
* * @param value The value to add the amount to * @param amount The amount to add to the value * @param max The maximum the value is allowed to be * @return The wrapped value */ function (value, amount, max) { var diff; value = Math.abs(value); amount = Math.abs(amount); max = Math.abs(max); diff = (value + amount) % max; return diff; }; GameMath.prototype.randomSign = /** * Randomly returns either a 1 or -1 * * @return 1 or -1 */ function () { return (Math.random() > 0.5) ? 1 : -1; }; GameMath.prototype.isOdd = /** * Returns true if the number given is odd. * * @param n The number to check * * @return True if the given number is odd. False if the given number is even. */ function (n) { if(n & 1) { return true; } else { return false; } }; GameMath.prototype.isEven = /** * Returns true if the number given is even. * * @param n The number to check * * @return True if the given number is even. False if the given number is odd. */ function (n) { if(n & 1) { return false; } else { return true; } }; GameMath.prototype.wrapAngle = /** * Keeps an angle value between -180 and +180Number
between 0 and 1.
*/
function () {
return this.globalSeed = this.srand(this.globalSeed);
};
GameMath.prototype.srand = /**
* Generates a random number based on the seed provided.
*
* @param Seed A number between 0 and 1, used to generate a predictable random number (very optional).
*
* @return A Number
between 0 and 1.
*/
function (Seed) {
return ((69621 * (Seed * 0x7FFFFFFF)) % 0x7FFFFFFF) / 0x7FFFFFFF;
};
GameMath.prototype.getRandom = /**
* Fetch a random entry from the given array.
* Will return null if random selection is missing, or array has no entries.
*
* @param objects An array of objects.
* @param startIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param length Optional restriction on the number of values you want to randomly select from.
*
* @return The random object that was selected.
*/
function (objects, startIndex, length) {
if (typeof startIndex === "undefined") { startIndex = 0; }
if (typeof length === "undefined") { length = 0; }
if(objects != null) {
var l = length;
if((l == 0) || (l > objects.length - startIndex)) {
l = objects.length - startIndex;
}
if(l > 0) {
return objects[startIndex + Math.floor(Math.random() * l)];
}
}
return null;
};
GameMath.prototype.floor = /**
* Round down to the next whole number. E.g. floor(1.7) == 1, and floor(-2.7) == -2.
*
* @param Value Any number.
*
* @return The rounded value of that number.
*/
function (Value) {
var n = Value | 0;
return (Value > 0) ? (n) : ((n != Value) ? (n - 1) : (n));
};
GameMath.prototype.ceil = /**
* Round up to the next whole number. E.g. ceil(1.3) == 2, and ceil(-2.3) == -3.
*
* @param Value Any number.
*
* @return The rounded value of that number.
*/
function (Value) {
var n = Value | 0;
return (Value > 0) ? ((n != Value) ? (n + 1) : (n)) : (n);
};
GameMath.prototype.sinCosGenerator = /**
* Generate a sine and cosine table simultaneously and extremely quickly. Based on research by Franky of scene.at
* * The parameters allow you to specify the length, amplitude and frequency of the wave. Once you have called this function * you should get the results via getSinTable() and getCosTable(). This generator is fast enough to be used in real-time. *
* @param length The length of the wave * @param sinAmplitude The amplitude to apply to the sine table (default 1.0) if you need values between say -+ 125 then give 125 as the value * @param cosAmplitude The amplitude to apply to the cosine table (default 1.0) if you need values between say -+ 125 then give 125 as the value * @param frequency The frequency of the sine and cosine table data * @return Returns the sine table * @see getSinTable * @see getCosTable */ function (length, sinAmplitude, cosAmplitude, frequency) { if (typeof sinAmplitude === "undefined") { sinAmplitude = 1.0; } if (typeof cosAmplitude === "undefined") { cosAmplitude = 1.0; } if (typeof frequency === "undefined") { frequency = 1.0; } var sin = sinAmplitude; var cos = cosAmplitude; var frq = frequency * Math.PI / length; this.cosTable = []; this.sinTable = []; for(var c = 0; c < length; c++) { cos -= sin * frq; sin += cos * frq; this.cosTable[c] = cos; this.sinTable[c] = sin; } return this.sinTable; }; GameMath.prototype.shiftSinTable = /** * Shifts through the sin table data by one value and returns it. * This effectively moves the position of the data from the start to the end of the table. * @return The sin value. */ function () { if(this.sinTable) { var s = this.sinTable.shift(); this.sinTable.push(s); return s; } }; GameMath.prototype.shiftCosTable = /** * Shifts through the cos table data by one value and returns it. * This effectively moves the position of the data from the start to the end of the table. * @return The cos value. */ function () { if(this.cosTable) { var s = this.cosTable.shift(); this.cosTable.push(s); return s; } }; GameMath.prototype.vectorLength = /** * Finds the length of the given vector * * @param dx * @param dy * * @return */ function (dx, dy) { return Math.sqrt(dx * dx + dy * dy); }; GameMath.prototype.dotProduct = /** * Finds the dot product value of two vectors * * @param ax Vector X * @param ay Vector Y * @param bx Vector X * @param by Vector Y * * @return Dot product */ function (ax, ay, bx, by) { return ax * bx + ay * by; }; GameMath.prototype.shuffleArray = /** * Shuffles the data in the given array into a new order * @param array The array to shuffle * @return The array */ function (array) { for(var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; } return array; }; GameMath.distanceBetween = /** * Returns the distance from this Point object to the given Point object. * @method distanceFrom * @param {Point} target - The destination Point object. * @param {Boolean} round - Round the distance to the nearest integer (default false) * @return {Number} The distance between this Point object and the destination Point object. **/ function distanceBetween(x1, y1, x2, y2) { var dx = x1 - x2; var dy = y1 - y2; return Math.sqrt(dx * dx + dy * dy); }; GameMath.prototype.rotatePoint = /** * Rotates the point around the x/y coordinates given to the desired angle and distance * @param point {Object} Any object with exposed x and y properties * @param x {number} The x coordinate of the anchor point * @param y {number} The y coordinate of the anchor point * @param {Number} angle The angle in radians (unless asDegrees is true) to return the point from. * @param {Boolean} asDegrees Is the given angle in radians (false) or degrees (true)? * @param {Number} distance An optional distance constraint between the point and the anchor * @return The modified point object */ function (point, x1, y1, angle, asDegrees, distance) { if (typeof asDegrees === "undefined") { asDegrees = false; } if (typeof distance === "undefined") { distance = null; } if(asDegrees) { angle = angle * GameMath.DEG_TO_RAD; } // Get distance from origin to the point if(distance === null) { distance = Math.sqrt(((x1 - point.x) * (x1 - point.x)) + ((y1 - point.y) * (y1 - point.y))); } point.x = x1 + distance * Math.cos(angle); point.y = y1 + distance * Math.sin(angle); return point; }; return GameMath; })(); Phaser.GameMath = GameMath; })(Phaser || (Phaser = {})); ///Basic
subclass (Basic, GameObject, Sprite, etc) to the group.
* Group will try to replace a null member of the array first.
* Failing that, Group will add it to the end of the member array,
* assuming there is room for it, and doubling the size of the array if necessary.
*
* WARNING: If the group has a maxSize that has already been met, * the object will NOT be added to the group!
* * @param {Basic} Object The object you want to add to the group. * @return {Basic} The sameBasic
object that was passed in.
*/
function (Object) {
//Don't bother adding an object twice.
if(this.members.indexOf(Object) >= 0) {
return Object;
}
//First, look for a null entry where we can add the object.
var i = 0;
var l = this.members.length;
while(i < l) {
if(this.members[i] == null) {
this.members[i] = Object;
if(i >= this.length) {
this.length = i + 1;
}
return Object;
}
i++;
}
//Failing that, expand the array (if we can) and add the object.
if(this._maxSize > 0) {
if(this.members.length >= this._maxSize) {
return Object;
} else if(this.members.length * 2 <= this._maxSize) {
this.members.length *= 2;
} else {
this.members.length = this._maxSize;
}
} else {
this.members.length *= 2;
}
//If we made it this far, then we successfully grew the group,
//and we can go ahead and add the object at the first open slot.
this.members[i] = Object;
this.length = i + 1;
return Object;
};
Group.prototype.recycle = /**
* Recycling is designed to help you reuse game objects without always re-allocating or "newing" them.
*
* If you specified a maximum size for this group (like in Emitter), * then recycle will employ what we're calling "rotating" recycling. * Recycle() will first check to see if the group is at capacity yet. * If group is not yet at capacity, recycle() returns a new object. * If the group IS at capacity, then recycle() just returns the next object in line.
* *If you did NOT specify a maximum size for this group, * then recycle() will employ what we're calling "grow-style" recycling. * Recycle() will return either the first object with exists == false, * or, finding none, add a new object to the array, * doubling the size of the array if necessary.
* *WARNING: If this function needs to create a new object, * and no object class was provided, it will return null * instead of a valid object!
* * @param {class} ObjectClass The class type you want to recycle (e.g. Basic, EvilRobot, etc). Do NOT "new" the class in the parameter! * * @return {any} A reference to the object that was created. Don't forget to cast it back to the Class you want (e.g. myObject = myGroup.recycle(myObjectClass) as myObjectClass;). */ function (ObjectClass) { if (typeof ObjectClass === "undefined") { ObjectClass = null; } var basic; if(this._maxSize > 0) { if(this.length < this._maxSize) { if(ObjectClass == null) { return null; } return this.add(new ObjectClass(this._game)); } else { basic = this.members[this._marker++]; if(this._marker >= this._maxSize) { this._marker = 0; } return basic; } } else { basic = this.getFirstAvailable(ObjectClass); if(basic != null) { return basic; } if(ObjectClass == null) { return null; } return this.add(new ObjectClass(this._game)); } }; Group.prototype.remove = /** * Removes an object from the group. * * @param {Basic} object TheBasic
you want to remove.
* @param {boolean} splice Whether the object should be cut from the array entirely or not.
*
* @return {Basic} The removed object.
*/
function (object, splice) {
if (typeof splice === "undefined") { splice = false; }
var index = this.members.indexOf(object);
if((index < 0) || (index >= this.members.length)) {
return null;
}
if(splice) {
this.members.splice(index, 1);
this.length--;
} else {
this.members[index] = null;
}
return object;
};
Group.prototype.replace = /**
* Replaces an existing Basic
with a new one.
*
* @param {Basic} oldObject The object you want to replace.
* @param {Basic} newObject The new object you want to use instead.
*
* @return {Basic} The new object.
*/
function (oldObject, newObject) {
var index = this.members.indexOf(oldObject);
if((index < 0) || (index >= this.members.length)) {
return null;
}
this.members[index] = newObject;
return newObject;
};
Group.prototype.sort = /**
* Call this function to sort the group according to a particular value and order.
* For example, to sort game objects for Zelda-style overlaps you might call
* myGroup.sort("y",Group.ASCENDING)
at the bottom of your
* State.update()
override. To sort all existing objects after
* a big explosion or bomb attack, you might call myGroup.sort("exists",Group.DESCENDING)
.
*
* @param {string} index The string
name of the member variable you want to sort on. Default value is "y".
* @param {number} order A Group
constant that defines the sort order. Possible values are Group.ASCENDING
and Group.DESCENDING
. Default value is Group.ASCENDING
.
*/
function (index, order) {
if (typeof index === "undefined") { index = "y"; }
if (typeof order === "undefined") { order = Group.ASCENDING; }
this._sortIndex = index;
this._sortOrder = order;
this.members.sort(this.sortHandler);
};
Group.prototype.setAll = /**
* Go through and set the specified variable to the specified value on all members of the group.
*
* @param {string} VariableName The string representation of the variable name you want to modify, for example "visible" or "scrollFactor".
* @param {Object} Value The value you want to assign to that variable.
* @param {boolean} Recurse Default value is true, meaning if setAll()
encounters a member that is a group, it will call setAll()
on that group rather than modifying its variable.
*/
function (VariableName, Value, Recurse) {
if (typeof Recurse === "undefined") { Recurse = true; }
var basic;
var i = 0;
while(i < length) {
basic = this.members[i++];
if(basic != null) {
if(Recurse && (basic.isGroup == true)) {
basic['setAll'](VariableName, Value, Recurse);
} else {
basic[VariableName] = Value;
}
}
}
};
Group.prototype.callAll = /**
* Go through and call the specified function on all members of the group.
* Currently only works on functions that have no required parameters.
*
* @param {string} FunctionName The string representation of the function you want to call on each object, for example "kill()" or "init()".
* @param {boolean} Recurse Default value is true, meaning if callAll()
encounters a member that is a group, it will call callAll()
on that group rather than calling the group's function.
*/
function (FunctionName, Recurse) {
if (typeof Recurse === "undefined") { Recurse = true; }
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if(basic != null) {
if(Recurse && (basic.isGroup == true)) {
basic['callAll'](FunctionName, Recurse);
} else {
basic[FunctionName]();
}
}
}
};
Group.prototype.forEach = /**
* @param {function} callback
* @param {boolean} recursive
*/
function (callback, recursive) {
if (typeof recursive === "undefined") { recursive = false; }
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if(basic != null) {
if(recursive && (basic.isGroup == true)) {
basic.forEach(callback, true);
} else {
callback.call(this, basic);
}
}
}
};
Group.prototype.forEachAlive = /**
* @param {any} context
* @param {function} callback
* @param {boolean} recursive
*/
function (context, callback, recursive) {
if (typeof recursive === "undefined") { recursive = false; }
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if(basic != null && basic.alive) {
if(recursive && (basic.isGroup == true)) {
basic.forEachAlive(context, callback, true);
} else {
callback.call(context, basic);
}
}
}
};
Group.prototype.getFirstAvailable = /**
* Call this function to retrieve the first object with exists == false in the group.
* This is handy for recycling in general, e.g. respawning enemies.
*
* @param {any} [ObjectClass] An optional parameter that lets you narrow the results to instances of this particular class.
*
* @return {any} A Basic
currently flagged as not existing.
*/
function (ObjectClass) {
if (typeof ObjectClass === "undefined") { ObjectClass = null; }
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if((basic != null) && !basic.exists && ((ObjectClass == null) || (typeof basic === ObjectClass))) {
return basic;
}
}
return null;
};
Group.prototype.getFirstNull = /**
* Call this function to retrieve the first index set to 'null'.
* Returns -1 if no index stores a null object.
*
* @return {number} An int
indicating the first null slot in the group.
*/
function () {
var basic;
var i = 0;
var l = this.members.length;
while(i < l) {
if(this.members[i] == null) {
return i;
} else {
i++;
}
}
return -1;
};
Group.prototype.getFirstExtant = /**
* Call this function to retrieve the first object with exists == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return {Basic} A Basic
currently flagged as existing.
*/
function () {
var basic;
var i = 0;
while(i < length) {
basic = this.members[i++];
if((basic != null) && basic.exists) {
return basic;
}
}
return null;
};
Group.prototype.getFirstAlive = /**
* Call this function to retrieve the first object with dead == false in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return {Basic} A Basic
currently flagged as not dead.
*/
function () {
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if((basic != null) && basic.exists && basic.alive) {
return basic;
}
}
return null;
};
Group.prototype.getFirstDead = /**
* Call this function to retrieve the first object with dead == true in the group.
* This is handy for checking if everything's wiped out, or choosing a squad leader, etc.
*
* @return {Basic} A Basic
currently flagged as dead.
*/
function () {
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if((basic != null) && !basic.alive) {
return basic;
}
}
return null;
};
Group.prototype.countLiving = /**
* Call this function to find out how many members of the group are not dead.
*
* @return {number} The number of Basic
s flagged as not dead. Returns -1 if group is empty.
*/
function () {
var count = -1;
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if(basic != null) {
if(count < 0) {
count = 0;
}
if(basic.exists && basic.alive) {
count++;
}
}
}
return count;
};
Group.prototype.countDead = /**
* Call this function to find out how many members of the group are dead.
*
* @return {number} The number of Basic
s flagged as dead. Returns -1 if group is empty.
*/
function () {
var count = -1;
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if(basic != null) {
if(count < 0) {
count = 0;
}
if(!basic.alive) {
count++;
}
}
}
return count;
};
Group.prototype.getRandom = /**
* Returns a member at random from the group.
*
* @param {number} StartIndex Optional offset off the front of the array. Default value is 0, or the beginning of the array.
* @param {number} Length Optional restriction on the number of values you want to randomly select from.
*
* @return {Basic} A Basic
from the members list.
*/
function (StartIndex, Length) {
if (typeof StartIndex === "undefined") { StartIndex = 0; }
if (typeof Length === "undefined") { Length = 0; }
if(Length == 0) {
Length = this.length;
}
return this._game.math.getRandom(this.members, StartIndex, Length);
};
Group.prototype.clear = /**
* Remove all instances of Basic
subclass (Basic, Block, etc) from the list.
* WARNING: does not destroy() or kill() any of these objects!
*/
function () {
this.length = this.members.length = 0;
};
Group.prototype.kill = /**
* Calls kill on the group's members and then on the group itself.
*/
function () {
var basic;
var i = 0;
while(i < this.length) {
basic = this.members[i++];
if((basic != null) && basic.exists) {
basic.kill();
}
}
};
Group.prototype.sortHandler = /**
* Helper function for the sort process.
*
* @param {Basic} Obj1 The first object being sorted.
* @param {Basic} Obj2 The second object being sorted.
*
* @return {number} An integer value: -1 (Obj1 before Obj2), 0 (same), or 1 (Obj1 after Obj2).
*/
function (Obj1, Obj2) {
if(Obj1[this._sortIndex] < Obj2[this._sortIndex]) {
return this._sortOrder;
} else if(Obj1[this._sortIndex] > Obj2[this._sortIndex]) {
return -this._sortOrder;
}
return 0;
};
return Group;
})(Phaser.Basic);
Phaser.Group = Group;
})(Phaser || (Phaser = {}));
/// SoundManager
.
*/
function SoundManager(game) {
/**
* Reference to AudioContext instance.
*/
this._context = null;
this._game = game;
if(game.device.webaudio == true) {
if(!!window['AudioContext']) {
this._context = new window['AudioContext']();
} else if(!!window['webkitAudioContext']) {
this._context = new window['webkitAudioContext']();
}
if(this._context !== null) {
this._gainNode = this._context.createGainNode();
this._gainNode.connect(this._context.destination);
this._volume = 1;
}
}
}
SoundManager.prototype.mute = /**
* Mute sounds.
*/
function () {
this._gainNode.gain.value = 0;
};
SoundManager.prototype.unmute = /**
* Enable sounds.
*/
function () {
this._gainNode.gain.value = this._volume;
};
Object.defineProperty(SoundManager.prototype, "volume", {
get: function () {
return this._volume;
},
set: function (value) {
this._volume = value;
this._gainNode.gain.value = this._volume;
},
enumerable: true,
configurable: true
});
SoundManager.prototype.decode = /**
* Decode a sound with its assets key.
* @param key {string} Assets key of the sound to be decoded.
* @param callback {function} This will be invoked when finished decoding.
* @param [sound] {Sound} its bufer will be set to decoded data.
*/
function (key, callback, sound) {
if (typeof callback === "undefined") { callback = null; }
if (typeof sound === "undefined") { sound = null; }
var soundData = this._game.cache.getSound(key);
if(soundData) {
if(this._game.cache.isSoundDecoded(key) === false) {
var that = this;
this._context.decodeAudioData(soundData, function (buffer) {
that._game.cache.decodedSound(key, buffer);
if(sound) {
sound.setDecodedBuffer(buffer);
}
callback();
});
}
}
};
SoundManager.prototype.play = /**
* Play a sound with its assets key.
* @param key {string} Assets key of the sound you want to play.
* @param [volume] {number} volume of the sound you want to play.
* @param [loop] {boolean} loop when it finished playing? (Default to false)
* @return {Sound} The playing sound object.
*/
function (key, volume, loop) {
if (typeof volume === "undefined") { volume = 1; }
if (typeof loop === "undefined") { loop = false; }
if(this._context === null) {
return;
}
var soundData = this._game.cache.getSound(key);
if(soundData) {
// Does the sound need decoding?
if(this._game.cache.isSoundDecoded(key) === true) {
return new Phaser.Sound(this._context, this._gainNode, soundData, volume, loop);
} else {
var tempSound = new Phaser.Sound(this._context, this._gainNode, null, volume, loop);
// this is an async process, so we can return the Sound object anyway, it just won't be playing yet
this.decode(key, function () {
return tempSound.play();
}, tempSound);
return tempSound;
}
}
};
return SoundManager;
})();
Phaser.SoundManager = SoundManager;
})(Phaser || (Phaser = {}));
/**
* Phaser
*
* v0.9.6 - May 21st 2013
*
* A small and feature-packed 2D canvas game framework born from the firey pits of Flixel and Kiwi.
*
* Richard Davey (@photonstorm)
*
* Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel on which Phaser took a lot of inspiration.
*
* "If you want your children to be intelligent, read them fairy tales."
* "If you want them to be more intelligent, read them more fairy tales."
* -- Albert Einstein
*/
var Phaser;
(function (Phaser) {
Phaser.VERSION = 'Phaser version 0.9.6';
})(Phaser || (Phaser = {}));
/// BootScreen
with specific width and height.
*
* @param width {number} Screen canvas width.
* @param height {number} Screen canvas height.
*/
function BootScreen(game) {
/**
* Engine logo image data.
*/
this._logoData = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGgAAAAZCAYAAADdYmvFAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAstJREFUeNrsWlFuwjAMbavdZGcAcRm4AXzvCPuGG8BlEJxhZ+l4TJ48z3actGGthqUI1MaO/V6cmIT2/fW10eTt46NvKshtvDZlG31yfOL9a/ldU6x4IZ0GQs0gS217enMkJYr5ixXkYrFoVqtV1kDn8/n+KfXw/Hq9Nin7h8MhScB2u3Xtav2ivsNWrh7XLcWMYqA4eUZ1kj0MAifHJEeKFojWzyIH+rL/0Cwif2AX9nN1oQOgrTg8XcTFx+ScdEOJ4WBxXQ1EjRyrn0cOzzQLzFyQSQcgw/5Qkkr0JVEQpNIdhL4vm4DL5fLulNTHcy6Uxl4/6iMLiePx2KzX6/v30+n0aynUlrnSeNq2/VN9bgM4dFPdNPmsJnIg/PuQbJmLdFN3UNu0SzbyJ0GOWJVWZE/QMkY+owrqXxGEdZA37BVyX6lJTipT6J1lf7fbqc+xh8nYeIvikatP+PGW0nEJ4jOydHYOIcfKnmgWoZDQSIIeio4Sf1IthYWskCO4vqQ6lFYjl8tl9L1H67PZbMz3VO3t93uVXHofmUjReLyMwHi5eCb3ICwJj5ZU9nCg+SzUgPYyif+2epTk4pkkyDp+eXTlZu2BkUybEkklePZfK9lPuTnc07vbmt1bYulHBeNQgx18SsH4ni/cV2rSLtqNDNUH2JQ2SsXS57Y9PHlfumkwCdICt5rnkNdPjpMiIEWgRlAJSdF4SvCQMWj+VyfI0h8D/EgWSYKiJKXi8VrOhJUxaFiFCOKKUJAtR78k9eX4USLHXqLGXOIiWUT4Vj9JiP4W0io3VDz8AJXblNWQrOimLjIGy/9uLICH6mrVmFbxEFHauzmc0fGJJmPg/v+6D0oB7N2bj0FsNHtSWTQniWTR931QlHXvasDTHXLjqY0/1/8hSDxACD+lAGH8dKQbQk5N3TFtzDmLWutvV0+pL5FVoHvCNG35FGAAayS4KUoKC9QAAAAASUVORK5CYII=";
/**
* Background gradient effect color 1.
*/
this._color1 = {
r: 20,
g: 20,
b: 20
};
/**
* Background gradient effect color 2.
*/
this._color2 = {
r: 200,
g: 200,
b: 200
};
/**
* Fade effect tween.
* @type {Phaser.Tween}
*/
this._fade = null;
this._game = game;
this._logo = new Image();
this._logo.src = this._logoData;
}
BootScreen.prototype.update = /**
* Update color and fade.
*/
function () {
if(this._fade == null) {
this.colorCycle();
}
this._color1.r = Math.round(this._color1.r);
this._color1.g = Math.round(this._color1.g);
this._color1.b = Math.round(this._color1.b);
this._color2.r = Math.round(this._color2.r);
this._color2.g = Math.round(this._color2.g);
this._color2.b = Math.round(this._color2.b);
};
BootScreen.prototype.render = /**
* Render BootScreen.
*/
function () {
var grd = this._game.stage.context.createLinearGradient(0, 0, 0, this._game.stage.height);
grd.addColorStop(0, 'rgb(' + this._color1.r + ', ' + this._color1.g + ', ' + this._color1.b + ')');
grd.addColorStop(0.5, 'rgb(' + this._color2.r + ', ' + this._color2.g + ', ' + this._color2.b + ')');
grd.addColorStop(1, 'rgb(' + this._color1.r + ', ' + this._color1.g + ', ' + this._color1.b + ')');
this._game.stage.context.fillStyle = grd;
this._game.stage.context.fillRect(0, 0, this._game.stage.width, this._game.stage.height);
this._game.stage.context.shadowOffsetX = 0;
this._game.stage.context.shadowOffsetY = 0;
if(this._logo) {
this._game.stage.context.drawImage(this._logo, 32, 32);
}
this._game.stage.context.shadowColor = 'rgb(0,0,0)';
this._game.stage.context.shadowOffsetX = 1;
this._game.stage.context.shadowOffsetY = 1;
this._game.stage.context.shadowBlur = 0;
this._game.stage.context.fillStyle = 'rgb(255,255,255)';
this._game.stage.context.font = 'bold 18px Arial';
this._game.stage.context.textBaseline = 'top';
this._game.stage.context.fillText(Phaser.VERSION, 32, 64 + 32);
this._game.stage.context.fillText('Game Size: ' + this._game.stage.width + ' x ' + this._game.stage.height, 32, 64 + 64);
this._game.stage.context.fillText('www.photonstorm.com', 32, 64 + 96);
this._game.stage.context.font = '16px Arial';
this._game.stage.context.fillText('You are seeing this screen because you didn\'t specify any default', 32, 64 + 160);
this._game.stage.context.fillText('functions in the Game constructor or use Game.switchState()', 32, 64 + 184);
};
BootScreen.prototype.colorCycle = /**
* Start color fading cycle.
*/
function () {
this._fade = this._game.add.tween(this._color2);
this._fade.to({
r: Math.random() * 250,
g: Math.random() * 250,
b: Math.random() * 250
}, 3000, Phaser.Easing.Linear.None);
this._fade.onComplete.add(this.colorCycle, this);
this._fade.start();
};
return BootScreen;
})();
Phaser.BootScreen = BootScreen;
})(Phaser || (Phaser = {}));
/// PauseScreen
with specific width and height.
*
* @param width {number} Screen canvas width.
* @param height {number} Screen canvas height.
*/
function PauseScreen(game, width, height) {
this._game = game;
this._canvas = document.createElement('canvas');
this._canvas.width = width;
this._canvas.height = height;
this._context = this._canvas.getContext('2d');
}
PauseScreen.prototype.onPaused = /**
* Called when the game enters pause mode.
*/
function () {
// Take a grab of the current canvas to our temporary one
this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);
this._context.drawImage(this._game.stage.canvas, 0, 0);
this._color = {
r: 255,
g: 255,
b: 255
};
this.fadeOut();
};
PauseScreen.prototype.onResume = /**
* Called when the game resume from pause mode.
*/
function () {
this._fade.stop();
this._game.tweens.remove(this._fade);
};
PauseScreen.prototype.update = /**
* Update background color.
*/
function () {
this._color.r = Math.round(this._color.r);
this._color.g = Math.round(this._color.g);
this._color.b = Math.round(this._color.b);
};
PauseScreen.prototype.render = /**
* Render PauseScreen.
*/
function () {
this._game.stage.context.drawImage(this._canvas, 0, 0);
this._game.stage.context.fillStyle = 'rgba(0, 0, 0, 0.4)';
this._game.stage.context.fillRect(0, 0, this._game.stage.width, this._game.stage.height);
// Draw a 'play' arrow
var arrowWidth = Math.round(this._game.stage.width / 2);
var arrowHeight = Math.round(this._game.stage.height / 2);
var sx = this._game.stage.centerX - arrowWidth / 2;
var sy = this._game.stage.centerY - arrowHeight / 2;
this._game.stage.context.beginPath();
this._game.stage.context.moveTo(sx, sy);
this._game.stage.context.lineTo(sx, sy + arrowHeight);
this._game.stage.context.lineTo(sx + arrowWidth, this._game.stage.centerY);
this._game.stage.context.fillStyle = 'rgba(' + this._color.r + ', ' + this._color.g + ', ' + this._color.b + ', 0.8)';
this._game.stage.context.fill();
this._game.stage.context.closePath();
};
PauseScreen.prototype.fadeOut = /**
* Start fadeOut effect.
*/
function () {
this._fade = this._game.add.tween(this._color);
this._fade.to({
r: 50,
g: 50,
b: 50
}, 1000, Phaser.Easing.Linear.None);
this._fade.onComplete.add(this.fadeIn, this);
this._fade.start();
};
PauseScreen.prototype.fadeIn = /**
* Start fadeIn effect.
*/
function () {
this._fade = this._game.add.tween(this._color);
this._fade.to({
r: 255,
g: 255,
b: 255
}, 1000, Phaser.Easing.Linear.None);
this._fade.onComplete.add(this.fadeOut, this);
this._fade.start();
};
return PauseScreen;
})();
Phaser.PauseScreen = PauseScreen;
})(Phaser || (Phaser = {}));
/// Stage
with specific width and height.
*
* @param parent {number} ID of parent DOM element.
* @param width {number} Width of the stage.
* @param height {number} Height of the stage.
*/
function Stage(game, parent, width, height) {
var _this = this;
/**
* Background color of the stage (defaults to black)
* @type {string}
*/
this._bgColor = 'rgb(0,0,0)';
/**
* Clear the whole stage every frame? (Default to true)
* @type {boolean}
*/
this.clear = true;
/**
* Do not use pause screen when game is paused?
* (Default to false, aka always use PauseScreen)
* @type {boolean}
*/
this.disablePauseScreen = false;
/**
* Do not use boot screen when engine starts?
* (Default to false, aka always use BootScreen)
* @type {boolean}
*/
this.disableBootScreen = false;
this._game = game;
this.canvas = document.createElement('canvas');
this.canvas.width = width;
this.canvas.height = height;
if(document.getElementById(parent)) {
document.getElementById(parent).appendChild(this.canvas);
document.getElementById(parent).style.overflow = 'hidden';
} else {
document.body.appendChild(this.canvas);
}
// Consume default actions on the canvas
this.canvas.style.msTouchAction = 'none';
this.canvas.style['ms-touch-action'] = 'none';
this.canvas.style['touch-action'] = 'none';
this.canvas.style.backgroundColor = 'rgb(0,0,0)';
this.canvas.oncontextmenu = function (event) {
event.preventDefault();
};
this.context = this.canvas.getContext('2d');
this.offset = this.getOffset(this.canvas);
this.bounds = new Phaser.Quad(this.offset.x, this.offset.y, width, height);
this.aspectRatio = width / height;
this.scaleMode = Phaser.StageScaleMode.NO_SCALE;
this.scale = new Phaser.StageScaleMode(this._game);
this._bootScreen = new Phaser.BootScreen(this._game);
this._pauseScreen = new Phaser.PauseScreen(this._game, width, height);
document.addEventListener('visibilitychange', function (event) {
return _this.visibilityChange(event);
}, false);
document.addEventListener('webkitvisibilitychange', function (event) {
return _this.visibilityChange(event);
}, false);
window.onblur = function (event) {
return _this.visibilityChange(event);
};
window.onfocus = function (event) {
return _this.visibilityChange(event);
};
}
Stage.prototype.update = /**
* Update stage for rendering. This will handle scaling, clearing
* and PauseScreen/BootScreen updating and rendering.
*/
function () {
this.scale.update();
if(this.clear) {
// implement dirty rect? could take up more cpu time than it saves. needs benching.
this.context.clearRect(0, 0, this.width, this.height);
}
if(this._game.isRunning == false && this.disableBootScreen == false) {
this._bootScreen.update();
this._bootScreen.render();
}
if(this._game.paused == true && this.disablePauseScreen == false) {
this._pauseScreen.update();
this._pauseScreen.render();
}
};
Stage.prototype.visibilityChange = /**
* This method is called when the canvas elements visibility is changed.
*/
function (event) {
if(this.disablePauseScreen) {
return;
}
if(event.type == 'blur' || document['hidden'] == true || document['webkitHidden'] == true) {
if(this._game.paused == false) {
this.pauseGame();
}
} else {
if(this._game.paused == true) {
this.resumeGame();
}
}
};
Stage.prototype.pauseGame = function () {
this._pauseScreen.onPaused();
this.saveCanvasValues();
this._game.paused = true;
};
Stage.prototype.resumeGame = function () {
this._pauseScreen.onResume();
this.restoreCanvasValues();
this._game.paused = false;
};
Stage.prototype.getOffset = /**
* Get the DOM offset values of the given element
*/
function (element) {
var box = element.getBoundingClientRect();
var clientTop = element.clientTop || document.body.clientTop || 0;
var clientLeft = element.clientLeft || document.body.clientLeft || 0;
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
return new Phaser.MicroPoint(box.left + scrollLeft - clientLeft, box.top + scrollTop - clientTop);
};
Stage.prototype.saveCanvasValues = /**
* Save current canvas properties (strokeStyle, lineWidth and fillStyle) for later using.
*/
function () {
this.strokeStyle = this.context.strokeStyle;
this.lineWidth = this.context.lineWidth;
this.fillStyle = this.context.fillStyle;
};
Stage.prototype.restoreCanvasValues = /**
* Restore current canvas values (strokeStyle, lineWidth and fillStyle) with saved values.
*/
function () {
this.context.strokeStyle = this.strokeStyle;
this.context.lineWidth = this.lineWidth;
this.context.fillStyle = this.fillStyle;
};
Object.defineProperty(Stage.prototype, "backgroundColor", {
get: function () {
return this._bgColor;
},
set: function (color) {
this.canvas.style.backgroundColor = color;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "x", {
get: function () {
return this.bounds.x;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "y", {
get: function () {
return this.bounds.y;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "width", {
get: function () {
return this.bounds.width;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "height", {
get: function () {
return this.bounds.height;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "centerX", {
get: function () {
return this.bounds.halfWidth;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "centerY", {
get: function () {
return this.bounds.halfHeight;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "randomX", {
get: function () {
return Math.round(Math.random() * this.bounds.width);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Stage.prototype, "randomY", {
get: function () {
return Math.round(Math.random() * this.bounds.height);
},
enumerable: true,
configurable: true
});
return Stage;
})();
Phaser.Stage = Stage;
})(Phaser || (Phaser = {}));
/// Time
.
*
* @param game {Phaser.Game} Current game instance.
*/
function Time(game) {
/**
* Time scale factor.
* Set it to 0.5 for slow motion, to 2.0 makes game twice faster.
* @type {number}
*/
this.timeScale = 1.0;
/**
* Elapsed since last frame.
* @type {number}
*/
this.elapsed = 0;
/**
* Game time counter.
* @property time
* @type {number}
*/
this.time = 0;
/**
* Time of current frame.
* @property now
* @type {number}
*/
this.now = 0;
/**
* Elapsed time since last frame.
* @property delta
* @type {number}
*/
this.delta = 0;
/**
* Frames per second.
* @type {number}
*/
this.fps = 0;
/**
* Minimal fps.
* @type {number}
*/
this.fpsMin = 1000;
/**
* Maximal fps.
* @type {number}
*/
this.fpsMax = 0;
/**
* Mininal duration between 2 frames.
* @type {number}
*/
this.msMin = 1000;
/**
* Maximal duration between 2 frames.
* @type {number}
*/
this.msMax = 0;
/**
* How many frames in last second.
* @type {number}
*/
this.frames = 0;
/**
* Time of last second.
* @type {number}
*/
this._timeLastSecond = 0;
this._started = 0;
this._timeLastSecond = this._started;
this.time = this._started;
this._game = game;
}
Object.defineProperty(Time.prototype, "totalElapsedSeconds", {
get: /**
*
* @method totalElapsedSeconds
* @return {Number}
*/
function () {
return (this.now - this._started) * 0.001;
},
enumerable: true,
configurable: true
});
Time.prototype.update = /**
* Update clock and calculate the fps.
* This is called automatically by Game._raf
* @method update
* @param {number} raf The current timestamp, either performance.now or Date.now
*/
function (raf) {
this.now = raf// mark
;
//this.now = Date.now(); // mark
this.delta = this.now - this.time// elapsedMS
;
this.msMin = Math.min(this.msMin, this.delta);
this.msMax = Math.max(this.msMax, this.delta);
this.frames++;
if(this.now > this._timeLastSecond + 1000) {
this.fps = Math.round((this.frames * 1000) / (this.now - this._timeLastSecond));
this.fpsMin = Math.min(this.fpsMin, this.fps);
this.fpsMax = Math.max(this.fpsMax, this.fps);
this._timeLastSecond = this.now;
this.frames = 0;
}
this.time = this.now// _total
;
};
Time.prototype.elapsedSince = /**
* How long has passed since given time.
* @method elapsedSince
* @param {number} since The time you want to measure.
* @return {number} Duration between given time and now.
*/
function (since) {
return this.now - since;
};
Time.prototype.elapsedSecondsSince = /**
* How long has passed since give time (in seconds).
* @method elapsedSecondsSince
* @param {number} since The time you want to measure (in seconds).
* @return {number} Duration between given time and now (in seconds).
*/
function (since) {
return (this.now - since) * 0.001;
};
Time.prototype.reset = /**
* Set the start time to now.
* @method reset
*/
function () {
this._started = this.now;
};
return Time;
})();
Phaser.Time = Time;
})(Phaser || (Phaser = {}));
var Phaser;
(function (Phaser) {
/// Tween
.
*
* @param object {object} Target object will be affected by this tween.
* @param game {Phaser.Game} Current game instance.
*/
function Tween(object, game) {
/**
* Reference to the target object.
* @type {object}
*/
this._object = null;
this._pausedTime = 0;
/**
* Start values container.
* @type {object}
*/
this._valuesStart = {
};
/**
* End values container.
* @type {object}
*/
this._valuesEnd = {
};
/**
* How long this tween will perform.
* @type {number}
*/
this._duration = 1000;
this._delayTime = 0;
this._startTime = null;
/**
* Contains chained tweens.
* @type {Tweens[]}
*/
this._chainedTweens = [];
this._object = object;
this._game = game;
this._manager = this._game.tweens;
this._interpolationFunction = this._game.math.linearInterpolation;
this._easingFunction = Phaser.Easing.Linear.None;
this._chainedTweens = [];
this.onStart = new Phaser.Signal();
this.onUpdate = new Phaser.Signal();
this.onComplete = new Phaser.Signal();
}
Tween.prototype.to = /**
* Configure the Tween
* @param properties {object} Propertis you want to tween.
* @param [duration] {number} duration of this tween.
* @param [ease] {any} Easing function.
* @param [autoStart] {boolean} Whether this tween will start automatically or not.
* @param [delay] {number} delay before this tween will start, defaults to 0 (no delay)
* @return {Tween} Itself.
*/
function (properties, duration, ease, autoStart, delay) {
if (typeof duration === "undefined") { duration = 1000; }
if (typeof ease === "undefined") { ease = null; }
if (typeof autoStart === "undefined") { autoStart = false; }
if (typeof delay === "undefined") { delay = 0; }
this._duration = duration;
// If properties isn't an object this will fail, sanity check it here somehow?
this._valuesEnd = properties;
if(ease !== null) {
this._easingFunction = ease;
}
if(delay > 0) {
this._delayTime = delay;
}
if(autoStart === true) {
return this.start();
} else {
return this;
}
};
Tween.prototype.start = /**
* Start to tween.
*/
function () {
if(this._game === null || this._object === null) {
return;
}
this._manager.add(this);
this.onStart.dispatch(this._object);
this._startTime = this._game.time.now + this._delayTime;
for(var property in this._valuesEnd) {
// This prevents the interpolation of null values or of non-existing properties
if(this._object[property] === null || !(property in this._object)) {
throw Error('Phaser.Tween interpolation of null value of non-existing property');
continue;
}
// check if an Array was provided as property value
if(this._valuesEnd[property] instanceof Array) {
if(this._valuesEnd[property].length === 0) {
continue;
}
// create a local copy of the Array with the start value at the front
this._valuesEnd[property] = [
this._object[property]
].concat(this._valuesEnd[property]);
}
this._valuesStart[property] = this._object[property];
}
return this;
};
Tween.prototype.stop = /**
* Stop tweening.
*/
function () {
if(this._manager !== null) {
this._manager.remove(this);
}
this.onComplete.dispose();
return this;
};
Object.defineProperty(Tween.prototype, "parent", {
set: function (value) {
this._game = value;
this._manager = this._game.tweens;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tween.prototype, "delay", {
get: function () {
return this._delayTime;
},
set: function (amount) {
this._delayTime = amount;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tween.prototype, "easing", {
get: function () {
return this._easingFunction;
},
set: function (easing) {
this._easingFunction = easing;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tween.prototype, "interpolation", {
get: function () {
return this._interpolationFunction;
},
set: function (interpolation) {
this._interpolationFunction = interpolation;
},
enumerable: true,
configurable: true
});
Tween.prototype.chain = /**
* Add another chained tween, which will start automatically when the one before it completes.
* @param tween {Phaser.Tween} Tween object you want to chain with this.
* @return {Phaser.Tween} Itselfe.
*/
function (tween) {
this._chainedTweens.push(tween);
return this;
};
Tween.prototype.update = /**
* Update tweening.
* @param time {number} Current time from game clock.
* @return {boolean} Return false if this completed and no need to update, otherwise return true.
*/
function (time) {
if(this._game.paused == true) {
if(this._pausedTime == 0) {
this._pausedTime = time;
}
} else {
// Ok we aren't paused, but was there some time gained?
if(this._pausedTime > 0) {
this._startTime += (time - this._pausedTime);
this._pausedTime = 0;
}
}
if(time < this._startTime) {
return true;
}
var elapsed = (time - this._startTime) / this._duration;
elapsed = elapsed > 1 ? 1 : elapsed;
var value = this._easingFunction(elapsed);
for(var property in this._valuesStart) {
// Add checks for object, array, numeric up front
if(this._valuesEnd[property] instanceof Array) {
this._object[property] = this._interpolationFunction(this._valuesEnd[property], value);
} else {
this._object[property] = this._valuesStart[property] + (this._valuesEnd[property] - this._valuesStart[property]) * value;
}
}
this.onUpdate.dispatch(this._object, value);
if(elapsed == 1) {
this.onComplete.dispatch(this._object);
for(var i = 0; i < this._chainedTweens.length; i++) {
this._chainedTweens[i].start();
}
return false;
}
return true;
};
return Tween;
})();
Phaser.Tween = Tween;
})(Phaser || (Phaser = {}));
/// World
with specific width and height.
*
* @param width {number} Width of the world bound.
* @param height {number} Height of the world bound.
*/
function World(game, width, height) {
this._game = game;
this.cameras = new Phaser.CameraManager(this._game, 0, 0, width, height);
this.group = new Phaser.Group(this._game, 0);
this.bounds = new Phaser.Rectangle(0, 0, width, height);
this.worldDivisions = 6;
}
World.prototype.update = /**
* This is called automatically every frame, and is where main logic performs.
*/
function () {
this.group.preUpdate();
this.group.update();
this.group.postUpdate();
this.cameras.update();
};
World.prototype.render = /**
* Render every thing to the screen, automatically called after update().
*/
function () {
// Unlike in flixel our render process is camera driven, not group driven
this.cameras.render();
};
World.prototype.destroy = /**
* Clean up memory.
*/
function () {
this.group.destroy();
this.cameras.destroy();
};
World.prototype.setSize = // World methods
/**
* Update size of this world with specific width and height.
* You can choose update camera bounds and verlet manager automatically or not.
*
* @param width {number} New width of the world.
* @param height {number} New height of the world.
* @param [updateCameraBounds] {boolean} update camera bounds automatically or not. Default to true.
* @param [updateVerletBounds] {boolean} update verlet bounds automatically or not. Default to true.
*/
function (width, height, updateCameraBounds, updateVerletBounds) {
if (typeof updateCameraBounds === "undefined") { updateCameraBounds = true; }
if (typeof updateVerletBounds === "undefined") { updateVerletBounds = true; }
this.bounds.width = width;
this.bounds.height = height;
if(updateCameraBounds == true) {
this._game.camera.setBounds(0, 0, width, height);
}
if(updateVerletBounds == true) {
this._game.verlet.width = width;
this._game.verlet.height = height;
}
};
Object.defineProperty(World.prototype, "width", {
get: function () {
return this.bounds.width;
},
set: function (value) {
this.bounds.width = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(World.prototype, "height", {
get: function () {
return this.bounds.height;
},
set: function (value) {
this.bounds.height = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(World.prototype, "centerX", {
get: function () {
return this.bounds.halfWidth;
},
enumerable: true,
configurable: true
});
Object.defineProperty(World.prototype, "centerY", {
get: function () {
return this.bounds.halfHeight;
},
enumerable: true,
configurable: true
});
Object.defineProperty(World.prototype, "randomX", {
get: function () {
return Math.round(Math.random() * this.bounds.width);
},
enumerable: true,
configurable: true
});
Object.defineProperty(World.prototype, "randomY", {
get: function () {
return Math.round(Math.random() * this.bounds.height);
},
enumerable: true,
configurable: true
});
World.prototype.createCamera = // Cameras
/**
* Create a new camera with specific position and size.
*
* @param x {number} X position of the new camera.
* @param y {number} Y position of the new camera.
* @param width {number} Width of the new camera.
* @param height {number} Height of the new camera.
* @returns {Camera} The newly created camera object.
*/
function (x, y, width, height) {
return this.cameras.addCamera(x, y, width, height);
};
World.prototype.removeCamera = /**
* Remove a new camera with its id.
*
* @param id {number} ID of the camera you want to remove.
* @returns {boolean} True if successfully removed the camera, otherwise return false.
*/
function (id) {
return this.cameras.removeCamera(id);
};
World.prototype.getAllCameras = /**
* Get all the cameras.
*
* @returns {array} An array contains all the cameras.
*/
function () {
return this.cameras.getAll();
};
World.prototype.createSprite = // Game Objects
/**
* Create a new Sprite with specific position and sprite sheet key.
*
* @param x {number} X position of the new sprite.
* @param y {number} Y position of the new sprite.
* @param [key] {string} key for the sprite sheet you want it to use.
* @returns {Sprite} The newly created sprite object.
*/
function (x, y, key) {
if (typeof key === "undefined") { key = ''; }
return this.group.add(new Phaser.Sprite(this._game, x, y, key));
};
World.prototype.createGeomSprite = /**
* Create a new GeomSprite with specific position.
*
* @param x {number} X position of the new geom sprite.
* @param y {number} Y position of the new geom sprite.
* @returns {GeomSprite} The newly created geom sprite object.
*/
function (x, y) {
return this.group.add(new Phaser.GeomSprite(this._game, x, y));
};
World.prototype.createDynamicTexture = /**
* Create a new DynamicTexture with specific size.
*
* @param width {number} Width of the texture.
* @param height {number} Height of the texture.
* @returns {DynamicTexture} The newly created dynamic texture object.
*/
function (width, height) {
return new Phaser.DynamicTexture(this._game, width, height);
};
World.prototype.createGroup = /**
* Create a new object container.
*
* @param [maxSize] {number} capacity of this group.
* @returns {Group} The newly created group.
*/
function (maxSize) {
if (typeof maxSize === "undefined") { maxSize = 0; }
return this.group.add(new Phaser.Group(this._game, maxSize));
};
World.prototype.createScrollZone = /**
* Create a new ScrollZone object with image key, position and size.
*
* @param key {number} Key to a image you wish this object to use.
* @param x {number} X position of this object.
* @param y {number} Y position of this object.
* @param width {number} Width of this object.
* @param height {number} Height of this object.
* @returns {ScrollZone} The newly created scroll zone object.
*/
function (key, x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof width === "undefined") { width = 0; }
if (typeof height === "undefined") { height = 0; }
return this.group.add(new Phaser.ScrollZone(this._game, key, x, y, width, height));
};
World.prototype.createTilemap = /**
* Create a new Tilemap.
*
* @param key {string} Key for tileset image.
* @param mapData {string} Data of this tilemap.
* @param format {number} Format of map data. (Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON)
* @param [resizeWorld] {boolean} resize the world to make same as tilemap?
* @param [tileWidth] {number} width of each tile.
* @param [tileHeight] {number} height of each tile.
* @return {Tilemap} The newly created tilemap object.
*/
function (key, mapData, format, resizeWorld, tileWidth, tileHeight) {
if (typeof resizeWorld === "undefined") { resizeWorld = true; }
if (typeof tileWidth === "undefined") { tileWidth = 0; }
if (typeof tileHeight === "undefined") { tileHeight = 0; }
return this.group.add(new Phaser.Tilemap(this._game, key, mapData, format, resizeWorld, tileWidth, tileHeight));
};
World.prototype.createParticle = /**
* Create a new Particle.
*
* @return {Particle} The newly created particle object.
*/
function () {
return new Phaser.Particle(this._game);
};
World.prototype.createEmitter = /**
* Create a new Emitter.
*
* @param [x] {number} x position of the emitter.
* @param [y] {number} y position of the emitter.
* @param [size] {number} size of this emitter.
* @return {Emitter} The newly created emitter object.
*/
function (x, y, size) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof size === "undefined") { size = 0; }
return this.group.add(new Phaser.Emitter(this._game, x, y, size));
};
return World;
})();
Phaser.World = World;
})(Phaser || (Phaser = {}));
/// Emitter
object at a specific position.
* Does NOT automatically generate or attach particles!
*
* @param x {number} The X position of the emitter.
* @param y {number} The Y position of the emitter.
* @param [size] {number} Specifies a maximum capacity for this emitter.
*/
function Emitter(game, x, y, size) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof size === "undefined") { size = 0; }
_super.call(this, game, size);
this.x = x;
this.y = y;
this.width = 0;
this.height = 0;
this.minParticleSpeed = new Phaser.MicroPoint(-100, -100);
this.maxParticleSpeed = new Phaser.MicroPoint(100, 100);
this.minRotation = -360;
this.maxRotation = 360;
this.gravity = 0;
this.particleClass = null;
this.particleDrag = new Phaser.MicroPoint();
this.frequency = 0.1;
this.lifespan = 3;
this.bounce = 0;
this._quantity = 0;
this._counter = 0;
this._explode = true;
this.on = false;
this._point = new Phaser.MicroPoint();
}
Emitter.prototype.destroy = /**
* Clean up memory.
*/
function () {
this.minParticleSpeed = null;
this.maxParticleSpeed = null;
this.particleDrag = null;
this.particleClass = null;
this._point = null;
_super.prototype.destroy.call(this);
};
Emitter.prototype.makeParticles = /**
* This function generates a new array of particle sprites to attach to the emitter.
*
* @param graphics If you opted to not pre-configure an array of Sprite objects, you can simply pass in a particle image or sprite sheet.
* @param quantity {number} The number of particles to generate when using the "create from image" option.
* @param multiple {boolean} Whether the image in the Graphics param is a single particle or a bunch of particles (if it's a bunch, they need to be square!).
* @param collide {number} Whether the particles should be flagged as not 'dead' (non-colliding particles are higher performance). 0 means no collisions, 0-1 controls scale of particle's bounding box.
*
* @return This Emitter instance (nice for chaining stuff together, if you're into that).
*/
function (graphics, quantity, multiple, collide) {
if (typeof quantity === "undefined") { quantity = 50; }
if (typeof multiple === "undefined") { multiple = false; }
if (typeof collide === "undefined") { collide = 0; }
this.maxSize = quantity;
var totalFrames = 1;
/*
if(Multiple)
{
var sprite:Sprite = new Sprite(this._game);
sprite.loadGraphic(Graphics,true);
totalFrames = sprite.frames;
sprite.destroy();
}
*/
var randomFrame;
var particle;
var i = 0;
while(i < quantity) {
if(this.particleClass == null) {
particle = new Phaser.Particle(this._game);
} else {
particle = new this.particleClass(this._game);
}
if(multiple) {
/*
randomFrame = this._game.math.random()*totalFrames;
if(BakedRotations > 0)
particle.loadRotatedGraphic(Graphics,BakedRotations,randomFrame);
else
{
particle.loadGraphic(Graphics,true);
particle.frame = randomFrame;
}
*/
} else {
/*
if (BakedRotations > 0)
particle.loadRotatedGraphic(Graphics,BakedRotations);
else
particle.loadGraphic(Graphics);
*/
if(graphics) {
particle.loadGraphic(graphics);
}
}
if(collide > 0) {
particle.allowCollisions = Phaser.Collision.ANY;
particle.width *= collide;
particle.height *= collide;
//particle.centerOffsets();
} else {
particle.allowCollisions = Phaser.Collision.NONE;
}
particle.exists = false;
this.add(particle);
i++;
}
return this;
};
Emitter.prototype.update = /**
* Called automatically by the game loop, decides when to launch particles and when to "die".
*/
function () {
if(this.on) {
if(this._explode) {
this.on = false;
var i = 0;
var l = this._quantity;
if((l <= 0) || (l > this.length)) {
l = this.length;
}
while(i < l) {
this.emitParticle();
i++;
}
this._quantity = 0;
} else {
this._timer += this._game.time.elapsed;
while((this.frequency > 0) && (this._timer > this.frequency) && this.on) {
this._timer -= this.frequency;
this.emitParticle();
if((this._quantity > 0) && (++this._counter >= this._quantity)) {
this.on = false;
this._quantity = 0;
}
}
}
}
_super.prototype.update.call(this);
};
Emitter.prototype.kill = /**
* Call this function to turn off all the particles and the emitter.
*/
function () {
this.on = false;
_super.prototype.kill.call(this);
};
Emitter.prototype.start = /**
* Call this function to start emitting particles.
*
* @param explode {boolean} Whether the particles should all burst out at once.
* @param lifespan {number} How long each particle lives once emitted. 0 = forever.
* @param frequency {number} Ignored if Explode is set to true. Frequency is how often to emit a particle. 0 = never emit, 0.1 = 1 particle every 0.1 seconds, 5 = 1 particle every 5 seconds.
* @param quantity {number} How many particles to launch. 0 = "all of the particles".
*/
function (explode, lifespan, frequency, quantity) {
if (typeof explode === "undefined") { explode = true; }
if (typeof lifespan === "undefined") { lifespan = 0; }
if (typeof frequency === "undefined") { frequency = 0.1; }
if (typeof quantity === "undefined") { quantity = 0; }
this.revive();
this.visible = true;
this.on = true;
this._explode = explode;
this.lifespan = lifespan;
this.frequency = frequency;
this._quantity += quantity;
this._counter = 0;
this._timer = 0;
};
Emitter.prototype.emitParticle = /**
* This function can be used both internally and externally to emit the next particle.
*/
function () {
var particle = this.recycle(Phaser.Particle);
particle.lifespan = this.lifespan;
particle.elasticity = this.bounce;
particle.reset(this.x - (particle.width >> 1) + this._game.math.random() * this.width, this.y - (particle.height >> 1) + this._game.math.random() * this.height);
particle.visible = true;
if(this.minParticleSpeed.x != this.maxParticleSpeed.x) {
particle.velocity.x = this.minParticleSpeed.x + this._game.math.random() * (this.maxParticleSpeed.x - this.minParticleSpeed.x);
} else {
particle.velocity.x = this.minParticleSpeed.x;
}
if(this.minParticleSpeed.y != this.maxParticleSpeed.y) {
particle.velocity.y = this.minParticleSpeed.y + this._game.math.random() * (this.maxParticleSpeed.y - this.minParticleSpeed.y);
} else {
particle.velocity.y = this.minParticleSpeed.y;
}
particle.acceleration.y = this.gravity;
if(this.minRotation != this.maxRotation && this.minRotation !== 0 && this.maxRotation !== 0) {
particle.angularVelocity = this.minRotation + this._game.math.random() * (this.maxRotation - this.minRotation);
} else {
particle.angularVelocity = this.minRotation;
}
if(particle.angularVelocity != 0) {
particle.angle = this._game.math.random() * 360 - 180;
}
particle.drag.x = this.particleDrag.x;
particle.drag.y = this.particleDrag.y;
particle.onEmit();
};
Emitter.prototype.setSize = /**
* A more compact way of setting the width and height of the emitter.
*
* @param width {number} The desired width of the emitter (particles are spawned randomly within these dimensions).
* @param height {number} The desired height of the emitter.
*/
function (width, height) {
this.width = width;
this.height = height;
};
Emitter.prototype.setXSpeed = /**
* A more compact way of setting the X velocity range of the emitter.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
function (min, max) {
if (typeof min === "undefined") { min = 0; }
if (typeof max === "undefined") { max = 0; }
this.minParticleSpeed.x = min;
this.maxParticleSpeed.x = max;
};
Emitter.prototype.setYSpeed = /**
* A more compact way of setting the Y velocity range of the emitter.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
function (min, max) {
if (typeof min === "undefined") { min = 0; }
if (typeof max === "undefined") { max = 0; }
this.minParticleSpeed.y = min;
this.maxParticleSpeed.y = max;
};
Emitter.prototype.setRotation = /**
* A more compact way of setting the angular velocity constraints of the emitter.
*
* @param Min {number} The minimum value for this range.
* @param Max {number} The maximum value for this range.
*/
function (min, max) {
if (typeof min === "undefined") { min = 0; }
if (typeof max === "undefined") { max = 0; }
this.minRotation = min;
this.maxRotation = max;
};
Emitter.prototype.at = /**
* Change the emitter's midpoint to match the midpoint of a Object
.
*
* @param Object {object} The Object
that you want to sync up with.
*/
function (object) {
object.getMidpoint(this._point);
this.x = this._point.x - (this.width >> 1);
this.y = this._point.y - (this.height >> 1);
};
return Emitter;
})(Phaser.Group);
Phaser.Emitter = Emitter;
})(Phaser || (Phaser = {}));
/// GeomSprite
.
*
* @param game {Phaser.Game} Current game instance.
* @param [x] {number} the initial x position of the sprite.
* @param [y] {number} the initial y position of the sprite.
*/
function GeomSprite(game, x, y) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
_super.call(this, game, x, y);
// local rendering related temp vars to help avoid gc spikes
this._dx = 0;
this._dy = 0;
this._dw = 0;
this._dh = 0;
/**
* Geom type of this sprite. (available: UNASSIGNED, CIRCLE, LINE, POINT, RECTANGLE)
* @type {number}
*/
this.type = 0;
/**
* Render outline of this sprite or not. (default is true)
* @type {boolean}
*/
this.renderOutline = true;
/**
* Fill the shape or not. (default is true)
* @type {boolean}
*/
this.renderFill = true;
/**
* Width of outline. (default is 1)
* @type {number}
*/
this.lineWidth = 1;
/**
* Width of outline. (default is 1)
* @type {number}
*/
this.lineColor = 'rgb(0,255,0)';
/**
* The color of the filled area in rgb or rgba string format
* @type {string} Defaults to rgb(0,100,0) - a green color
*/
this.fillColor = 'rgb(0,100,0)';
this.type = GeomSprite.UNASSIGNED;
return this;
}
GeomSprite.UNASSIGNED = 0;
GeomSprite.CIRCLE = 1;
GeomSprite.LINE = 2;
GeomSprite.POINT = 3;
GeomSprite.RECTANGLE = 4;
GeomSprite.POLYGON = 5;
GeomSprite.prototype.loadCircle = /**
* Just like Sprite.loadGraphic(), this will load a circle and set its shape to Circle.
* @param circle {Circle} Circle geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
function (circle) {
this.refresh();
this.circle = circle;
this.type = GeomSprite.CIRCLE;
return this;
};
GeomSprite.prototype.loadLine = /**
* Just like Sprite.loadGraphic(), this will load a line and set its shape to Line.
* @param line {Line} Line geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
function (line) {
this.refresh();
this.line = line;
this.type = GeomSprite.LINE;
return this;
};
GeomSprite.prototype.loadPoint = /**
* Just like Sprite.loadGraphic(), this will load a point and set its shape to Point.
* @param point {Point} Point geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
function (point) {
this.refresh();
this.point = point;
this.type = GeomSprite.POINT;
return this;
};
GeomSprite.prototype.loadRectangle = /**
* Just like Sprite.loadGraphic(), this will load a rect and set its shape to Rectangle.
* @param rect {Rectangle} Rectangle geometry define.
* @return {GeomSprite} GeomSprite instance itself.
*/
function (rect) {
this.refresh();
this.rect = rect;
this.type = GeomSprite.RECTANGLE;
return this;
};
GeomSprite.prototype.createCircle = /**
* Create a circle shape with specific diameter.
* @param diameter {number} Diameter of the circle.
* @return {GeomSprite} GeomSprite instance itself.
*/
function (diameter) {
this.refresh();
this.circle = new Phaser.Circle(this.x, this.y, diameter);
this.type = GeomSprite.CIRCLE;
this.frameBounds.setTo(this.circle.x - this.circle.radius, this.circle.y - this.circle.radius, this.circle.diameter, this.circle.diameter);
return this;
};
GeomSprite.prototype.createLine = /**
* Create a line shape with specific end point.
* @param x {number} X position of the end point.
* @param y {number} Y position of the end point.
* @return {GeomSprite} GeomSprite instance itself.
*/
function (x, y) {
this.refresh();
this.line = new Phaser.Line(this.x, this.y, x, y);
this.type = GeomSprite.LINE;
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
return this;
};
GeomSprite.prototype.createPoint = /**
* Create a point shape at spriter's position.
* @return {GeomSprite} GeomSprite instance itself.
*/
function () {
this.refresh();
this.point = new Phaser.Point(this.x, this.y);
this.type = GeomSprite.POINT;
this.frameBounds.width = 1;
this.frameBounds.height = 1;
return this;
};
GeomSprite.prototype.createRectangle = /**
* Create a rectangle shape of the given width and height size
* @param width {Number} Width of the rectangle
* @param height {Number} Height of the rectangle
* @return {GeomSprite} GeomSprite instance.
*/
function (width, height) {
this.refresh();
this.rect = new Phaser.Rectangle(this.x, this.y, width, height);
this.type = GeomSprite.RECTANGLE;
this.frameBounds.copyFrom(this.rect);
return this;
};
GeomSprite.prototype.createPolygon = /**
* Create a polygon object
* @param width {Number} Width of the rectangle
* @param height {Number} Height of the rectangle
* @return {GeomSprite} GeomSprite instance.
*/
function (points) {
if (typeof points === "undefined") { points = []; }
this.refresh();
this.polygon = new Phaser.Polygon(new Phaser.Vector2(this.x, this.y), points);
this.type = GeomSprite.POLYGON;
//this.frameBounds.copyFrom(this.rect);
return this;
};
GeomSprite.prototype.refresh = /**
* Destroy all geom shapes of this sprite.
*/
function () {
this.circle = null;
this.line = null;
this.point = null;
this.rect = null;
};
GeomSprite.prototype.update = /**
* Update bounds.
*/
function () {
// Update bounds and position?
if(this.type == GeomSprite.UNASSIGNED) {
return;
} else if(this.type == GeomSprite.CIRCLE) {
this.circle.x = this.x;
this.circle.y = this.y;
this.frameBounds.width = this.circle.diameter;
this.frameBounds.height = this.circle.diameter;
} else if(this.type == GeomSprite.LINE) {
this.line.x1 = this.x;
this.line.y1 = this.y;
this.frameBounds.setTo(this.x, this.y, this.line.width, this.line.height);
} else if(this.type == GeomSprite.POINT) {
this.point.x = this.x;
this.point.y = this.y;
} else if(this.type == GeomSprite.RECTANGLE) {
this.rect.x = this.x;
this.rect.y = this.y;
this.frameBounds.copyFrom(this.rect);
}
};
GeomSprite.prototype.inCamera = /**
* Check whether this object is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bounds of this sprite intersects the given rectangle, otherwise return false.
*/
function (camera) {
if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
} else {
return camera.intersects(this.frameBounds);
}
};
GeomSprite.prototype.render = /**
* Render this sprite to specific camera. Called by game loop after update().
* @param camera {Camera} Camera this sprite will be rendered to.
* @cameraOffsetX {number} X offset to the camera.
* @cameraOffsetY {number} Y offset to the camera.
* @return {boolean} Return false if not rendered, otherwise return true.
*/
function (camera, cameraOffsetX, cameraOffsetY) {
// Render checks
if(this.type == GeomSprite.UNASSIGNED || this.visible === false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView) == false) {
return false;
}
// Alpha
if(this.alpha !== 1) {
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.frameBounds.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.y - camera.worldView.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
// Apply camera difference
if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
this._dx -= (camera.worldView.x * this.scrollFactor.x);
this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
// Rotation is disabled for now as I don't want it to be misleading re: collision
/*
if (this.angle !== 0)
{
this.context.save();
this.context.translate(this._dx + (this._dw / 2) - this.origin.x, this._dy + (this._dh / 2) - this.origin.y);
this.context.rotate(this.angle * (Math.PI / 180));
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
}
*/
this._dx = Math.round(this._dx);
this._dy = Math.round(this._dy);
this._dw = Math.round(this._dw);
this._dh = Math.round(this._dh);
this._game.stage.saveCanvasValues();
// Debug
//this.context.fillStyle = 'rgba(255,0,0,0.5)';
//this.context.fillRect(this.frameBounds.x, this.frameBounds.y, this.frameBounds.width, this.frameBounds.height);
this.context.lineWidth = this.lineWidth;
this.context.strokeStyle = this.lineColor;
this.context.fillStyle = this.fillColor;
if(this._game.stage.fillStyle !== this.fillColor) {
}
// Primitive Renderer
if(this.type == GeomSprite.CIRCLE) {
this.context.beginPath();
this.context.arc(this._dx, this._dy, this.circle.radius, 0, Math.PI * 2);
if(this.renderOutline) {
this.context.stroke();
}
if(this.renderFill) {
this.context.fill();
}
this.context.closePath();
} else if(this.type == GeomSprite.LINE) {
this.context.beginPath();
this.context.moveTo(this._dx, this._dy);
this.context.lineTo(this.line.x2, this.line.y2);
this.context.stroke();
this.context.closePath();
} else if(this.type == GeomSprite.POINT) {
this.context.fillRect(this._dx, this._dy, 2, 2);
} else if(this.type == GeomSprite.RECTANGLE) {
// We can use the faster fillRect if we don't need the outline
if(this.renderOutline == false) {
this.context.fillRect(this._dx, this._dy, this.rect.width, this.rect.height);
} else {
this.context.beginPath();
this.context.rect(this._dx, this._dy, this.rect.width, this.rect.height);
this.context.stroke();
if(this.renderFill) {
this.context.fill();
}
this.context.closePath();
}
// And now the edge points
this.context.fillStyle = 'rgb(255,255,255)';
//this.renderPoint(this.rect.topLeft, this._dx, this._dy, 2);
//this.renderPoint(this.rect.topCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.topRight, this._dx, this._dy, 2);
//this.renderPoint(this.rect.leftCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.center, this._dx, this._dy, 2);
//this.renderPoint(this.rect.rightCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomLeft, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomCenter, this._dx, this._dy, 2);
//this.renderPoint(this.rect.bottomRight, this._dx, this._dy, 2);
this.renderPoint(this.rect.topLeft, 0, 0, 2);
this.renderPoint(this.rect.topCenter, 0, 0, 2);
this.renderPoint(this.rect.topRight, 0, 0, 2);
this.renderPoint(this.rect.leftCenter, 0, 0, 2);
this.renderPoint(this.rect.center, 0, 0, 2);
this.renderPoint(this.rect.rightCenter, 0, 0, 2);
this.renderPoint(this.rect.bottomLeft, 0, 0, 2);
this.renderPoint(this.rect.bottomCenter, 0, 0, 2);
this.renderPoint(this.rect.bottomRight, 0, 0, 2);
}
this._game.stage.restoreCanvasValues();
if(this.rotation !== 0) {
this.context.translate(0, 0);
this.context.restore();
}
if(globalAlpha > -1) {
this.context.globalAlpha = globalAlpha;
}
return true;
};
GeomSprite.prototype.renderPoint = /**
* Render a point of geometry.
* @param point {Point} Position of the point.
* @param offsetX {number} X offset to its position.
* @param offsetY {number} Y offset to its position.
* @param [size] {number} point size.
*/
function (point, offsetX, offsetY, size) {
if (typeof offsetX === "undefined") { offsetX = 0; }
if (typeof offsetY === "undefined") { offsetY = 0; }
if (typeof size === "undefined") { size = 1; }
this.context.fillRect(offsetX + point.x, offsetY + point.y, size, size);
};
GeomSprite.prototype.renderDebugInfo = /**
* Render debug infos. (this method does not work now)
* @param x {number} X position of the debug info to be rendered.
* @param y {number} Y position of the debug info to be rendered.
* @param [color] {number} color of the debug info to be rendered. (format is css color string)
*/
function (x, y, color) {
if (typeof color === "undefined") { color = 'rgb(255,255,255)'; }
//this.context.fillStyle = color;
//this.context.fillText('Sprite: ' + this.name + ' (' + this.frameBounds.width + ' x ' + this.frameBounds.height + ')', x, y);
//this.context.fillText('x: ' + this.frameBounds.x.toFixed(1) + ' y: ' + this.frameBounds.y.toFixed(1) + ' rotation: ' + this.angle.toFixed(1), x, y + 14);
//this.context.fillText('dx: ' + this._dx.toFixed(1) + ' dy: ' + this._dy.toFixed(1) + ' dw: ' + this._dw.toFixed(1) + ' dh: ' + this._dh.toFixed(1), x, y + 28);
//this.context.fillText('sx: ' + this._sx.toFixed(1) + ' sy: ' + this._sy.toFixed(1) + ' sw: ' + this._sw.toFixed(1) + ' sh: ' + this._sh.toFixed(1), x, y + 42);
};
GeomSprite.prototype.collide = /**
* Gives a basic boolean response to a geometric collision.
* If you need the details of the collision use the Collision functions instead and inspect the IntersectResult object.
* @param source {GeomSprite} Sprite you want to check.
* @return {boolean} Whether they overlaps or not.
*/
function (source) {
// Circle vs. Circle
if(this.type == GeomSprite.CIRCLE && source.type == GeomSprite.CIRCLE) {
return Phaser.Collision.circleToCircle(this.circle, source.circle).result;
}
// Circle vs. Rect
if(this.type == GeomSprite.CIRCLE && source.type == GeomSprite.RECTANGLE) {
return Phaser.Collision.circleToRectangle(this.circle, source.rect).result;
}
// Circle vs. Point
if(this.type == GeomSprite.CIRCLE && source.type == GeomSprite.POINT) {
return Phaser.Collision.circleContainsPoint(this.circle, source.point).result;
}
// Circle vs. Line
if(this.type == GeomSprite.CIRCLE && source.type == GeomSprite.LINE) {
return Phaser.Collision.lineToCircle(source.line, this.circle).result;
}
// Rect vs. Rect
if(this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.RECTANGLE) {
return Phaser.Collision.rectangleToRectangle(this.rect, source.rect).result;
}
// Rect vs. Circle
if(this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.CIRCLE) {
return Phaser.Collision.circleToRectangle(source.circle, this.rect).result;
}
// Rect vs. Point
if(this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.POINT) {
return Phaser.Collision.pointToRectangle(source.point, this.rect).result;
}
// Rect vs. Line
if(this.type == GeomSprite.RECTANGLE && source.type == GeomSprite.LINE) {
return Phaser.Collision.lineToRectangle(source.line, this.rect).result;
}
// Point vs. Point
if(this.type == GeomSprite.POINT && source.type == GeomSprite.POINT) {
return this.point.equals(source.point);
}
// Point vs. Circle
if(this.type == GeomSprite.POINT && source.type == GeomSprite.CIRCLE) {
return Phaser.Collision.circleContainsPoint(source.circle, this.point).result;
}
// Point vs. Rect
if(this.type == GeomSprite.POINT && source.type == GeomSprite.RECTANGLE) {
return Phaser.Collision.pointToRectangle(this.point, source.rect).result;
}
// Point vs. Line
if(this.type == GeomSprite.POINT && source.type == GeomSprite.LINE) {
return source.line.isPointOnLine(this.point.x, this.point.y);
}
// Line vs. Line
if(this.type == GeomSprite.LINE && source.type == GeomSprite.LINE) {
return Phaser.Collision.lineSegmentToLineSegment(this.line, source.line).result;
}
// Line vs. Circle
if(this.type == GeomSprite.LINE && source.type == GeomSprite.CIRCLE) {
return Phaser.Collision.lineToCircle(this.line, source.circle).result;
}
// Line vs. Rect
if(this.type == GeomSprite.LINE && source.type == GeomSprite.RECTANGLE) {
return Phaser.Collision.lineSegmentToRectangle(this.line, source.rect).result;
}
// Line vs. Point
if(this.type == GeomSprite.LINE && source.type == GeomSprite.POINT) {
return this.line.isPointOnLine(source.point.x, source.point.y);
}
return false;
};
return GeomSprite;
})(Phaser.GameObject);
Phaser.GeomSprite = GeomSprite;
})(Phaser || (Phaser = {}));
/// Sprite
, all meaningful creation
* happens during loadGraphic()
or makeGraphic()
or whatever.
*/
function Particle(game) {
_super.call(this, game);
this.lifespan = 0;
this.friction = 500;
}
Particle.prototype.update = /**
* The particle's main update logic. Basically it checks to see if it should
* be dead yet, and then has some special bounce behavior if there is some gravity on it.
*/
function () {
//lifespan behavior
if(this.lifespan <= 0) {
return;
}
this.lifespan -= this._game.time.elapsed;
if(this.lifespan <= 0) {
this.kill();
}
//simpler bounce/spin behavior for now
if(this.touching) {
if(this.angularVelocity != 0) {
this.angularVelocity = -this.angularVelocity;
}
}
if(this.acceleration.y > 0)//special behavior for particles with gravity
{
if(this.touching & Phaser.Collision.FLOOR) {
this.drag.x = this.friction;
if(!(this.wasTouching & Phaser.Collision.FLOOR)) {
if(this.velocity.y < -this.elasticity * 10) {
if(this.angularVelocity != 0) {
this.angularVelocity *= -this.elasticity;
}
} else {
this.velocity.y = 0;
this.angularVelocity = 0;
}
}
} else {
this.drag.x = 0;
}
}
};
Particle.prototype.onEmit = /**
* Triggered whenever this object is launched by a Emitter
.
* You can override this to add custom behavior like a sound or AI or something.
*/
function () {
};
return Particle;
})(Phaser.Sprite);
Phaser.Particle = Particle;
})(Phaser || (Phaser = {}));
/// TilemapLayer
.
*
* @param game {Phaser.Game} Current game instance.
* @param parent {Tilemap} The tilemap that contains this layer.
* @param key {string} Asset key for this map.
* @param mapFormat {number} Format of this map data, available: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
* @param name {string} Name of this layer, so you can get this layer by its name.
* @param tileWidth {number} Width of tiles in this map.
* @param tileHeight {number} Height of tiles in this map.
*/
function TilemapLayer(game, parent, key, mapFormat, name, tileWidth, tileHeight) {
this._startX = 0;
this._startY = 0;
this._maxX = 0;
this._maxY = 0;
this._tx = 0;
this._ty = 0;
this._dx = 0;
this._dy = 0;
this._oldCameraX = 0;
this._oldCameraY = 0;
/**
* Opacity of this layer.
* @type {number}
*/
this.alpha = 1;
/**
* Controls whether update() and draw() are automatically called.
* @type {boolean}
*/
this.exists = true;
/**
* Controls whether draw() are automatically called.
* @type {boolean}
*/
this.visible = true;
/**
* How many tiles in each row.
* Read-only variable, do NOT recommend changing after the map is loaded!
* @type {number}
*/
this.widthInTiles = 0;
/**
* How many tiles in each column.
* Read-only variable, do NOT recommend changing after the map is loaded!
* @type {number}
*/
this.heightInTiles = 0;
/**
* Read-only variable, do NOT recommend changing after the map is loaded!
* @type {number}
*/
this.widthInPixels = 0;
/**
* Read-only variable, do NOT recommend changing after the map is loaded!
* @type {number}
*/
this.heightInPixels = 0;
/**
* Distance between REAL tiles to the tileset texture bound.
* @type {number}
*/
this.tileMargin = 0;
/**
* Distance between every 2 neighbor tile in the tileset texture.
* @type {number}
*/
this.tileSpacing = 0;
this._game = game;
this._parent = parent;
this.name = name;
this.mapFormat = mapFormat;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.boundsInTiles = new Phaser.Rectangle();
//this.scrollFactor = new MicroPoint(1, 1);
this.canvas = game.stage.canvas;
this.context = game.stage.context;
this.mapData = [];
this._tempTileBlock = [];
this._texture = this._game.cache.getImage(key);
}
TilemapLayer.prototype.putTile = /**
* Set a specific tile with its x and y in tiles.
* @param x {number} X position of this tile.
* @param y {number} Y position of this tile.
* @param index {number} The index of this tile type in the core map data.
*/
function (x, y, index) {
x = this._game.math.snapToFloor(x, this.tileWidth) / this.tileWidth;
y = this._game.math.snapToFloor(y, this.tileHeight) / this.tileHeight;
if(y >= 0 && y < this.mapData.length) {
if(x >= 0 && x < this.mapData[y].length) {
this.mapData[y][x] = index;
}
}
};
TilemapLayer.prototype.swapTile = /**
* Swap tiles with 2 kinds of indexes.
* @param tileA {number} First tile index.
* @param tileB {number} Second tile index.
* @param [x] {number} specify a rectangle of tiles to operate. The x position in tiles of rectangle's left-top corner.
* @param [y] {number} specify a rectangle of tiles to operate. The y position in tiles of rectangle's left-top corner.
* @param [width] {number} specify a rectangle of tiles to operate. The width in tiles.
* @param [height] {number} specify a rectangle of tiles to operate. The height in tiles.
*/
function (tileA, tileB, x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof width === "undefined") { width = this.widthInTiles; }
if (typeof height === "undefined") { height = this.heightInTiles; }
this.getTempBlock(x, y, width, height);
for(var r = 0; r < this._tempTileBlock.length; r++) {
// First sweep marking tileA as needing a new index
if(this._tempTileBlock[r].tile.index == tileA) {
this._tempTileBlock[r].newIndex = true;
}
// In the same pass we can swap tileB to tileA
if(this._tempTileBlock[r].tile.index == tileB) {
this.mapData[this._tempTileBlock[r].y][this._tempTileBlock[r].x] = tileA;
}
}
for(var r = 0; r < this._tempTileBlock.length; r++) {
// And now swap our newIndex tiles for tileB
if(this._tempTileBlock[r].newIndex == true) {
this.mapData[this._tempTileBlock[r].y][this._tempTileBlock[r].x] = tileB;
}
}
};
TilemapLayer.prototype.fillTile = /**
* Fill a tile block with a specific tile index.
* @param index {number} Index of tiles you want to fill with.
* @param [x] {number} x position (in tiles) of block's left-top corner.
* @param [y] {number} y position (in tiles) of block's left-top corner.
* @param [width] {number} width of block.
* @param [height] {number} height of block.
*/
function (index, x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof width === "undefined") { width = this.widthInTiles; }
if (typeof height === "undefined") { height = this.heightInTiles; }
this.getTempBlock(x, y, width, height);
for(var r = 0; r < this._tempTileBlock.length; r++) {
this.mapData[this._tempTileBlock[r].y][this._tempTileBlock[r].x] = index;
}
};
TilemapLayer.prototype.randomiseTiles = /**
* Set random tiles to a specific tile block.
* @param tiles {number[]} Tiles with indexes in this array will be randomly set to the given block.
* @param [x] {number} x position (in tiles) of block's left-top corner.
* @param [y] {number} y position (in tiles) of block's left-top corner.
* @param [width] {number} width of block.
* @param [height] {number} height of block.
*/
function (tiles, x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof width === "undefined") { width = this.widthInTiles; }
if (typeof height === "undefined") { height = this.heightInTiles; }
this.getTempBlock(x, y, width, height);
for(var r = 0; r < this._tempTileBlock.length; r++) {
this.mapData[this._tempTileBlock[r].y][this._tempTileBlock[r].x] = this._game.math.getRandom(tiles);
}
};
TilemapLayer.prototype.replaceTile = /**
* Replace one kind of tiles to another kind.
* @param tileA {number} Index of tiles you want to replace.
* @param tileB {number} Index of tiles you want to set.
* @param [x] {number} x position (in tiles) of block's left-top corner.
* @param [y] {number} y position (in tiles) of block's left-top corner.
* @param [width] {number} width of block.
* @param [height] {number} height of block.
*/
function (tileA, tileB, x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof width === "undefined") { width = this.widthInTiles; }
if (typeof height === "undefined") { height = this.heightInTiles; }
this.getTempBlock(x, y, width, height);
for(var r = 0; r < this._tempTileBlock.length; r++) {
if(this._tempTileBlock[r].tile.index == tileA) {
this.mapData[this._tempTileBlock[r].y][this._tempTileBlock[r].x] = tileB;
}
}
};
TilemapLayer.prototype.getTileBlock = /**
* Get a tile block with specific position and size.(both are in tiles)
* @param x {number} X position of block's left-top corner.
* @param y {number} Y position of block's left-top corner.
* @param width {number} Width of block.
* @param height {number} Height of block.
*/
function (x, y, width, height) {
var output = [];
this.getTempBlock(x, y, width, height);
for(var r = 0; r < this._tempTileBlock.length; r++) {
output.push({
x: this._tempTileBlock[r].x,
y: this._tempTileBlock[r].y,
tile: this._tempTileBlock[r].tile
});
}
return output;
};
TilemapLayer.prototype.getTileFromWorldXY = /**
* Get a tile with specific position (in world coordinate). (thus you give a position of a point which is within the tile)
* @param x {number} X position of the point in target tile.
* @param x {number} Y position of the point in target tile.
*/
function (x, y) {
x = this._game.math.snapToFloor(x, this.tileWidth) / this.tileWidth;
y = this._game.math.snapToFloor(y, this.tileHeight) / this.tileHeight;
return this.getTileIndex(x, y);
};
TilemapLayer.prototype.getTileOverlaps = /**
* Get tiles overlaps the given object.
* @param object {GameObject} Tiles you want to get that overlaps this.
* @return {array} Array with tiles informations. (Each contains x, y and the tile.)
*/
function (object) {
// If the object is outside of the world coordinates then abort the check (tilemap has to exist within world bounds)
if(object.collisionMask.x < 0 || object.collisionMask.x > this.widthInPixels || object.collisionMask.y < 0 || object.collisionMask.bottom > this.heightInPixels) {
return;
}
// What tiles do we need to check against?
this._tempTileX = this._game.math.snapToFloor(object.collisionMask.x, this.tileWidth) / this.tileWidth;
this._tempTileY = this._game.math.snapToFloor(object.collisionMask.y, this.tileHeight) / this.tileHeight;
this._tempTileW = (this._game.math.snapToCeil(object.collisionMask.width, this.tileWidth) + this.tileWidth) / this.tileWidth;
this._tempTileH = (this._game.math.snapToCeil(object.collisionMask.height, this.tileHeight) + this.tileHeight) / this.tileHeight;
// Loop through the tiles we've got and check overlaps accordingly (the results are stored in this._tempTileBlock)
this._tempBlockResults = [];
this.getTempBlock(this._tempTileX, this._tempTileY, this._tempTileW, this._tempTileH, true);
Phaser.Collision.TILE_OVERLAP = false;
for(var r = 0; r < this._tempTileBlock.length; r++) {
if(Phaser.Collision.separateTile(object, this._tempTileBlock[r].x * this.tileWidth, this._tempTileBlock[r].y * this.tileHeight, this.tileWidth, this.tileHeight, this._tempTileBlock[r].tile.mass, this._tempTileBlock[r].tile.collideLeft, this._tempTileBlock[r].tile.collideRight, this._tempTileBlock[r].tile.collideUp, this._tempTileBlock[r].tile.collideDown, this._tempTileBlock[r].tile.separateX, this._tempTileBlock[r].tile.separateY) == true) {
this._tempBlockResults.push({
x: this._tempTileBlock[r].x,
y: this._tempTileBlock[r].y,
tile: this._tempTileBlock[r].tile
});
}
}
return this._tempBlockResults;
};
TilemapLayer.prototype.getTempBlock = /**
* Get a tile block with its position and size. (This method does not return, it'll set result to _tempTileBlock)
* @param x {number} X position of block's left-top corner.
* @param y {number} Y position of block's left-top corner.
* @param width {number} Width of block.
* @param height {number} Height of block.
* @param collisionOnly {boolean} Whethor or not ONLY return tiles which will collide (its allowCollisions value is not Collision.NONE).
*/
function (x, y, width, height, collisionOnly) {
if (typeof collisionOnly === "undefined") { collisionOnly = false; }
if(x < 0) {
x = 0;
}
if(y < 0) {
y = 0;
}
if(width > this.widthInTiles) {
width = this.widthInTiles;
}
if(height > this.heightInTiles) {
height = this.heightInTiles;
}
this._tempTileBlock = [];
for(var ty = y; ty < y + height; ty++) {
for(var tx = x; tx < x + width; tx++) {
if(collisionOnly) {
// We only want to consider the tile for checking if you can actually collide with it
if(this.mapData[ty] && this.mapData[ty][tx] && this._parent.tiles[this.mapData[ty][tx]].allowCollisions != Phaser.Collision.NONE) {
this._tempTileBlock.push({
x: tx,
y: ty,
tile: this._parent.tiles[this.mapData[ty][tx]]
});
}
} else {
if(this.mapData[ty] && this.mapData[ty][tx]) {
this._tempTileBlock.push({
x: tx,
y: ty,
tile: this._parent.tiles[this.mapData[ty][tx]]
});
}
}
}
}
};
TilemapLayer.prototype.getTileIndex = /**
* Get the tile index of specific position (in tiles).
* @param x {number} X position of the tile.
* @param y {number} Y position of the tile.
* @return {number} Index of the tile at that position. Return null if there isn't a tile there.
*/
function (x, y) {
if(y >= 0 && y < this.mapData.length) {
if(x >= 0 && x < this.mapData[y].length) {
return this.mapData[y][x];
}
}
return null;
};
TilemapLayer.prototype.addColumn = /**
* Add a column of tiles into the layer.
* @param column {string[]/number[]} An array of tile indexes to be added.
*/
function (column) {
var data = [];
for(var c = 0; c < column.length; c++) {
data[c] = parseInt(column[c]);
}
if(this.widthInTiles == 0) {
this.widthInTiles = data.length;
this.widthInPixels = this.widthInTiles * this.tileWidth;
}
this.mapData.push(data);
this.heightInTiles++;
this.heightInPixels += this.tileHeight;
};
TilemapLayer.prototype.updateBounds = /**
* Update boundsInTiles with widthInTiles and heightInTiles.
*/
function () {
this.boundsInTiles.setTo(0, 0, this.widthInTiles, this.heightInTiles);
};
TilemapLayer.prototype.parseTileOffsets = /**
* Parse tile offsets from map data.
* @return {number} length of _tileOffsets array.
*/
function () {
this._tileOffsets = [];
var i = 0;
if(this.mapFormat == Phaser.Tilemap.FORMAT_TILED_JSON) {
// For some reason Tiled counts from 1 not 0
this._tileOffsets[0] = null;
i = 1;
}
for(var ty = this.tileMargin; ty < this._texture.height; ty += (this.tileHeight + this.tileSpacing)) {
for(var tx = this.tileMargin; tx < this._texture.width; tx += (this.tileWidth + this.tileSpacing)) {
this._tileOffsets[i] = {
x: tx,
y: ty
};
i++;
}
}
return this._tileOffsets.length;
};
TilemapLayer.prototype.renderDebugInfo = function (x, y, color) {
if (typeof color === "undefined") { color = 'rgb(255,255,255)'; }
this.context.fillStyle = color;
this.context.fillText('TilemapLayer: ' + this.name, x, y);
this.context.fillText('startX: ' + this._startX + ' endX: ' + this._maxX, x, y + 14);
this.context.fillText('startY: ' + this._startY + ' endY: ' + this._maxY, x, y + 28);
this.context.fillText('dx: ' + this._dx + ' dy: ' + this._dy, x, y + 42);
};
TilemapLayer.prototype.render = /**
* Render this layer to a specific camera with offset to camera.
* @param camera {Camera} The camera the layer is going to be rendered.
* @param dx {number} X offset to the camera.
* @param dy {number} Y offset to the camera.
* @return {boolean} Return false if layer is invisible or has a too low opacity(will stop rendering), return true if succeed.
*/
function (camera, dx, dy) {
if(this.visible === false || this.alpha < 0.1) {
return false;
}
// Work out how many tiles we can fit into our camera and round it up for the edges
this._maxX = this._game.math.ceil(camera.width / this.tileWidth) + 1;
this._maxY = this._game.math.ceil(camera.height / this.tileHeight) + 1;
// And now work out where in the tilemap the camera actually is
this._startX = this._game.math.floor(camera.worldView.x / this.tileWidth);
this._startY = this._game.math.floor(camera.worldView.y / this.tileHeight);
// Tilemap bounds check
if(this._startX < 0) {
this._startX = 0;
}
if(this._startY < 0) {
this._startY = 0;
}
if(this._maxX > this.widthInTiles) {
this._maxX = this.widthInTiles;
}
if(this._maxY > this.heightInTiles) {
this._maxY = this.heightInTiles;
}
if(this._startX + this._maxX > this.widthInTiles) {
this._startX = this.widthInTiles - this._maxX;
}
if(this._startY + this._maxY > this.heightInTiles) {
this._startY = this.heightInTiles - this._maxY;
}
// Finally get the offset to avoid the blocky movement
this._dx = dx;
this._dy = dy;
this._dx += -(camera.worldView.x - (this._startX * this.tileWidth));
this._dy += -(camera.worldView.y - (this._startY * this.tileHeight));
this._tx = this._dx;
this._ty = this._dy;
// Apply camera difference
/*
if (this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0)
{
this._dx -= (camera.worldView.x * this.scrollFactor.x);
this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
*/
// Alpha
if(this.alpha !== 1) {
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
for(var row = this._startY; row < this._startY + this._maxY; row++) {
this._columnData = this.mapData[row];
for(var tile = this._startX; tile < this._startX + this._maxX; tile++) {
if(this._tileOffsets[this._columnData[tile]]) {
this.context.drawImage(this._texture, // Source Image
this._tileOffsets[this._columnData[tile]].x, // Source X (location within the source image)
this._tileOffsets[this._columnData[tile]].y, // Source Y
this.tileWidth, // Source Width
this.tileHeight, // Source Height
this._tx, // Destination X (where on the canvas it'll be drawn)
this._ty, // Destination Y
this.tileWidth, // Destination Width (always same as Source Width unless scaled)
this.tileHeight);
// Destination Height (always same as Source Height unless scaled)
}
this._tx += this.tileWidth;
}
this._tx = this._dx;
this._ty += this.tileHeight;
}
if(globalAlpha > -1) {
this.context.globalAlpha = globalAlpha;
}
return true;
};
return TilemapLayer;
})();
Phaser.TilemapLayer = TilemapLayer;
})(Phaser || (Phaser = {}));
/// Tile
.
*
* @param tilemap {Tilemap} the tilemap this tile belongs to.
* @param index {number} The index of this tile type in the core map data.
* @param width {number} Width of the tile.
* @param height number} Height of the tile.
*/
function Tile(game, tilemap, index, width, height) {
/**
* The virtual mass of the tile.
* @type {number}
*/
this.mass = 1.0;
/**
* Indicating collide with any object on the left.
* @type {boolean}
*/
this.collideLeft = false;
/**
* Indicating collide with any object on the right.
* @type {boolean}
*/
this.collideRight = false;
/**
* Indicating collide with any object on the top.
* @type {boolean}
*/
this.collideUp = false;
/**
* Indicating collide with any object on the bottom.
* @type {boolean}
*/
this.collideDown = false;
/**
* Enable separation at x-axis.
* @type {boolean}
*/
this.separateX = true;
/**
* Enable separation at y-axis.
* @type {boolean}
*/
this.separateY = true;
this._game = game;
this.tilemap = tilemap;
this.index = index;
this.width = width;
this.height = height;
this.allowCollisions = Phaser.Collision.NONE;
}
Tile.prototype.destroy = /**
* Clean up memory.
*/
function () {
this.tilemap = null;
};
Tile.prototype.setCollision = /**
* Set collision configs.
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
* @param resetCollisions {boolean} Reset collision flags before set.
* @param separateX {boolean} Enable seprate at x-axis.
* @param separateY {boolean} Enable seprate at y-axis.
*/
function (collision, resetCollisions, separateX, separateY) {
if(resetCollisions) {
this.resetCollision();
}
this.separateX = separateX;
this.separateY = separateY;
this.allowCollisions = collision;
if(collision & Phaser.Collision.ANY) {
this.collideLeft = true;
this.collideRight = true;
this.collideUp = true;
this.collideDown = true;
return;
}
if(collision & Phaser.Collision.LEFT || collision & Phaser.Collision.WALL) {
this.collideLeft = true;
}
if(collision & Phaser.Collision.RIGHT || collision & Phaser.Collision.WALL) {
this.collideRight = true;
}
if(collision & Phaser.Collision.UP || collision & Phaser.Collision.CEILING) {
this.collideUp = true;
}
if(collision & Phaser.Collision.DOWN || collision & Phaser.Collision.CEILING) {
this.collideDown = true;
}
};
Tile.prototype.resetCollision = /**
* Reset collision status flags.
*/
function () {
this.allowCollisions = Phaser.Collision.NONE;
this.collideLeft = false;
this.collideRight = false;
this.collideUp = false;
this.collideDown = false;
};
Tile.prototype.toString = /**
* Returns a string representation of this object.
* @method toString
* @return {string} a string representation of the object.
**/
function () {
return "[{Tiled (index=" + this.index + " collisions=" + this.allowCollisions + " width=" + this.width + " height=" + this.height + ")}]";
};
return Tile;
})();
Phaser.Tile = Tile;
})(Phaser || (Phaser = {}));
/// Tilemap
.
*
* @param game {Phaser.Game} Current game instance.
* @param key {string} Asset key for this map.
* @param mapData {string} Data of this map. (a big 2d array, normally in csv)
* @param format {number} Format of this map data, available: Tilemap.FORMAT_CSV or Tilemap.FORMAT_TILED_JSON.
* @param resizeWorld {boolean} Resize the world bound automatically based on this tilemap?
* @param tileWidth {number} Width of tiles in this map.
* @param tileHeight {number} Height of tiles in this map.
*/
function Tilemap(game, key, mapData, format, resizeWorld, tileWidth, tileHeight) {
if (typeof resizeWorld === "undefined") { resizeWorld = true; }
if (typeof tileWidth === "undefined") { tileWidth = 0; }
if (typeof tileHeight === "undefined") { tileHeight = 0; }
_super.call(this, game);
/**
* Tilemap collision callback.
* @type {function}
*/
this.collisionCallback = null;
this.isGroup = false;
this.tiles = [];
this.layers = [];
this.mapFormat = format;
switch(format) {
case Tilemap.FORMAT_CSV:
this.parseCSV(game.cache.getText(mapData), key, tileWidth, tileHeight);
break;
case Tilemap.FORMAT_TILED_JSON:
this.parseTiledJSON(game.cache.getText(mapData), key);
break;
}
if(this.currentLayer && resizeWorld) {
this._game.world.setSize(this.currentLayer.widthInPixels, this.currentLayer.heightInPixels, true);
}
}
Tilemap.FORMAT_CSV = 0;
Tilemap.FORMAT_TILED_JSON = 1;
Tilemap.prototype.update = /**
* Inherited update method.
*/
function () {
};
Tilemap.prototype.render = /**
* Render this tilemap to a specific camera with specific offset.
* @param camera {Camera} The camera this tilemap will be rendered to.
* @param cameraOffsetX {number} X offset of the camera.
* @param cameraOffsetY {number} Y offset of the camera.
*/
function (camera, cameraOffsetX, cameraOffsetY) {
if(this.cameraBlacklist.indexOf(camera.ID) == -1) {
// Loop through the layers
for(var i = 0; i < this.layers.length; i++) {
this.layers[i].render(camera, cameraOffsetX, cameraOffsetY);
}
}
};
Tilemap.prototype.parseCSV = /**
* Parset csv map data and generate tiles.
* @param data {string} CSV map data.
* @param key {string} Asset key for tileset image.
* @param tileWidth {number} Width of its tile.
* @param tileHeight {number} Height of its tile.
*/
function (data, key, tileWidth, tileHeight) {
var layer = new Phaser.TilemapLayer(this._game, this, key, Tilemap.FORMAT_CSV, 'TileLayerCSV' + this.layers.length.toString(), tileWidth, tileHeight);
// Trim any rogue whitespace from the data
data = data.trim();
var rows = data.split("\n");
for(var i = 0; i < rows.length; i++) {
var column = rows[i].split(",");
if(column.length > 0) {
layer.addColumn(column);
}
}
layer.updateBounds();
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this.layers.push(layer);
this.generateTiles(tileQuantity);
};
Tilemap.prototype.parseTiledJSON = /**
* Parset JSON map data and generate tiles.
* @param data {string} JSON map data.
* @param key {string} Asset key for tileset image.
*/
function (data, key) {
// Trim any rogue whitespace from the data
data = data.trim();
var json = JSON.parse(data);
for(var i = 0; i < json.layers.length; i++) {
var layer = new Phaser.TilemapLayer(this._game, this, key, Tilemap.FORMAT_TILED_JSON, json.layers[i].name, json.tilewidth, json.tileheight);
layer.alpha = json.layers[i].opacity;
layer.visible = json.layers[i].visible;
layer.tileMargin = json.tilesets[0].margin;
layer.tileSpacing = json.tilesets[0].spacing;
var c = 0;
var row;
for(var t = 0; t < json.layers[i].data.length; t++) {
if(c == 0) {
row = [];
}
row.push(json.layers[i].data[t]);
c++;
if(c == json.layers[i].width) {
layer.addColumn(row);
c = 0;
}
}
layer.updateBounds();
var tileQuantity = layer.parseTileOffsets();
this.currentLayer = layer;
this.collisionLayer = layer;
this.layers.push(layer);
}
this.generateTiles(tileQuantity);
};
Tilemap.prototype.generateTiles = /**
* Create tiles of given quantity.
* @param qty {number} Quentity of tiles to be generated.
*/
function (qty) {
for(var i = 0; i < qty; i++) {
this.tiles.push(new Phaser.Tile(this._game, this, i, this.currentLayer.tileWidth, this.currentLayer.tileHeight));
}
};
Object.defineProperty(Tilemap.prototype, "widthInPixels", {
get: function () {
return this.currentLayer.widthInPixels;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tilemap.prototype, "heightInPixels", {
get: function () {
return this.currentLayer.heightInPixels;
},
enumerable: true,
configurable: true
});
Tilemap.prototype.setCollisionCallback = // Tile Collision
/**
* Set callback to be called when this tilemap collides.
* @param context {object} Callback will be called with this context.
* @param callback {function} Callback function.
*/
function (context, callback) {
this.collisionCallbackContext = context;
this.collisionCallback = callback;
};
Tilemap.prototype.setCollisionRange = /**
* Set collision configs of tiles in a range index.
* @param start {number} First index of tiles.
* @param end {number} Last index of tiles.
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
* @param resetCollisions {boolean} Reset collision flags before set.
* @param separateX {boolean} Enable seprate at x-axis.
* @param separateY {boolean} Enable seprate at y-axis.
*/
function (start, end, collision, resetCollisions, separateX, separateY) {
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
if (typeof separateX === "undefined") { separateX = true; }
if (typeof separateY === "undefined") { separateY = true; }
for(var i = start; i < end; i++) {
this.tiles[i].setCollision(collision, resetCollisions, separateX, separateY);
}
};
Tilemap.prototype.setCollisionByIndex = /**
* Set collision configs of tiles with given index.
* @param values {number[]} Index array which contains all tile indexes. The tiles with those indexes will be setup with rest parameters.
* @param collision {number} Bit field of flags. (see Tile.allowCollision)
* @param resetCollisions {boolean} Reset collision flags before set.
* @param separateX {boolean} Enable seprate at x-axis.
* @param separateY {boolean} Enable seprate at y-axis.
*/
function (values, collision, resetCollisions, separateX, separateY) {
if (typeof collision === "undefined") { collision = Phaser.Collision.ANY; }
if (typeof resetCollisions === "undefined") { resetCollisions = false; }
if (typeof separateX === "undefined") { separateX = true; }
if (typeof separateY === "undefined") { separateY = true; }
for(var i = 0; i < values.length; i++) {
this.tiles[values[i]].setCollision(collision, resetCollisions, separateX, separateY);
}
};
Tilemap.prototype.getTileByIndex = // Tile Management
/**
* Get the tile by its index.
* @param value {number} Index of the tile you want to get.
* @return {Tile} The tile with given index.
*/
function (value) {
if(this.tiles[value]) {
return this.tiles[value];
}
return null;
};
Tilemap.prototype.getTile = /**
* Get the tile located at specific position and layer.
* @param x {number} X position of this tile located.
* @param y {number} Y position of this tile located.
* @param [layer] {number} layer of this tile located.
* @return {Tile} The tile with specific properties.
*/
function (x, y, layer) {
if (typeof layer === "undefined") { layer = 0; }
return this.tiles[this.layers[layer].getTileIndex(x, y)];
};
Tilemap.prototype.getTileFromWorldXY = /**
* Get the tile located at specific position (in world coordinate) and layer. (thus you give a position of a point which is within the tile)
* @param x {number} X position of the point in target tile.
* @param x {number} Y position of the point in target tile.
* @param [layer] {number} layer of this tile located.
* @return {Tile} The tile with specific properties.
*/
function (x, y, layer) {
if (typeof layer === "undefined") { layer = 0; }
return this.tiles[this.layers[layer].getTileFromWorldXY(x, y)];
};
Tilemap.prototype.getTileFromInputXY = function (layer) {
if (typeof layer === "undefined") { layer = 0; }
return this.tiles[this.layers[layer].getTileFromWorldXY(this._game.input.getWorldX(), this._game.input.getWorldY())];
};
Tilemap.prototype.getTileOverlaps = /**
* Get tiles overlaps the given object.
* @param object {GameObject} Tiles you want to get that overlaps this.
* @return {array} Array with tiles informations. (Each contains x, y and the tile.)
*/
function (object) {
return this.currentLayer.getTileOverlaps(object);
};
Tilemap.prototype.collide = // COLLIDE
/**
* Check whether this tilemap collides with the given game object or group of objects.
* @param objectOrGroup {function} Target object of group you want to check.
* @param callback {function} This is called if objectOrGroup collides the tilemap.
* @param context {object} Callback will be called with this context.
* @return {boolean} Return true if this collides with given object, otherwise return false.
*/
function (objectOrGroup, callback, context) {
if (typeof objectOrGroup === "undefined") { objectOrGroup = null; }
if (typeof callback === "undefined") { callback = null; }
if (typeof context === "undefined") { context = null; }
if(callback !== null && context !== null) {
this.collisionCallback = callback;
this.collisionCallbackContext = context;
}
if(objectOrGroup == null) {
objectOrGroup = this._game.world.group;
}
// Group?
if(objectOrGroup.isGroup == false) {
this.collideGameObject(objectOrGroup);
} else {
objectOrGroup.forEachAlive(this, this.collideGameObject, true);
}
};
Tilemap.prototype.collideGameObject = /**
* Check whether this tilemap collides with the given game object.
* @param object {GameObject} Target object you want to check.
* @return {boolean} Return true if this collides with given object, otherwise return false.
*/
function (object) {
if(object !== this && object.immovable == false && object.exists == true && object.allowCollisions != Phaser.Collision.NONE) {
this._tempCollisionData = this.collisionLayer.getTileOverlaps(object);
if(this.collisionCallback !== null && this._tempCollisionData.length > 0) {
this.collisionCallback.call(this.collisionCallbackContext, object, this._tempCollisionData);
}
return true;
} else {
return false;
}
};
Tilemap.prototype.putTile = /**
* Set a tile to a specific layer.
* @param x {number} X position of this tile.
* @param y {number} Y position of this tile.
* @param index {number} The index of this tile type in the core map data.
* @param [layer] {number} which layer you want to set the tile to.
*/
function (x, y, index, layer) {
if (typeof layer === "undefined") { layer = 0; }
this.layers[layer].putTile(x, y, index);
};
return Tilemap;
})(Phaser.GameObject);
Phaser.Tilemap = Tilemap;
// Set current layer
// Set layer order?
// Delete tiles of certain type
// Erase tiles
})(Phaser || (Phaser = {}));
/// ScrollRegion
.
*
* @param x {number} X position in world coordinate.
* @param y {number} Y position in world coordinate.
* @param width {number} Width of this object.
* @param height {number} Height of this object.
* @param speedX {number} X-axis scrolling speed.
* @param speedY {number} Y-axis scrolling speed.
*/
function ScrollRegion(x, y, width, height, speedX, speedY) {
this._anchorWidth = 0;
this._anchorHeight = 0;
this._inverseWidth = 0;
this._inverseHeight = 0;
/**
* Will this region be rendered? (default to true)
* @type {boolean}
*/
this.visible = true;
// Our seamless scrolling quads
this._A = new Phaser.Quad(x, y, width, height);
this._B = new Phaser.Quad(x, y, width, height);
this._C = new Phaser.Quad(x, y, width, height);
this._D = new Phaser.Quad(x, y, width, height);
this._scroll = new Phaser.MicroPoint();
this._bounds = new Phaser.Quad(x, y, width, height);
this.scrollSpeed = new Phaser.MicroPoint(speedX, speedY);
}
ScrollRegion.prototype.update = /**
* Update region scrolling with tick time.
* @param delta {number} Elapsed time since last update.
*/
function (delta) {
this._scroll.x += this.scrollSpeed.x;
this._scroll.y += this.scrollSpeed.y;
if(this._scroll.x > this._bounds.right) {
this._scroll.x = this._bounds.x;
}
if(this._scroll.x < this._bounds.x) {
this._scroll.x = this._bounds.right;
}
if(this._scroll.y > this._bounds.bottom) {
this._scroll.y = this._bounds.y;
}
if(this._scroll.y < this._bounds.y) {
this._scroll.y = this._bounds.bottom;
}
// Anchor Dimensions
this._anchorWidth = (this._bounds.width - this._scroll.x) + this._bounds.x;
this._anchorHeight = (this._bounds.height - this._scroll.y) + this._bounds.y;
if(this._anchorWidth > this._bounds.width) {
this._anchorWidth = this._bounds.width;
}
if(this._anchorHeight > this._bounds.height) {
this._anchorHeight = this._bounds.height;
}
this._inverseWidth = this._bounds.width - this._anchorWidth;
this._inverseHeight = this._bounds.height - this._anchorHeight;
// Quad A
this._A.setTo(this._scroll.x, this._scroll.y, this._anchorWidth, this._anchorHeight);
// Quad B
this._B.y = this._scroll.y;
this._B.width = this._inverseWidth;
this._B.height = this._anchorHeight;
// Quad C
this._C.x = this._scroll.x;
this._C.width = this._anchorWidth;
this._C.height = this._inverseHeight;
// Quad D
this._D.width = this._inverseWidth;
this._D.height = this._inverseHeight;
};
ScrollRegion.prototype.render = /**
* Render this region to specific context.
* @param context {CanvasRenderingContext2D} Canvas context this region will be rendered to.
* @param texture {object} The texture to be rendered.
* @param dx {number} X position in world coordinate.
* @param dy {number} Y position in world coordinate.
* @param width {number} Width of this region to be rendered.
* @param height {number} Height of this region to be rendered.
*/
function (context, texture, dx, dy, dw, dh) {
if(this.visible == false) {
return;
}
// dx/dy are the world coordinates to render the FULL ScrollZone into.
// This ScrollRegion may be smaller than that and offset from the dx/dy coordinates.
this.crop(context, texture, this._A.x, this._A.y, this._A.width, this._A.height, dx, dy, dw, dh, 0, 0);
this.crop(context, texture, this._B.x, this._B.y, this._B.width, this._B.height, dx, dy, dw, dh, this._A.width, 0);
this.crop(context, texture, this._C.x, this._C.y, this._C.width, this._C.height, dx, dy, dw, dh, 0, this._A.height);
this.crop(context, texture, this._D.x, this._D.y, this._D.width, this._D.height, dx, dy, dw, dh, this._C.width, this._A.height);
//context.fillStyle = 'rgb(255,255,255)';
//context.font = '18px Arial';
//context.fillText('QuadA: ' + this._A.toString(), 32, 450);
//context.fillText('QuadB: ' + this._B.toString(), 32, 480);
//context.fillText('QuadC: ' + this._C.toString(), 32, 510);
//context.fillText('QuadD: ' + this._D.toString(), 32, 540);
};
ScrollRegion.prototype.crop = /**
* Crop part of the texture and render it to the given context.
* @param context {CanvasRenderingContext2D} Canvas context the texture will be rendered to.
* @param texture {object} Texture to be rendered.
* @param srcX {number} Target region top-left x coordinate in the texture.
* @param srcX {number} Target region top-left y coordinate in the texture.
* @param srcW {number} Target region width in the texture.
* @param srcH {number} Target region height in the texture.
* @param destX {number} Render region top-left x coordinate in the context.
* @param destX {number} Render region top-left y coordinate in the context.
* @param destW {number} Target region width in the context.
* @param destH {number} Target region height in the context.
* @param offsetX {number} X offset to the context.
* @param offsetY {number} Y offset to the context.
*/
function (context, texture, srcX, srcY, srcW, srcH, destX, destY, destW, destH, offsetX, offsetY) {
offsetX += destX;
offsetY += destY;
if(srcW > (destX + destW) - offsetX) {
srcW = (destX + destW) - offsetX;
}
if(srcH > (destY + destH) - offsetY) {
srcH = (destY + destH) - offsetY;
}
srcX = Math.floor(srcX);
srcY = Math.floor(srcY);
srcW = Math.floor(srcW);
srcH = Math.floor(srcH);
offsetX = Math.floor(offsetX + this._bounds.x);
offsetY = Math.floor(offsetY + this._bounds.y);
if(srcW > 0 && srcH > 0) {
context.drawImage(texture, srcX, srcY, srcW, srcH, offsetX, offsetY, srcW, srcH);
}
};
return ScrollRegion;
})();
Phaser.ScrollRegion = ScrollRegion;
})(Phaser || (Phaser = {}));
/// ScrollZone
.
*
* @param game {Phaser.Game} Current game instance.
* @param key {string} Asset key for image texture of this object.
* @param x {number} X position in world coordinate.
* @param y {number} Y position in world coordinate.
* @param [width] {number} width of this object.
* @param [height] {number} height of this object.
*/
function ScrollZone(game, key, x, y, width, height) {
if (typeof x === "undefined") { x = 0; }
if (typeof y === "undefined") { y = 0; }
if (typeof width === "undefined") { width = 0; }
if (typeof height === "undefined") { height = 0; }
_super.call(this, game, x, y, width, height);
/**
* If this zone is larger than texture image, this will be filled with a pattern of texture.
* @type {DynamicTexture}
*/
this._dynamicTexture = null;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
this._dx = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
this._dy = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
this._dw = 0;
/**
* Local rendering related temp vars to help avoid gc spikes.
* @type {number}
*/
this._dh = 0;
/**
* Flip this zone vertically? (default to false)
* @type {boolean}
*/
this.flipped = false;
this.regions = [];
if(this._game.cache.getImage(key)) {
this._texture = this._game.cache.getImage(key);
this.width = this._texture.width;
this.height = this._texture.height;
if(width > this._texture.width || height > this._texture.height) {
// Create our repeating texture (as the source image wasn't large enough for the requested size)
this.createRepeatingTexture(width, height);
this.width = width;
this.height = height;
}
// Create a default ScrollRegion at the requested size
this.addRegion(0, 0, this.width, this.height);
// If the zone is smaller than the image itself then shrink the bounds
if((width < this._texture.width || height < this._texture.height) && width !== 0 && height !== 0) {
this.width = width;
this.height = height;
}
}
}
ScrollZone.prototype.addRegion = /**
* Add a new region to this zone.
* @param x {number} X position of the new region.
* @param y {number} Y position of the new region.
* @param width {number} Width of the new region.
* @param height {number} Height of the new region.
* @param [speedX] {number} x-axis scrolling speed.
* @param [speedY] {number} y-axis scrolling speed.
* @return {ScrollRegion} The newly added region.
*/
function (x, y, width, height, speedX, speedY) {
if (typeof speedX === "undefined") { speedX = 0; }
if (typeof speedY === "undefined") { speedY = 0; }
if(x > this.width || y > this.height || x < 0 || y < 0 || (x + width) > this.width || (y + height) > this.height) {
throw Error('Invalid ScrollRegion defined. Cannot be larger than parent ScrollZone');
return;
}
this.currentRegion = new Phaser.ScrollRegion(x, y, width, height, speedX, speedY);
this.regions.push(this.currentRegion);
return this.currentRegion;
};
ScrollZone.prototype.setSpeed = /**
* Set scrolling speed of current region.
* @param x {number} X speed of current region.
* @param y {number} Y speed of current region.
*/
function (x, y) {
if(this.currentRegion) {
this.currentRegion.scrollSpeed.setTo(x, y);
}
return this;
};
ScrollZone.prototype.update = /**
* Update regions.
*/
function () {
for(var i = 0; i < this.regions.length; i++) {
this.regions[i].update(this._game.time.delta);
}
};
ScrollZone.prototype.inCamera = /**
* Check whether this zone is visible in a specific camera rectangle.
* @param camera {Rectangle} The rectangle you want to check.
* @return {boolean} Return true if bound of this zone intersects the given rectangle, otherwise return false.
*/
function (camera) {
if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
this._dx = this.frameBounds.x - (camera.x * this.scrollFactor.x);
this._dy = this.frameBounds.y - (camera.y * this.scrollFactor.x);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
return (camera.right > this._dx) && (camera.x < this._dx + this._dw) && (camera.bottom > this._dy) && (camera.y < this._dy + this._dh);
} else {
return camera.intersects(this.frameBounds, this.frameBounds.length);
}
};
ScrollZone.prototype.render = /**
* Render this zone object to a specific camera.
* @param camera {Camera} The camera this object will be render to.
* @param cameraOffsetX {number} X offset of camera.
* @param cameraOffsetY {number} Y offset of camera.
* @return Return false if not rendered, otherwise return true.
*/
function (camera, cameraOffsetX, cameraOffsetY) {
// Render checks
if(this.visible == false || this.scale.x == 0 || this.scale.y == 0 || this.alpha < 0.1 || this.cameraBlacklist.indexOf(camera.ID) !== -1 || this.inCamera(camera.worldView) == false) {
return false;
}
// Alpha
if(this.alpha !== 1) {
var globalAlpha = this.context.globalAlpha;
this.context.globalAlpha = this.alpha;
}
this._dx = cameraOffsetX + (this.frameBounds.topLeft.x - camera.worldView.x);
this._dy = cameraOffsetY + (this.frameBounds.topLeft.y - camera.worldView.y);
this._dw = this.frameBounds.width * this.scale.x;
this._dh = this.frameBounds.height * this.scale.y;
// Apply camera difference
if(this.scrollFactor.x !== 1.0 || this.scrollFactor.y !== 1.0) {
this._dx -= (camera.worldView.x * this.scrollFactor.x);
this._dy -= (camera.worldView.y * this.scrollFactor.y);
}
// Rotation - needs to work from origin point really, but for now from center
if(this.angle !== 0 || this.flipped == true) {
this.context.save();
this.context.translate(this._dx + (this._dw / 2), this._dy + (this._dh / 2));
if(this.angle !== 0) {
this.context.rotate(this.angle * (Math.PI / 180));
}
this._dx = -(this._dw / 2);
this._dy = -(this._dh / 2);
if(this.flipped == true) {
this.context.scale(-1, 1);
}
}
this._dx = Math.round(this._dx);
this._dy = Math.round(this._dy);
this._dw = Math.round(this._dw);
this._dh = Math.round(this._dh);
for(var i = 0; i < this.regions.length; i++) {
if(this._dynamicTexture) {
this.regions[i].render(this.context, this._dynamicTexture.canvas, this._dx, this._dy, this._dw, this._dh);
} else {
this.regions[i].render(this.context, this._texture, this._dx, this._dy, this._dw, this._dh);
}
}
if(globalAlpha > -1) {
this.context.globalAlpha = globalAlpha;
}
return true;
};
ScrollZone.prototype.createRepeatingTexture = /**
* Create repeating texture with _texture, and store it into the _dynamicTexture.
* Used to create texture when texture image is small than size of the zone.
*/
function (regionWidth, regionHeight) {
// Work out how many we'll need of the source image to make it tile properly
var tileWidth = Math.ceil(this._texture.width / regionWidth) * regionWidth;
var tileHeight = Math.ceil(this._texture.height / regionHeight) * regionHeight;
this._dynamicTexture = new Phaser.DynamicTexture(this._game, tileWidth, tileHeight);
this._dynamicTexture.context.rect(0, 0, tileWidth, tileHeight);
this._dynamicTexture.context.fillStyle = this._dynamicTexture.context.createPattern(this._texture, "repeat");
this._dynamicTexture.context.fill();
};
return ScrollZone;
})(Phaser.GameObject);
Phaser.ScrollZone = ScrollZone;
})(Phaser || (Phaser = {}));
/// Phaser.Game
object.
*
* @param callbackContext Which context will the callbacks be called with.
* @param parent {string} ID of its parent DOM element.
* @param width {number} The width of your game in game pixels.
* @param height {number} The height of your game in game pixels.
* @param initCallback {function} Init callback invoked when init default screen.
* @param createCallback {function} Create callback invoked when create default screen.
* @param updateCallback {function} Update callback invoked when update default screen.
* @param renderCallback {function} Render callback invoked when render default screen.
* @param destroyCallback {function} Destroy callback invoked when state is destroyed.
*/
function Game(callbackContext, parent, width, height, initCallback, createCallback, updateCallback, renderCallback, destroyCallback) {
if (typeof parent === "undefined") { parent = ''; }
if (typeof width === "undefined") { width = 800; }
if (typeof height === "undefined") { height = 600; }
if (typeof initCallback === "undefined") { initCallback = null; }
if (typeof createCallback === "undefined") { createCallback = null; }
if (typeof updateCallback === "undefined") { updateCallback = null; }
if (typeof renderCallback === "undefined") { renderCallback = null; }
if (typeof destroyCallback === "undefined") { destroyCallback = null; }
var _this = this;
/**
* Max allowable accumulation.
* @type {number}
*/
this._maxAccumulation = 32;
/**
* Total number of milliseconds elapsed since last update loop.
* @type {number}
*/
this._accumulator = 0;
/**
* Milliseconds of time per step of the game loop.
* @type {number}
*/
this._step = 0;
/**
* Whether loader complete loading or not.
* @type {boolean}
*/
this._loadComplete = false;
/**
* Game is paused?
* @type {boolean}
*/
this._paused = false;
/**
* The state to be switched to in the next frame.
* @type {State}
*/
this._pendingState = null;
/**
* The current State object (defaults to null)
* @type {State}
*/
this.state = null;
/**
* This will be called when init states. (loading assets...)
* @type {function}
*/
this.onInitCallback = null;
/**
* This will be called when create states. (setup states...)
* @type {function}
*/
this.onCreateCallback = null;
/**
* This will be called when update states.
* @type {function}
*/
this.onUpdateCallback = null;
/**
* This will be called when render states.
* @type {function}
*/
this.onRenderCallback = null;
/**
* This will be called when states paused.
* @type {function}
*/
this.onPausedCallback = null;
/**
* This will be called when the state is destroyed (i.e. swapping to a new state)
* @type {function}
*/
this.onDestroyCallback = null;
/**
* Whether the game engine is booted, aka available.
* @type {boolean}
*/
this.isBooted = false;
/**
* Is game running or paused?
* @type {boolean}
*/
this.isRunning = false;
this.callbackContext = callbackContext;
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
if(document.readyState === 'complete' || document.readyState === 'interactive') {
setTimeout(function () {
return _this.boot(parent, width, height);
});
} else {
document.addEventListener('DOMContentLoaded', function () {
return _this.boot(parent, width, height);
}, false);
window.addEventListener('load', function () {
return _this.boot(parent, width, height);
}, false);
}
}
Game.prototype.boot = /**
* Initialize engine sub modules and start the game.
* @param parent {string} ID of parent Dom element.
* @param width {number} Width of the game screen.
* @param height {number} Height of the game screen.
*/
function (parent, width, height) {
var _this = this;
if(this.isBooted == true) {
return;
}
if(!document.body) {
window.setTimeout(function () {
return _this.boot(parent, width, height);
}, 13);
} else {
this.device = new Phaser.Device();
this.motion = new Phaser.Motion(this);
this.math = new Phaser.GameMath(this);
this.stage = new Phaser.Stage(this, parent, width, height);
this.world = new Phaser.World(this, width, height);
this.add = new Phaser.GameObjectFactory(this);
this.sound = new Phaser.SoundManager(this);
this.cache = new Phaser.Cache(this);
this.collision = new Phaser.Collision(this);
this.loader = new Phaser.Loader(this, this.loadComplete);
this.time = new Phaser.Time(this);
this.tweens = new Phaser.TweenManager(this);
this.input = new Phaser.Input(this);
this.rnd = new Phaser.RandomDataGenerator([
(Date.now() * Math.random()).toString()
]);
this.verlet = new Phaser.Verlet.VerletManager(this, width, height);
this.framerate = 60;
this.isBooted = true;
this.input.start();
// Display the default game screen?
if(this.onInitCallback == null && this.onCreateCallback == null && this.onUpdateCallback == null && this.onRenderCallback == null && this._pendingState == null) {
this._raf = new Phaser.RequestAnimationFrame(this, this.bootLoop);
} else {
this.isRunning = true;
this._loadComplete = false;
this._raf = new Phaser.RequestAnimationFrame(this, this.loop);
if(this._pendingState) {
this.switchState(this._pendingState, false, false);
} else {
this.startState();
}
}
}
};
Game.prototype.loadComplete = /**
* Called when the loader has finished after init was run.
*/
function () {
this._loadComplete = true;
};
Game.prototype.bootLoop = /**
* Game loop method will be called when it's booting.
*/
function () {
this.tweens.update();
this.input.update();
this.stage.update();
};
Game.prototype.pausedLoop = /**
* Game loop method will be called when it's paused.
*/
function () {
this.tweens.update();
this.input.update();
this.stage.update();
if(this.onPausedCallback !== null) {
this.onPausedCallback.call(this.callbackContext);
}
};
Game.prototype.loop = /**
* Game loop method will be called when it's running.
*/
function () {
this.tweens.update();
this.input.update();
this.stage.update();
this.verlet.update();
this._accumulator += this.time.delta;
if(this._accumulator > this._maxAccumulation) {
this._accumulator = this._maxAccumulation;
}
while(this._accumulator >= this._step) {
this.time.elapsed = this.time.timeScale * (this._step / 1000);
this.world.update();
this._accumulator = this._accumulator - this._step;
}
if(this._loadComplete && this.onUpdateCallback) {
this.onUpdateCallback.call(this.callbackContext);
}
this.world.render();
if(this._loadComplete && this.onRenderCallback) {
this.onRenderCallback.call(this.callbackContext);
}
};
Game.prototype.startState = /**
* Start current state.
*/
function () {
if(this.onInitCallback !== null) {
this.loader.reset();
this.onInitCallback.call(this.callbackContext);
// Is the loader empty?
if(this.loader.queueSize == 0) {
if(this.onCreateCallback !== null) {
this.onCreateCallback.call(this.callbackContext);
}
this._loadComplete = true;
}
} else {
// No init? Then there was nothing to load either
if(this.onCreateCallback !== null) {
this.onCreateCallback.call(this.callbackContext);
}
this._loadComplete = true;
}
};
Game.prototype.setCallbacks = /**
* Set all state callbacks (init, create, update, render).
* @param initCallback {function} Init callback invoked when init state.
* @param createCallback {function} Create callback invoked when create state.
* @param updateCallback {function} Update callback invoked when update state.
* @param renderCallback {function} Render callback invoked when render state.
* @param destroyCallback {function} Destroy callback invoked when state is destroyed.
*/
function (initCallback, createCallback, updateCallback, renderCallback, destroyCallback) {
if (typeof initCallback === "undefined") { initCallback = null; }
if (typeof createCallback === "undefined") { createCallback = null; }
if (typeof updateCallback === "undefined") { updateCallback = null; }
if (typeof renderCallback === "undefined") { renderCallback = null; }
if (typeof destroyCallback === "undefined") { destroyCallback = null; }
this.onInitCallback = initCallback;
this.onCreateCallback = createCallback;
this.onUpdateCallback = updateCallback;
this.onRenderCallback = renderCallback;
this.onDestroyCallback = destroyCallback;
};
Game.prototype.switchState = /**
* Switch to a new State.
* @param state {State} The state you want to switch to.
* @param [clearWorld] {boolean} clear everything in the world? (Default to true)
* @param [clearCache] {boolean} clear asset cache? (Default to false and ONLY available when clearWorld=true)
*/
function (state, clearWorld, clearCache) {
if (typeof clearWorld === "undefined") { clearWorld = true; }
if (typeof clearCache === "undefined") { clearCache = false; }
if(this.isBooted == false) {
this._pendingState = state;
return;
}
// Destroy current state?
if(this.onDestroyCallback !== null) {
this.onDestroyCallback.call(this.callbackContext);
}
this.input.reset(true);
// Prototype?
if(typeof state === 'function') {
this.state = new state(this);
}
// Ok, have we got the right functions?
if(this.state['create'] || this.state['update']) {
this.callbackContext = this.state;
this.onInitCallback = null;
this.onCreateCallback = null;
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.onDestroyCallback = null;
// Bingo, let's set them up
if(this.state['init']) {
this.onInitCallback = this.state['init'];
}
if(this.state['create']) {
this.onCreateCallback = this.state['create'];
}
if(this.state['update']) {
this.onUpdateCallback = this.state['update'];
}
if(this.state['render']) {
this.onRenderCallback = this.state['render'];
}
if(this.state['paused']) {
this.onPausedCallback = this.state['paused'];
}
if(this.state['destroy']) {
this.onDestroyCallback = this.state['destroy'];
}
if(clearWorld) {
this.world.destroy();
if(clearCache == true) {
this.cache.destroy();
}
}
this._loadComplete = false;
this.startState();
} else {
throw new Error("Invalid State object given. Must contain at least a create or update function.");
}
};
Game.prototype.destroy = /**
* Nuke the whole game from orbit
*/
function () {
this.callbackContext = null;
this.onInitCallback = null;
this.onCreateCallback = null;
this.onUpdateCallback = null;
this.onRenderCallback = null;
this.onPausedCallback = null;
this.onDestroyCallback = null;
this.cache = null;
this.input = null;
this.loader = null;
this.sound = null;
this.stage = null;
this.time = null;
this.world = null;
this.isBooted = false;
};
Object.defineProperty(Game.prototype, "paused", {
get: function () {
return this._paused;
},
set: function (value) {
if(value == true && this._paused == false) {
this._paused = true;
this._raf.callback = this.pausedLoop;
} else if(value == false && this._paused == true) {
this._paused = false;
//this.time.time = window.performance.now ? (performance.now() + performance.timing.navigationStart) : Date.now();
this.input.reset();
if(this.isRunning == false) {
this._raf.callback = this.bootLoop;
} else {
this._raf.callback = this.loop;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(Game.prototype, "framerate", {
get: function () {
return 1000 / this._step;
},
set: function (value) {
this._step = 1000 / value;
if(this._maxAccumulation < this._step) {
this._maxAccumulation = this._step;
}
},
enumerable: true,
configurable: true
});
Game.prototype.collide = /**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
* @param object2 The second GameObject or Group to check.
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
* @param context The context in which the callbacks will be called
* @returns {boolean} true if the objects overlap, otherwise false.
*/
function (objectOrGroup1, objectOrGroup2, notifyCallback, context) {
if (typeof objectOrGroup1 === "undefined") { objectOrGroup1 = null; }
if (typeof objectOrGroup2 === "undefined") { objectOrGroup2 = null; }
if (typeof notifyCallback === "undefined") { notifyCallback = null; }
if (typeof context === "undefined") { context = this.callbackContext; }
return this.collision.overlap(objectOrGroup1, objectOrGroup2, notifyCallback, Phaser.Collision.separate, context);
};
Object.defineProperty(Game.prototype, "camera", {
get: function () {
return this.world.cameras.current;
},
enumerable: true,
configurable: true
});
return Game;
})();
Phaser.Game = Game;
})(Phaser || (Phaser = {}));
/// State
.
*/
function State(game) {
this.game = game;
this.add = game.add;
this.camera = game.camera;
this.cache = game.cache;
this.collision = game.collision;
this.input = game.input;
this.loader = game.loader;
this.math = game.math;
this.motion = game.motion;
this.sound = game.sound;
this.stage = game.stage;
this.time = game.time;
this.tweens = game.tweens;
this.world = game.world;
}
State.prototype.init = // Override these in your own States
/**
* Override this method to add some load operations.
* If you need to use the loader, you may need to use them here.
*/
function () {
};
State.prototype.create = /**
* This method is called after the game engine successfully switches states.
* Feel free to add any setup code here.(Do not load anything here, override init() instead)
*/
function () {
};
State.prototype.update = /**
* Put update logic here.
*/
function () {
};
State.prototype.render = /**
* Put render operations here.
*/
function () {
};
State.prototype.paused = /**
* This method will be called when game paused.
*/
function () {
};
State.prototype.destroy = /**
* This method will be called when the state is destroyed
*/
function () {
};
State.prototype.collide = /**
* Call this method to see if one object collids another.
* @return {boolean} Whether the given objects or groups collids.
*/
function (ObjectOrGroup1, ObjectOrGroup2, NotifyCallback) {
if (typeof ObjectOrGroup1 === "undefined") { ObjectOrGroup1 = null; }
if (typeof ObjectOrGroup2 === "undefined") { ObjectOrGroup2 = null; }
if (typeof NotifyCallback === "undefined") { NotifyCallback = null; }
return this.collision.overlap(ObjectOrGroup1, ObjectOrGroup2, NotifyCallback, Phaser.Collision.separate);
};
return State;
})();
Phaser.State = State;
})(Phaser || (Phaser = {}));