UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers.

1,738 lines (1,406 loc) 1.65 MB
/** * @author Richard Davey <rich@photonstorm.com> * @copyright 2014 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} * * @overview * * Phaser - http://phaser.io * * v2.1.2 "Whitebridge" - Built: Thu Oct 09 2014 16:16:06 * * By Richard Davey http://www.photonstorm.com @photonstorm * * Phaser is a fun, free and fast 2D game framework for making HTML5 games * for desktop and mobile web browsers, supporting Canvas and WebGL rendering. * * Phaser uses Pixi.js for rendering, created by Mat Groves http://matgroves.com @Doormat23 * Phaser uses p2.js for full-body physics, created by Stefan Hedman https://github.com/schteppe/p2.js @schteppe * Phaser contains a port of N+ Physics, converted by Richard Davey, original by http://www.metanetsoftware.com * * Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel, from which both Phaser * and my love of framework development originate. * * Follow development at http://phaser.io and on our forum * * "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 */ /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2014 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ (function(){ var root = this; /* global Phaser:true */ /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2014 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * @namespace Phaser */ var Phaser = Phaser || { VERSION: '2.1.2', GAMES: [], AUTO: 0, CANVAS: 1, WEBGL: 2, HEADLESS: 3, NONE: 0, LEFT: 1, RIGHT: 2, UP: 3, DOWN: 4, SPRITE: 0, BUTTON: 1, IMAGE: 2, GRAPHICS: 3, TEXT: 4, TILESPRITE: 5, BITMAPTEXT: 6, GROUP: 7, RENDERTEXTURE: 8, TILEMAP: 9, TILEMAPLAYER: 10, EMITTER: 11, POLYGON: 12, BITMAPDATA: 13, CANVAS_FILTER: 14, WEBGL_FILTER: 15, ELLIPSE: 16, SPRITEBATCH: 17, RETROFONT: 18, POINTER: 19, ROPE: 20, // The various blend modes supported by pixi / phaser blendModes: { NORMAL:0, ADD:1, MULTIPLY:2, SCREEN:3, OVERLAY:4, DARKEN:5, LIGHTEN:6, COLOR_DODGE:7, COLOR_BURN:8, HARD_LIGHT:9, SOFT_LIGHT:10, DIFFERENCE:11, EXCLUSION:12, HUE:13, SATURATION:14, COLOR:15, LUMINOSITY:16 }, // The scale modes scaleModes: { DEFAULT:0, LINEAR:0, NEAREST:1 } }; // We don't need this in Pixi, so we've removed it to save space // however the Stage object expects a reference to it, so here is a dummy entry. // Ensure that an existing PIXI.InteractionManager is not overriden - in case you're using your own PIXI library. PIXI.InteractionManager = PIXI.InteractionManager || function () {}; // Equally we're going to supress the Pixi console log, with their agreement. PIXI.dontSayHello = true; /* jshint supernew: true */ /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2014 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * @class Phaser.Utils * @static */ Phaser.Utils = { /** * Gets an objects property by string. * * @method Phaser.Utils.getProperty * @param {object} obj - The object to traverse. * @param {string} prop - The property whose value will be returned. * @return {*} the value of the property or null if property isn't found . */ getProperty: function(obj, prop) { var parts = prop.split('.'), last = parts.pop(), l = parts.length, i = 1, current = parts[0]; while (i < l && (obj = obj[current])) { current = parts[i]; i++; } if (obj) { return obj[last]; } else { return null; } }, /** * Sets an objects property by string. * * @method Phaser.Utils.setProperty * @param {object} obj - The object to traverse * @param {string} prop - The property whose value will be changed * @return {object} The object on which the property was set. */ setProperty: function(obj, prop, value) { var parts = prop.split('.'), last = parts.pop(), l = parts.length, i = 1, current = parts[0]; while (i < l && (obj = obj[current])) { current = parts[i]; i++; } if (obj) { obj[last] = value; } return obj; }, /** * Transposes the elements of the given Array. * * @method Phaser.Utils.transposeArray * @param {array} array - The array to transpose. * @return {array} The transposed array. */ transposeArray: function (array) { var result = new Array(array[0].length); for (var i = 0; i < array[0].length; i++) { result[i] = new Array(array.length - 1); for (var j = array.length - 1; j > -1; j--) { result[i][j] = array[j][i]; } } return result; }, /** * Rotates the given array. * Based on the routine from http://jsfiddle.net/MrPolywhirl/NH42z/ * * @method Phaser.Utils.rotateArray * @param {array} matrix - The array to rotate. * @param {number|string} direction - The amount to rotate. Either a number: 90, -90, 270, -270, 180 or a string: 'rotateLeft', 'rotateRight' or 'rotate180' * @return {array} The rotated array */ rotateArray: function (matrix, direction) { if (typeof direction !== 'string') { direction = ((direction % 360) + 360) % 360; } if (direction === 90 || direction === -270 || direction === 'rotateLeft') { matrix = Phaser.Utils.transposeArray(matrix); matrix = matrix.reverse(); } else if (direction === -90 || direction === 270 || direction === 'rotateRight') { matrix = matrix.reverse(); matrix = Phaser.Utils.transposeArray(matrix); } else if (Math.abs(direction) === 180 || direction === 'rotate180') { for (var i = 0; i < matrix.length; i++) { matrix[i].reverse(); } matrix = matrix.reverse(); } return matrix; }, /** * Get a unit dimension from a string. * * @method Phaser.Utils.parseDimension * @param {string|number} size - The size to parse. * @param {number} dimension - The window dimension to check. * @return {number} The parsed dimension. */ parseDimension: function (size, dimension) { var f = 0; var px = 0; if (typeof size === 'string') { // %? if (size.substr(-1) === '%') { f = parseInt(size, 10) / 100; if (dimension === 0) { px = window.innerWidth * f; } else { px = window.innerHeight * f; } } else { px = parseInt(size, 10); } } else { px = size; } return px; }, /** * A standard Fisher-Yates Array shuffle implementation. * @method Phaser.Utils.shuffle * @param {array} array - The array to shuffle. * @return {array} The shuffled array. */ shuffle: 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; }, /** * Javascript string pad http://www.webtoolkit.info/. * pad = the string to pad it out with (defaults to a space) * dir = 1 (left), 2 (right), 3 (both) * @method Phaser.Utils.pad * @param {string} str - The target string. * @param {number} len - The number of characters to be added. * @param {number} pad - The string to pad it out with (defaults to a space). * @param {number} [dir=3] The direction dir = 1 (left), 2 (right), 3 (both). * @return {string} The padded string */ pad: function (str, len, pad, dir) { if (typeof(len) == "undefined") { var len = 0; } if (typeof(pad) == "undefined") { var pad = ' '; } if (typeof(dir) == "undefined") { var dir = 3; } var padlen = 0; if (len + 1 >= str.length) { switch (dir) { case 1: str = new Array(len + 1 - str.length).join(pad) + str; break; case 3: var right = Math.ceil((padlen = len - str.length) / 2); var left = padlen - right; str = new Array(left+1).join(pad) + str + new Array(right+1).join(pad); break; default: str = str + new Array(len + 1 - str.length).join(pad); break; } } return str; }, /** * This is a slightly modified version of jQuery.isPlainObject. A plain object is an object whose internal class property is [object Object]. * @method Phaser.Utils.isPlainObject * @param {object} obj - The object to inspect. * @return {boolean} - true if the object is plain, otherwise false. */ isPlainObject: function (obj) { // Not plain objects: // - Any object or value whose internal [[Class]] property is not "[object Object]" // - DOM nodes // - window if (typeof(obj) !== "object" || obj.nodeType || obj === obj.window) { return false; } // Support: Firefox <20 // The try/catch suppresses exceptions thrown when attempting to access // the "constructor" property of certain host objects, ie. |window.location| // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 try { if (obj.constructor && !({}).hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")) { return false; } } catch (e) { return false; } // If the function hasn't returned already, we're confident that // |obj| is a plain object, created by {} or constructed with new Object return true; }, /** * This is a slightly modified version of http://api.jquery.com/jQuery.extend/ * @method Phaser.Utils.extend * @param {boolean} deep - Perform a deep copy? * @param {object} target - The target object to copy to. * @return {object} The extended object. */ extend: function () { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if (typeof target === "boolean") { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // extend Phaser if only one argument is passed if (length === i) { target = this; --i; } for (; i < length; i++) { // Only deal with non-null/undefined values if ((options = arguments[i]) != null) { // Extend the base object for (name in options) { src = target[name]; copy = options[name]; // Prevent never-ending loop if (target === copy) { continue; } // Recurse if we're merging plain objects or arrays if (deep && copy && (Phaser.Utils.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) { if (copyIsArray) { copyIsArray = false; clone = src && Array.isArray(src) ? src : []; } else { clone = src && Phaser.Utils.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[name] = Phaser.Utils.extend(deep, clone, copy); // Don't bring in undefined values } else if (copy !== undefined) { target[name] = copy; } } } } // Return the modified object return target; }, /** * Mixes the source object into the destination object, returning the newly modified destination object. * Based on original code by @mudcube * * @method Phaser.Utils.mixin * @param {object} from - The object to copy (the source object). * @param {object} to - The object to copy to (the destination object). * @return {object} The modified destination object. */ mixin: function (from, to) { if (!from || typeof (from) !== "object") { return to; } for (var key in from) { var o = from[key]; if (o.childNodes || o.cloneNode) { continue; } var type = typeof (from[key]); if (!from[key] || type !== "object") { to[key] = from[key]; } else { // Clone sub-object if (typeof (to[key]) === type) { to[key] = Phaser.Utils.mixin(from[key], to[key]); } else { to[key] = Phaser.Utils.mixin(from[key], new o.constructor()); } } } return to; } }; /** * A polyfill for Function.prototype.bind */ if (typeof Function.prototype.bind != 'function') { /* jshint freeze: false */ Function.prototype.bind = (function () { var slice = Array.prototype.slice; return function (thisArg) { var target = this, boundArgs = slice.call(arguments, 1); if (typeof target != 'function') { throw new TypeError(); } function bound() { var args = boundArgs.concat(slice.call(arguments)); target.apply(this instanceof bound ? this : thisArg, args); } bound.prototype = (function F(proto) { if (proto) { F.prototype = proto; } if (!(this instanceof F)) { return new F; } })(target.prototype); return bound; }; })(); } /** * A polyfill for Array.isArray */ if (!Array.isArray) { Array.isArray = function (arg) { return Object.prototype.toString.call(arg) == '[object Array]'; }; } /** * A polyfill for Array.forEach * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach */ if (!Array.prototype.forEach) { Array.prototype.forEach = function(fun /*, thisArg */) { "use strict"; if (this === void 0 || this === null) { throw new TypeError(); } var t = Object(this); var len = t.length >>> 0; if (typeof fun !== "function") { throw new TypeError(); } var thisArg = arguments.length >= 2 ? arguments[1] : void 0; for (var i = 0; i < len; i++) { if (i in t) { fun.call(thisArg, t[i], i, t); } } }; } /** * Low-budget Float32Array knock-off, suitable for use with P2.js in IE9 * Source: http://www.html5gamedevs.com/topic/5988-phaser-12-ie9/ * Cameron Foale (http://www.kibibu.com) */ if (typeof window.Uint32Array !== "function" && typeof window.Uint32Array !== "object") { var CheapArray = function(type) { var proto = new Array(); // jshint ignore:line window[type] = function(arg) { if (typeof(arg) === "number") { Array.call(this, arg); this.length = arg; for (var i = 0; i < this.length; i++) { this[i] = 0; } } else { Array.call(this, arg.length); this.length = arg.length; for (var i = 0; i < this.length; i++) { this[i] = arg[i]; } } }; window[type].prototype = proto; window[type].constructor = window[type]; }; CheapArray('Uint32Array'); // jshint ignore:line CheapArray('Int16Array'); // jshint ignore:line } /** * Also fix for the absent console in IE9 */ if (!window.console) { window.console = {}; window.console.log = window.console.assert = function(){}; window.console.warn = window.console.assert = function(){}; } /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2014 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * Creates a new Circle object with the center coordinate specified by the x and y parameters and the diameter specified by the diameter parameter. * If you call this function without parameters, a circle with x, y, diameter and radius properties set to 0 is created. * * @class Phaser.Circle * @constructor * @param {number} [x=0] - The x coordinate of the center of the circle. * @param {number} [y=0] - The y coordinate of the center of the circle. * @param {number} [diameter=0] - The diameter of the circle. */ Phaser.Circle = function (x, y, diameter) { x = x || 0; y = y || 0; diameter = diameter || 0; /** * @property {number} x - The x coordinate of the center of the circle. */ this.x = x; /** * @property {number} y - The y coordinate of the center of the circle. */ this.y = y; /** * @property {number} _diameter - The diameter of the circle. * @private */ this._diameter = diameter; if (diameter > 0) { /** * @property {number} _radius - The radius of the circle. * @private */ this._radius = diameter * 0.5; } else { this._radius = 0; } }; Phaser.Circle.prototype = { /** * The circumference of the circle. * @method Phaser.Circle#circumference * @return {number} */ circumference: function () { return 2 * (Math.PI * this._radius); }, /** * Sets the members of Circle to the specified values. * @method Phaser.Circle#setTo * @param {number} x - The x coordinate of the center of the circle. * @param {number} y - The y coordinate of the center of the circle. * @param {number} diameter - The diameter of the circle. * @return {Circle} This circle object. */ setTo: function (x, y, diameter) { this.x = x; this.y = y; this._diameter = diameter; this._radius = diameter * 0.5; return this; }, /** * Copies the x, y and diameter properties from any given object to this Circle. * @method Phaser.Circle#copyFrom * @param {any} source - The object to copy from. * @return {Circle} This Circle object. */ copyFrom: function (source) { return this.setTo(source.x, source.y, source.diameter); }, /** * Copies the x, y and diameter properties from this Circle to any given object. * @method Phaser.Circle#copyTo * @param {any} dest - The object to copy to. * @return {Object} This dest object. */ copyTo: function (dest) { dest.x = this.x; dest.y = this.y; dest.diameter = this._diameter; return dest; }, /** * Returns the distance from the center of the Circle object to the given object * (can be Circle, Point or anything with x/y properties) * @method Phaser.Circle#distance * @param {object} dest - The target object. Must have visible x and y properties that represent the center of the 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. */ distance: function (dest, round) { if (typeof round === "undefined") { round = false; } if (round) { return Phaser.Math.distanceRounded(this.x, this.y, dest.x, dest.y); } else { return Phaser.Math.distance(this.x, this.y, dest.x, dest.y); } }, /** * Returns a new Circle object with the same values for the x, y, width, and height properties as this Circle object. * @method Phaser.Circle#clone * @param {Phaser.Circle} output - Optional Circle object. If given the values will be set into the object, otherwise a brand new Circle object will be created and returned. * @return {Phaser.Circle} The cloned Circle object. */ clone: function (output) { if (typeof output === "undefined" || output === null) { output = new Phaser.Circle(this.x, this.y, this.diameter); } else { output.setTo(this.x, this.y, this.diameter); } return output; }, /** * Return true if the given x/y coordinates are within this Circle object. * @method Phaser.Circle#contains * @param {number} x - The X value of the coordinate to test. * @param {number} y - The Y value of the coordinate to test. * @return {boolean} True if the coordinates are within this circle, otherwise false. */ contains: function (x, y) { return Phaser.Circle.contains(this, x, y); }, /** * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. * @method Phaser.Circle#circumferencePoint * @param {number} angle - The angle in radians (unless asDegrees is true) to return the point from. * @param {boolean} [asDegrees=false] - Is the given angle in radians (false) or degrees (true)? * @param {Phaser.Point} [out] - An optional Point object to put the result in to. If none specified a new Point object will be created. * @return {Phaser.Point} The Point object holding the result. */ circumferencePoint: function (angle, asDegrees, out) { return Phaser.Circle.circumferencePoint(this, angle, asDegrees, out); }, /** * Adjusts the location of the Circle object, as determined by its center coordinate, by the specified amounts. * @method Phaser.Circle#offset * @param {number} dx - Moves the x value of the Circle object by this amount. * @param {number} dy - Moves the y value of the Circle object by this amount. * @return {Circle} This Circle object. */ offset: function (dx, dy) { this.x += dx; this.y += dy; return this; }, /** * Adjusts the location of the Circle object using a Point object as a parameter. This method is similar to the Circle.offset() method, except that it takes a Point object as a parameter. * @method Phaser.Circle#offsetPoint * @param {Point} point A Point object to use to offset this Circle object (or any valid object with exposed x and y properties). * @return {Circle} This Circle object. */ offsetPoint: function (point) { return this.offset(point.x, point.y); }, /** * Returns a string representation of this object. * @method Phaser.Circle#toString * @return {string} a string representation of the instance. */ toString: function () { return "[{Phaser.Circle (x=" + this.x + " y=" + this.y + " diameter=" + this.diameter + " radius=" + this.radius + ")}]"; } }; Phaser.Circle.prototype.constructor = Phaser.Circle; /** * The largest distance between any two points on the circle. The same as the radius * 2. * @name Phaser.Circle#diameter * @property {number} diameter - Gets or sets the diameter of the circle. */ Object.defineProperty(Phaser.Circle.prototype, "diameter", { get: function () { return this._diameter; }, set: function (value) { if (value > 0) { this._diameter = value; this._radius = value * 0.5; } } }); /** * The length of a line extending from the center of the circle to any point on the circle itself. The same as half the diameter. * @name Phaser.Circle#radius * @property {number} radius - Gets or sets the radius of the circle. */ Object.defineProperty(Phaser.Circle.prototype, "radius", { get: function () { return this._radius; }, set: function (value) { if (value > 0) { this._radius = value; this._diameter = value * 2; } } }); /** * The x coordinate of the leftmost point of the circle. Changing the left property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property. * @name Phaser.Circle#left * @propety {number} left - Gets or sets the value of the leftmost point of the circle. */ Object.defineProperty(Phaser.Circle.prototype, "left", { get: function () { return this.x - this._radius; }, set: function (value) { if (value > this.x) { this._radius = 0; this._diameter = 0; } else { this.radius = this.x - value; } } }); /** * The x coordinate of the rightmost point of the circle. Changing the right property of a Circle object has no effect on the x and y properties. However it does affect the diameter, whereas changing the x value does not affect the diameter property. * @name Phaser.Circle#right * @property {number} right - Gets or sets the value of the rightmost point of the circle. */ Object.defineProperty(Phaser.Circle.prototype, "right", { get: function () { return this.x + this._radius; }, set: function (value) { if (value < this.x) { this._radius = 0; this._diameter = 0; } else { this.radius = value - this.x; } } }); /** * The sum of the y minus the radius property. Changing the top property of a Circle object has no effect on the x and y properties, but does change the diameter. * @name Phaser.Circle#top * @property {number} top - Gets or sets the top of the circle. */ Object.defineProperty(Phaser.Circle.prototype, "top", { get: function () { return this.y - this._radius; }, set: function (value) { if (value > this.y) { this._radius = 0; this._diameter = 0; } else { this.radius = this.y - value; } } }); /** * The sum of the y and radius properties. Changing the bottom property of a Circle object has no effect on the x and y properties, but does change the diameter. * @name Phaser.Circle#bottom * @property {number} bottom - Gets or sets the bottom of the circle. */ Object.defineProperty(Phaser.Circle.prototype, "bottom", { get: function () { return this.y + this._radius; }, set: function (value) { if (value < this.y) { this._radius = 0; this._diameter = 0; } else { this.radius = value - this.y; } } }); /** * The area of this Circle. * @name Phaser.Circle#area * @property {number} area - The area of this circle. * @readonly */ Object.defineProperty(Phaser.Circle.prototype, "area", { get: function () { if (this._radius > 0) { return Math.PI * this._radius * this._radius; } else { return 0; } } }); /** * Determines whether or not this Circle object is empty. Will return a value of true if the Circle objects diameter is less than or equal to 0; otherwise false. * If set to true it will reset all of the Circle objects properties to 0. A Circle object is empty if its diameter is less than or equal to 0. * @name Phaser.Circle#empty * @property {boolean} empty - Gets or sets the empty state of the circle. */ Object.defineProperty(Phaser.Circle.prototype, "empty", { get: function () { return (this._diameter === 0); }, set: function (value) { if (value === true) { this.setTo(0, 0, 0); } } }); /** * Return true if the given x/y coordinates are within the Circle object. * @method Phaser.Circle.contains * @param {Phaser.Circle} a - The Circle to be checked. * @param {number} x - The X value of the coordinate to test. * @param {number} y - The Y value of the coordinate to test. * @return {boolean} True if the coordinates are within this circle, otherwise false. */ Phaser.Circle.contains = function (a, x, y) { // Check if x/y are within the bounds first if (a.radius > 0 && x >= a.left && x <= a.right && y >= a.top && y <= a.bottom) { var dx = (a.x - x) * (a.x - x); var dy = (a.y - y) * (a.y - y); return (dx + dy) <= (a.radius * a.radius); } else { return false; } }; /** * Determines whether the two Circle objects match. This method compares the x, y and diameter properties. * @method Phaser.Circle.equals * @param {Phaser.Circle} a - The first Circle object. * @param {Phaser.Circle} b - The second Circle object. * @return {boolean} A value of true if the object has exactly the same values for the x, y and diameter properties as this Circle object; otherwise false. */ Phaser.Circle.equals = function (a, b) { return (a.x == b.x && a.y == b.y && a.diameter == b.diameter); }; /** * Determines whether the two Circle objects intersect. * This method checks the radius distances between the two Circle objects to see if they intersect. * @method Phaser.Circle.intersects * @param {Phaser.Circle} a - The first Circle object. * @param {Phaser.Circle} b - The second Circle object. * @return {boolean} A value of true if the specified object intersects with this Circle object; otherwise false. */ Phaser.Circle.intersects = function (a, b) { return (Phaser.Math.distance(a.x, a.y, b.x, b.y) <= (a.radius + b.radius)); }; /** * Returns a Point object containing the coordinates of a point on the circumference of the Circle based on the given angle. * @method Phaser.Circle.circumferencePoint * @param {Phaser.Circle} a - The first Circle object. * @param {number} angle - The angle in radians (unless asDegrees is true) to return the point from. * @param {boolean} [asDegrees=false] - Is the given angle in radians (false) or degrees (true)? * @param {Phaser.Point} [out] - An optional Point object to put the result in to. If none specified a new Point object will be created. * @return {Phaser.Point} The Point object holding the result. */ Phaser.Circle.circumferencePoint = function (a, angle, asDegrees, out) { if (typeof asDegrees === "undefined") { asDegrees = false; } if (typeof out === "undefined") { out = new Phaser.Point(); } if (asDegrees === true) { angle = Phaser.Math.degToRad(angle); } out.x = a.x + a.radius * Math.cos(angle); out.y = a.y + a.radius * Math.sin(angle); return out; }; /** * Checks if the given Circle and Rectangle objects intersect. * @method Phaser.Circle.intersectsRectangle * @param {Phaser.Circle} c - The Circle object to test. * @param {Phaser.Rectangle} r - The Rectangle object to test. * @return {boolean} True if the two objects intersect, otherwise false. */ Phaser.Circle.intersectsRectangle = function (c, r) { var cx = Math.abs(c.x - r.x - r.halfWidth); var xDist = r.halfWidth + c.radius; if (cx > xDist) { return false; } var cy = Math.abs(c.y - r.y - r.halfHeight); var yDist = r.halfHeight + c.radius; if (cy > yDist) { return false; } if (cx <= r.halfWidth || cy <= r.halfHeight) { return true; } var xCornerDist = cx - r.halfWidth; var yCornerDist = cy - r.halfHeight; var xCornerDistSq = xCornerDist * xCornerDist; var yCornerDistSq = yCornerDist * yCornerDist; var maxCornerDistSq = c.radius * c.radius; return xCornerDistSq + yCornerDistSq <= maxCornerDistSq; }; // Because PIXI uses its own Circle, we'll replace it with ours to avoid duplicating code or confusion. PIXI.Circle = Phaser.Circle; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2014 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ /** * A Point object represents a location in a two-dimensional coordinate system, where x represents the horizontal axis and y represents the vertical axis. * The following code creates a point at (0,0): * `var myPoint = new Phaser.Point();` * You can also use them as 2D Vectors and you'll find different vector related methods in this class. * * @class Phaser.Point * @constructor * @param {number} [x=0] - The horizontal position of this Point. * @param {number} [y=0] - The vertical position of this Point. */ Phaser.Point = function (x, y) { x = x || 0; y = y || 0; /** * @property {number} x - The x value of the point. */ this.x = x; /** * @property {number} y - The y value of the point. */ this.y = y; }; Phaser.Point.prototype = { /** * Copies the x and y properties from any given object to this Point. * * @method Phaser.Point#copyFrom * @param {any} source - The object to copy from. * @return {Phaser.Point} This Point object. */ copyFrom: function (source) { return this.setTo(source.x, source.y); }, /** * Inverts the x and y values of this Point * * @method Phaser.Point#invert * @return {Phaser.Point} This Point object. */ invert: function () { return this.setTo(this.y, this.x); }, /** * Sets the `x` and `y` values of this Point object to the given values. * If you omit the `y` value then the `x` value will be applied to both, for example: * `Point.setTo(2)` is the same as `Point.setTo(2, 2)` * * @method Phaser.Point#setTo * @param {number} x - The horizontal value of this point. * @param {number} [y] - The vertical value of this point. If not given the x value will be used in its place. * @return {Phaser.Point} This Point object. Useful for chaining method calls. */ setTo: function (x, y) { this.x = x || 0; this.y = y || ( (y !== 0) ? this.x : 0 ); return this; }, /** * Sets the `x` and `y` values of this Point object to the given values. * If you omit the `y` value then the `x` value will be applied to both, for example: * `Point.setTo(2)` is the same as `Point.setTo(2, 2)` * * @method Phaser.Point#set * @param {number} x - The horizontal value of this point. * @param {number} [y] - The vertical value of this point. If not given the x value will be used in its place. * @return {Phaser.Point} This Point object. Useful for chaining method calls. */ set: function (x, y) { this.x = x || 0; this.y = y || ( (y !== 0) ? this.x : 0 ); return this; }, /** * Adds the given x and y values to this Point. * * @method Phaser.Point#add * @param {number} x - The value to add to Point.x. * @param {number} y - The value to add to Point.y. * @return {Phaser.Point} This Point object. Useful for chaining method calls. */ add: function (x, y) { this.x += x; this.y += y; return this; }, /** * Subtracts the given x and y values from this Point. * * @method Phaser.Point#subtract * @param {number} x - The value to subtract from Point.x. * @param {number} y - The value to subtract from Point.y. * @return {Phaser.Point} This Point object. Useful for chaining method calls. */ subtract: function (x, y) { this.x -= x; this.y -= y; return this; }, /** * Multiplies Point.x and Point.y by the given x and y values. Sometimes known as `Scale`. * * @method Phaser.Point#multiply * @param {number} x - The value to multiply Point.x by. * @param {number} y - The value to multiply Point.x by. * @return {Phaser.Point} This Point object. Useful for chaining method calls. */ multiply: function (x, y) { this.x *= x; this.y *= y; return this; }, /** * Divides Point.x and Point.y by the given x and y values. * * @method Phaser.Point#divide * @param {number} x - The value to divide Point.x by. * @param {number} y - The value to divide Point.x by. * @return {Phaser.Point} This Point object. Useful for chaining method calls. */ divide: function (x, y) { this.x /= x; this.y /= y; return this; }, /** * Clamps the x value of this Point to be between the given min and max. * * @method Phaser.Point#clampX * @param {number} min - The minimum value to clamp this Point to. * @param {number} max - The maximum value to clamp this Point to. * @return {Phaser.Point} This Point object. */ clampX: function (min, max) { this.x = Phaser.Math.clamp(this.x, min, max); return this; }, /** * Clamps the y value of this Point to be between the given min and max * * @method Phaser.Point#clampY * @param {number} min - The minimum value to clamp this Point to. * @param {number} max - The maximum value to clamp this Point to. * @return {Phaser.Point} This Point object. */ clampY: function (min, max) { this.y = Phaser.Math.clamp(this.y, min, max); return this; }, /** * Clamps this Point object values to be between the given min and max. * * @method Phaser.Point#clamp * @param {number} min - The minimum value to clamp this Point to. * @param {number} max - The maximum value to clamp this Point to. * @return {Phaser.Point} This Point object. */ clamp: function (min, max) { this.x = Phaser.Math.clamp(this.x, min, max); this.y = Phaser.Math.clamp(this.y, min, max); return this; }, /** * Creates a copy of the given Point. * * @method Phaser.Point#clone * @param {Phaser.Point} [output] Optional Point object. If given the values will be set into this object, otherwise a brand new Point object will be created and returned. * @return {Phaser.Point} The new Point object. */ clone: function (output) { if (typeof output === "undefined" || output === null) { output = new Phaser.Point(this.x, this.y); } else { output.setTo(this.x, this.y); } return output; }, /** * Copies the x and y properties from this Point to any given object. * * @method Phaser.Point#copyTo * @param {any} dest - The object to copy to. * @return {Object} The dest object. */ copyTo: function (dest) { dest.x = this.x; dest.y = this.y; return dest; }, /** * Returns the distance of this Point object to the given object (can be a Circle, Point or anything with x/y properties) * * @method Phaser.Point#distance * @param {object} dest - The target object. Must have visible x and y properties that represent the center of the 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. */ distance: function (dest, round) { return Phaser.Point.distance(this, dest, round); }, /** * Determines whether the given objects x/y values are equal to this Point object. * * @method Phaser.Point#equals * @param {Phaser.Point|any} a - The object to compare with this Point. * @return {boolean} A value of true if the x and y points are equal, otherwise false. */ equals: function (a) { return (a.x === this.x && a.y === this.y); }, /** * Returns the angle between this Point object and another object with public x and y properties. * * @method Phaser.Point#angle * @param {Phaser.Point|any} a - The object to get the angle from this Point to. * @param {boolean} [asDegrees=false] - Is the given angle in radians (false) or degrees (true)? * @return {number} The angle between the two objects. */ angle: function (a, asDegrees) { if (typeof asDegrees === 'undefined') { asDegrees = false; } if (asDegrees) { return Phaser.Math.radToDeg(Math.atan2(a.y - this.y, a.x - this.x)); } else { return Math.atan2(a.y - this.y, a.x - this.x); } }, /** * Returns the angle squared between this Point object and another object with public x and y properties. * * @method Phaser.Point#angleSq * @param {Phaser.Point|any} a - The object to get the angleSq from this Point to. * @return {number} The angleSq between the two objects. */ angleSq: function (a) { return this.subtract(a).angle(a.subtract(this)); }, /** * Rotates this Point around the x/y coordinates given to the desired angle. * * @method Phaser.Point#rotate * @param {number} x - The x coordinate of the anchor point. * @param {number} y - The y coordinate of the anchor point. * @param {number} angle - The angle in radians (unless asDegrees is true) to rotate the Point to. * @param {boolean} asDegrees - Is the given rotation in radians (false) or degrees (true)? * @param {number} [distance] - An optional distance constraint between the Point and the anchor. * @return {Phaser.Point} The modified point object. */ rotate: function (x, y, angle, asDegrees, distance) { return Phaser.Point.rotate(this, x, y, angle, asDegrees, distance); }, /** * Calculates the length of the Point object. * * @method Phaser.Point#getMagnitude * @return {number} The length of the Point. */ getMagnitude: function () { return Math.sqrt((this.x * this.x) + (this.y * this.y)); }, /** * Calculates the length squared of the Point object. * * @method Phaser.Point#getMagnitudeSq * @return {number} The length ^ 2 of the Point. */ getMagnitudeSq: function () { return (this.x * this.x) + (this.y * this.y); }, /** * Alters the length of the Point without changing the direction. * * @method Phaser.Point#setMagnitude * @param {number} magnitude - The desired magnitude of the resulting Point. * @return {Phaser.Point} This Point object. */ setMagnitude: function (magnitude) { return this.normalize().multiply(magnitude, magnitude); }, /** * Alters the Point object so that its length is 1, but it retains the same direction. * * @method Phaser.Point#normalize * @return {Phaser.Point} This Point object. */ normalize: function () { if (!this.isZero()) { var m = this.getMagnitude(); this.x /= m; this.y /= m; } return this; }, /** * Determine if this point is at 0,0. * * @method Phaser.Point#isZero * @return {boolean} True if this Point is 0,0, otherwise false. */ isZero: function () { return (this.x === 0 && this.y === 0); }, /** * The dot product of this and another Point object. * * @method Phaser.Point#dot * @param {Phaser.Point} a - The Point object to get the dot product combined with this Point. * @return {number} The result. */ dot: function (a) { return ((this.x * a.x) + (this.y * a.y)); }, /** * The cross product of this and another Point object. * * @method Phaser.Point#cross * @param {Phaser.Point} a - The Point object to get the cross product combined with this Point. * @return {number} The result. */ cross: function (a) { return ((this.x * a.y) - (this.y * a.x)); }, /** * Make this Point perpendicular (90 degrees rotation) * * @method Phaser.Point#perp * @return {Phaser.Point} This Point object. */ perp: function () { return this.setTo(-this.y, this.x); }, /** * Make this Point perpendicular (-90 degrees rotation) * * @method Phaser.Point#rperp * @return {Phaser.Point} This Point object. */ rperp: function () { return this.setTo(this.y, -this.x); }, /** * Right-hand normalize (make unit length) this Point. * * @method Phaser.Point#normalRightHand * @return {Phaser.Point} This Point object. */ normalRightHand: function () { return this.setTo(this.y * -1, this.x); }, /** * Returns a string representation of this object. * * @method Phaser.Point#toString * @return {string} A string representation of the instance. */ toString: function () { return '[{Point (x=' + this.x + ' y=' + this.y + ')}]'; } }; Phaser.Point.prototype.constructor = Phaser.Point; /** * Adds the coordinates of two points together to create a new point. * * @method Phaser.Point.add * @param {Phaser.Point} a - The first Point object. * @param {Phaser.Point} b - The second Point object. * @param {Phaser.Point} [out] - Optional Point to store the value in, if not supplied a new Point object will be created. * @return {Phaser.Point} The new Point object. */ Phaser.Point.add = function (a, b, out) { if (typeof out === "undefined") { out = new Phaser.Point(); } out.x = a.x + b.x; out.y = a.y + b.y; return out; }; /** * Subtracts the coordinates of two points to create a new point. * * @method Phaser.Point.subtract * @param {Phaser.Point} a - The first Point object. * @param {Phaser.Point} b - The second Point object. * @param {Phaser.Point} [out] - Optional Point to store the value in, if not supplied a new Point object will be created. * @return {Phaser.Point} The new Point object. */ Phaser.Point.subtract = function (a, b, out) { if (typeof out === "undefined") { out = new Phaser.Point(); } out.x = a.x - b.x; out.y = a.y - b.y; return out; }; /** * Multiplies the coordinates of two points to create a new point. * * @method Phaser.Point.multiply * @param {Phaser.Point} a - The first Point object. * @param {Phaser.Point} b - The second Point object. * @param {Ph