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 = {}));
diff --git a/Phaser/Cache.js b/Phaser/Cache.js
new file mode 100644
index 00000000..8b0437d1
--- /dev/null
+++ b/Phaser/Cache.js
@@ -0,0 +1,127 @@
+/// 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 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 = {}));
diff --git a/Phaser/FXManager.js b/Phaser/FXManager.js
new file mode 100644
index 00000000..1e9da3e2
--- /dev/null
+++ b/Phaser/FXManager.js
@@ -0,0 +1,150 @@
+/// + * 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 * Phaser.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 = {})); diff --git a/Phaser/GameObjectFactory.js b/Phaser/GameObjectFactory.js new file mode 100644 index 00000000..6f6f8f7b --- /dev/null +++ b/Phaser/GameObjectFactory.js @@ -0,0 +1,200 @@ +///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 = Phaser.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 Basics 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 Basics 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 = {}));
diff --git a/Phaser/Loader.js b/Phaser/Loader.js
new file mode 100644
index 00000000..532e9bdc
--- /dev/null
+++ b/Phaser/Loader.js
@@ -0,0 +1,309 @@
+/// 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 = {})); diff --git a/Phaser/SignalBinding.js b/Phaser/SignalBinding.js new file mode 100644 index 00000000..760df524 --- /dev/null +++ b/Phaser/SignalBinding.js @@ -0,0 +1,113 @@ +///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 = {})); diff --git a/Phaser/SoundManager.js b/Phaser/SoundManager.js new file mode 100644 index 00000000..76e584e1 --- /dev/null +++ b/Phaser/SoundManager.js @@ -0,0 +1,85 @@ +///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 = {}));
diff --git a/Phaser/TweenManager.js b/Phaser/TweenManager.js
new file mode 100644
index 00000000..f9889ea0
--- /dev/null
+++ b/Phaser/TweenManager.js
@@ -0,0 +1,58 @@
+/// 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 MicroPoint(-100, -100);
+ this.maxParticleSpeed = new MicroPoint(100, 100);
+ this.minRotation = -360;
+ this.maxRotation = 360;
+ this.gravity = 0;
+ this.particleClass = null;
+ this.particleDrag = new 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 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 = {}));
diff --git a/Phaser/gameobjects/GameObject.js b/Phaser/gameobjects/GameObject.js
new file mode 100644
index 00000000..6826946d
--- /dev/null
+++ b/Phaser/gameobjects/GameObject.js
@@ -0,0 +1,534 @@
+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 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 MicroPoint(1, 1);
+ this.last = new 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 = Collision.NONE;
+ this.wasTouching = Collision.NONE;
+ this.allowCollisions = Collision.ANY;
+ this.velocity = new MicroPoint();
+ this.acceleration = new MicroPoint();
+ this.drag = new MicroPoint();
+ this.maxVelocity = new MicroPoint(10000, 10000);
+ this.angle = 0;
+ this.angularVelocity = 0;
+ this.angularAcceleration = 0;
+ this.angularDrag = 0;
+ this.maxAngular = 10000;
+ this.cameraBlacklist = [];
+ this.scrollFactor = new MicroPoint(1, 1);
+ this.collisionMask = new 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 == Phaser.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 = Phaser.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 = {}));
diff --git a/Phaser/gameobjects/GeomSprite.js b/Phaser/gameobjects/GeomSprite.js
new file mode 100644
index 00000000..4d08929f
--- /dev/null
+++ b/Phaser/gameobjects/GeomSprite.js
@@ -0,0 +1,449 @@
+var __extends = this.__extends || function (d, b) {
+ function __() { this.constructor = d; }
+ __.prototype = b.prototype;
+ d.prototype = new __();
+};
+/// 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 = Phaser.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 = Phaser.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 = Phaser.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 = Phaser.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 = Phaser.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 = Phaser.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 = Phaser.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 = Phaser.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 Vector2(this.x, this.y), points);
+ this.type = Phaser.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 == Phaser.GeomSprite.UNASSIGNED) {
+ return;
+ } else if(this.type == Phaser.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 == Phaser.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 == Phaser.GeomSprite.POINT) {
+ this.point.x = this.x;
+ this.point.y = this.y;
+ } else if(this.type == Phaser.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 == Phaser.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 == Phaser.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 == Phaser.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 == Phaser.GeomSprite.POINT) {
+ this.context.fillRect(this._dx, this._dy, 2, 2);
+ } else if(this.type == Phaser.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 == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.CIRCLE) {
+ return Phaser.Collision.circleToCircle(this.circle, source.circle).result;
+ }
+ // Circle vs. Rect
+ if(this.type == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.RECTANGLE) {
+ return Phaser.Collision.circleToRectangle(this.circle, source.rect).result;
+ }
+ // Circle vs. Point
+ if(this.type == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.POINT) {
+ return Phaser.Collision.circleContainsPoint(this.circle, source.point).result;
+ }
+ // Circle vs. Line
+ if(this.type == Phaser.GeomSprite.CIRCLE && source.type == Phaser.GeomSprite.LINE) {
+ return Phaser.Collision.lineToCircle(source.line, this.circle).result;
+ }
+ // Rect vs. Rect
+ if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.RECTANGLE) {
+ return Phaser.Collision.rectangleToRectangle(this.rect, source.rect).result;
+ }
+ // Rect vs. Circle
+ if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.CIRCLE) {
+ return Phaser.Collision.circleToRectangle(source.circle, this.rect).result;
+ }
+ // Rect vs. Point
+ if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.POINT) {
+ return Phaser.Collision.pointToRectangle(source.point, this.rect).result;
+ }
+ // Rect vs. Line
+ if(this.type == Phaser.GeomSprite.RECTANGLE && source.type == Phaser.GeomSprite.LINE) {
+ return Phaser.Collision.lineToRectangle(source.line, this.rect).result;
+ }
+ // Point vs. Point
+ if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.POINT) {
+ return this.point.equals(source.point);
+ }
+ // Point vs. Circle
+ if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.CIRCLE) {
+ return Phaser.Collision.circleContainsPoint(source.circle, this.point).result;
+ }
+ // Point vs. Rect
+ if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.RECTANGLE) {
+ return Phaser.Collision.pointToRectangle(this.point, source.rect).result;
+ }
+ // Point vs. Line
+ if(this.type == Phaser.GeomSprite.POINT && source.type == Phaser.GeomSprite.LINE) {
+ return source.line.isPointOnLine(this.point.x, this.point.y);
+ }
+ // Line vs. Line
+ if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.LINE) {
+ return Phaser.Collision.lineSegmentToLineSegment(this.line, source.line).result;
+ }
+ // Line vs. Circle
+ if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.CIRCLE) {
+ return Phaser.Collision.lineToCircle(this.line, source.circle).result;
+ }
+ // Line vs. Rect
+ if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.RECTANGLE) {
+ return Phaser.Collision.lineSegmentToRectangle(this.line, source.rect).result;
+ }
+ // Line vs. Point
+ if(this.type == Phaser.GeomSprite.LINE && source.type == Phaser.GeomSprite.POINT) {
+ return this.line.isPointOnLine(source.point.x, source.point.y);
+ }
+ return false;
+ };
+ return GeomSprite;
+ })(Phaser.GameObject);
+ Phaser.GeomSprite = GeomSprite;
+})(Phaser || (Phaser = {}));
diff --git a/Phaser/gameobjects/Particle.js b/Phaser/gameobjects/Particle.js
new file mode 100644
index 00000000..fbb95484
--- /dev/null
+++ b/Phaser/gameobjects/Particle.js
@@ -0,0 +1,74 @@
+var __extends = this.__extends || function (d, b) {
+ function __() { this.constructor = d; }
+ __.prototype = b.prototype;
+ d.prototype = new __();
+};
+/// 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 = {}));
diff --git a/Phaser/gameobjects/Tilemap.js b/Phaser/gameobjects/Tilemap.js
new file mode 100644
index 00000000..e9e3170e
--- /dev/null
+++ b/Phaser/gameobjects/Tilemap.js
@@ -0,0 +1,314 @@
+var __extends = this.__extends || function (d, b) {
+ function __() { this.constructor = d; }
+ __.prototype = b.prototype;
+ d.prototype = new __();
+};
+/// 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, Phaser.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, Phaser.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 = {}));
diff --git a/Phaser/geom/IntersectResult.js b/Phaser/geom/IntersectResult.js
new file mode 100644
index 00000000..f9e2e865
--- /dev/null
+++ b/Phaser/geom/IntersectResult.js
@@ -0,0 +1,45 @@
+/// 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 = {}));
diff --git a/Phaser/system/LinkedList.js b/Phaser/system/LinkedList.js
new file mode 100644
index 00000000..c2846f50
--- /dev/null
+++ b/Phaser/system/LinkedList.js
@@ -0,0 +1,30 @@
+/// 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 = {}));
diff --git a/Phaser/system/QuadTree.js b/Phaser/system/QuadTree.js
new file mode 100644
index 00000000..7828f2b6
--- /dev/null
+++ b/Phaser/system/QuadTree.js
@@ -0,0 +1,355 @@
+var __extends = this.__extends || function (d, b) {
+ function __() { this.constructor = d; }
+ __.prototype = b.prototype;
+ d.prototype = new __();
+};
+/// 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, Phaser.QuadTree.A_LIST);
+ if(objectOrGroup2 != null) {
+ this.add(objectOrGroup2, Phaser.QuadTree.B_LIST);
+ Phaser.QuadTree._useBothLists = true;
+ } else {
+ Phaser.QuadTree._useBothLists = false;
+ }
+ Phaser.QuadTree._notifyCallback = notifyCallback;
+ Phaser.QuadTree._processingCallback = processCallback;
+ Phaser.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) {
+ Phaser.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 {
+ Phaser.QuadTree._object = basic;
+ if(Phaser.QuadTree._object.exists && Phaser.QuadTree._object.allowCollisions) {
+ this.addObject();
+ }
+ }
+ }
+ }
+ } else {
+ Phaser.QuadTree._object = objectOrGroup;
+ if(Phaser.QuadTree._object.exists && Phaser.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 >= Phaser.QuadTree._object.collisionMask.x) && (this._rightEdge <= Phaser.QuadTree._object.collisionMask.right) && (this._topEdge >= Phaser.QuadTree._object.collisionMask.y) && (this._bottomEdge <= Phaser.QuadTree._object.collisionMask.bottom))) {
+ this.addToList();
+ return;
+ }
+ //See if the selected object fits completely inside any of the quadrants
+ if((Phaser.QuadTree._object.collisionMask.x > this._leftEdge) && (Phaser.QuadTree._object.collisionMask.right < this._midpointX)) {
+ if((Phaser.QuadTree._object.collisionMask.y > this._topEdge) && (Phaser.QuadTree._object.collisionMask.bottom < this._midpointY)) {
+ if(this._northWestTree == null) {
+ this._northWestTree = new Phaser.QuadTree(this._leftEdge, this._topEdge, this._halfWidth, this._halfHeight, this);
+ }
+ this._northWestTree.addObject();
+ return;
+ }
+ if((Phaser.QuadTree._object.collisionMask.y > this._midpointY) && (Phaser.QuadTree._object.collisionMask.bottom < this._bottomEdge)) {
+ if(this._southWestTree == null) {
+ this._southWestTree = new Phaser.QuadTree(this._leftEdge, this._midpointY, this._halfWidth, this._halfHeight, this);
+ }
+ this._southWestTree.addObject();
+ return;
+ }
+ }
+ if((Phaser.QuadTree._object.collisionMask.x > this._midpointX) && (Phaser.QuadTree._object.collisionMask.right < this._rightEdge)) {
+ if((Phaser.QuadTree._object.collisionMask.y > this._topEdge) && (Phaser.QuadTree._object.collisionMask.bottom < this._midpointY)) {
+ if(this._northEastTree == null) {
+ this._northEastTree = new Phaser.QuadTree(this._midpointX, this._topEdge, this._halfWidth, this._halfHeight, this);
+ }
+ this._northEastTree.addObject();
+ return;
+ }
+ if((Phaser.QuadTree._object.collisionMask.y > this._midpointY) && (Phaser.QuadTree._object.collisionMask.bottom < this._bottomEdge)) {
+ if(this._southEastTree == null) {
+ this._southEastTree = new Phaser.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((Phaser.QuadTree._object.collisionMask.right > this._leftEdge) && (Phaser.QuadTree._object.collisionMask.x < this._midpointX) && (Phaser.QuadTree._object.collisionMask.bottom > this._topEdge) && (Phaser.QuadTree._object.collisionMask.y < this._midpointY)) {
+ if(this._northWestTree == null) {
+ this._northWestTree = new Phaser.QuadTree(this._leftEdge, this._topEdge, this._halfWidth, this._halfHeight, this);
+ }
+ this._northWestTree.addObject();
+ }
+ if((Phaser.QuadTree._object.collisionMask.right > this._midpointX) && (Phaser.QuadTree._object.collisionMask.x < this._rightEdge) && (Phaser.QuadTree._object.collisionMask.bottom > this._topEdge) && (Phaser.QuadTree._object.collisionMask.y < this._midpointY)) {
+ if(this._northEastTree == null) {
+ this._northEastTree = new Phaser.QuadTree(this._midpointX, this._topEdge, this._halfWidth, this._halfHeight, this);
+ }
+ this._northEastTree.addObject();
+ }
+ if((Phaser.QuadTree._object.collisionMask.right > this._midpointX) && (Phaser.QuadTree._object.collisionMask.x < this._rightEdge) && (Phaser.QuadTree._object.collisionMask.bottom > this._midpointY) && (Phaser.QuadTree._object.collisionMask.y < this._bottomEdge)) {
+ if(this._southEastTree == null) {
+ this._southEastTree = new Phaser.QuadTree(this._midpointX, this._midpointY, this._halfWidth, this._halfHeight, this);
+ }
+ this._southEastTree.addObject();
+ }
+ if((Phaser.QuadTree._object.collisionMask.right > this._leftEdge) && (Phaser.QuadTree._object.collisionMask.x < this._midpointX) && (Phaser.QuadTree._object.collisionMask.bottom > this._midpointY) && (Phaser.QuadTree._object.collisionMask.y < this._bottomEdge)) {
+ if(this._southWestTree == null) {
+ this._southWestTree = new Phaser.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(Phaser.QuadTree._list == Phaser.QuadTree.A_LIST) {
+ if(this._tailA.object != null) {
+ ot = this._tailA;
+ this._tailA = new Phaser.LinkedList();
+ ot.next = this._tailA;
+ }
+ this._tailA.object = Phaser.QuadTree._object;
+ } else {
+ if(this._tailB.object != null) {
+ ot = this._tailB;
+ this._tailB = new Phaser.LinkedList();
+ ot.next = this._tailB;
+ }
+ this._tailB.object = Phaser.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) {
+ Phaser.QuadTree._object = iterator.object;
+ if(Phaser.QuadTree._useBothLists) {
+ Phaser.QuadTree._iterator = this._headB;
+ } else {
+ Phaser.QuadTree._iterator = iterator.next;
+ }
+ if(Phaser.QuadTree._object.exists && (Phaser.QuadTree._object.allowCollisions > 0) && (Phaser.QuadTree._iterator != null) && (Phaser.QuadTree._iterator.object != null) && Phaser.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(Phaser.QuadTree._iterator != null) {
+ if(!Phaser.QuadTree._object.exists || (Phaser.QuadTree._object.allowCollisions <= 0)) {
+ break;
+ }
+ checkObject = Phaser.QuadTree._iterator.object;
+ if((Phaser.QuadTree._object === checkObject) || !checkObject.exists || (checkObject.allowCollisions <= 0)) {
+ Phaser.QuadTree._iterator = Phaser.QuadTree._iterator.next;
+ continue;
+ }
+ if(Phaser.QuadTree._object.collisionMask.checkHullIntersection(checkObject.collisionMask)) {
+ //Execute callback functions if they exist
+ if((Phaser.QuadTree._processingCallback == null) || Phaser.QuadTree._processingCallback(Phaser.QuadTree._object, checkObject)) {
+ overlapProcessed = true;
+ }
+ if(overlapProcessed && (Phaser.QuadTree._notifyCallback != null)) {
+ if(Phaser.QuadTree._callbackContext !== null) {
+ Phaser.QuadTree._notifyCallback.call(Phaser.QuadTree._callbackContext, Phaser.QuadTree._object, checkObject);
+ } else {
+ Phaser.QuadTree._notifyCallback(Phaser.QuadTree._object, checkObject);
+ }
+ }
+ }
+ Phaser.QuadTree._iterator = Phaser.QuadTree._iterator.next;
+ }
+ return overlapProcessed;
+ };
+ return QuadTree;
+ })(Phaser.Rectangle);
+ Phaser.QuadTree = QuadTree;
+})(Phaser || (Phaser = {}));
diff --git a/Phaser/system/RandomDataGenerator.js b/Phaser/system/RandomDataGenerator.js
new file mode 100644
index 00000000..d891ab0e
--- /dev/null
+++ b/Phaser/system/RandomDataGenerator.js
@@ -0,0 +1,227 @@
+/// 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 = 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 = {}));
diff --git a/Phaser/system/TilemapLayer.js b/Phaser/system/TilemapLayer.js
new file mode 100644
index 00000000..f789fba9
--- /dev/null
+++ b/Phaser/system/TilemapLayer.js
@@ -0,0 +1,455 @@
+/// 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 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 = {}));
diff --git a/Phaser/system/Tween.js b/Phaser/system/Tween.js
new file mode 100644
index 00000000..8159d3ab
--- /dev/null
+++ b/Phaser/system/Tween.js
@@ -0,0 +1,173 @@
+/// A complementary hue is one directly opposite the color given on the color wheel
- *Value returned in 0xAARRGGBB format with Alpha set to 255.
- * - * @param color The color to base the harmony on - * - * @return 0xAARRGGBB format color value - */ + * Returns a Complementary Color Harmony for the given color. + *A complementary hue is one directly opposite the color given on the color wheel
+ *Value returned in 0xAARRGGBB format with Alpha set to 255.
+ * + * @method getComplementHarmony + * @param {Number} color The color to base the harmony on. + * @return {Number} 0xAARRGGBB format color value. + */ public static getComplementHarmony(color: number): number { var hsv: any = Phaser.ColorUtils.RGBtoHSV(color); @@ -94,15 +111,15 @@ module Phaser { } /** - * Returns an Analogous Color Harmony for the given color. - *An Analogous harmony are hues adjacent to each other on the color wheel
- *Values returned in 0xAARRGGBB format with Alpha set to 255.
- * - * @param color The color to base the harmony on - * @param threshold Control how adjacent the colors will be (default +- 30 degrees) - * - * @return Object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) - */ + * Returns an Analogous Color Harmony for the given color. + *An Analogous harmony are hues adjacent to each other on the color wheel
+ *Values returned in 0xAARRGGBB format with Alpha set to 255.
+ * + * @method getAnalogousHarmony + * @param {Number} color The color to base the harmony on. + * @param {Number} threshold Control how adjacent the colors will be (default +- 30 degrees) + * @return {Object} Object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) + */ public static getAnalogousHarmony(color: number, threshold: number = 30) { var hsv: any = Phaser.ColorUtils.RGBtoHSV(color); @@ -120,15 +137,15 @@ module Phaser { } /** - * Returns an Split Complement Color Harmony for the given color. - *A Split Complement harmony are the two hues on either side of the color's Complement
- *Values returned in 0xAARRGGBB format with Alpha set to 255.
- * - * @param color The color to base the harmony on - * @param threshold Control how adjacent the colors will be to the Complement (default +- 30 degrees) - * - * @return Object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) - */ + * Returns an Split Complement Color Harmony for the given color. + *A Split Complement harmony are the two hues on either side of the color's Complement
+ *Values returned in 0xAARRGGBB format with Alpha set to 255.
+ * + * @method getSplitComplementHarmony + * @param {Number} color The color to base the harmony on + * @param {Number} threshold Control how adjacent the colors will be to the Complement (default +- 30 degrees) + * @return {Object} An object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) + */ public static getSplitComplementHarmony(color: number, threshold: number = 30): any { var hsv: any = Phaser.ColorUtils.RGBtoHSV(color); @@ -147,14 +164,14 @@ module Phaser { } /** - * Returns a Triadic Color Harmony for the given color. - *A Triadic harmony are 3 hues equidistant from each other on the color wheel
- *Values returned in 0xAARRGGBB format with Alpha set to 255.
- * - * @param color The color to base the harmony on - * - * @return Object containing 3 properties: color1 (the original color), color2 and color3 (the equidistant colors) - */ + * Returns a Triadic Color Harmony for the given color. + *A Triadic harmony are 3 hues equidistant from each other on the color wheel
+ *Values returned in 0xAARRGGBB format with Alpha set to 255.
+ * + * @method getTriadicHarmony + * @param {Number} color The color to base the harmony on. + * @return {Object} An Object containing 3 properties: color1 (the original color), color2 and color3 (the equidistant colors) + */ public static getTriadicHarmony(color: number): any { var hsv: any = Phaser.ColorUtils.RGBtoHSV(color); @@ -167,13 +184,13 @@ module Phaser { } /** - * Returns a string containing handy information about the given color including string hex value, - * RGB format information and HSL information. Each section starts on a newline, 3 lines in total. - * - * @param color A color value in the format 0xAARRGGBB - * - * @return string containing the 3 lines of information - */ + * Returns a string containing handy information about the given color including string hex value, + * RGB format information and HSL information. Each section starts on a newline, 3 lines in total. + * + * @method getColorInfo + * @param {Number} color A color value in the format 0xAARRGGBB + * @return {String} string containing the 3 lines of information + */ public static getColorInfo(color: number): string { var argb: any = Phaser.ColorUtils.getRGB(color); @@ -193,12 +210,12 @@ module Phaser { } /** - * Return a string representation of the color in the format 0xAARRGGBB - * - * @param color The color to get the string representation for - * - * @return A string of length 10 characters in the format 0xAARRGGBB - */ + * Return a string representation of the color in the format 0xAARRGGBB + * + * @method RGBtoHexstring + * @param {Number} color The color to get the string representation for + * @return {String A string of length 10 characters in the format 0xAARRGGBB + */ public static RGBtoHexstring(color: number): string { var argb: any = Phaser.ColorUtils.getRGB(color); @@ -208,12 +225,12 @@ module Phaser { } /** - * Return a string representation of the color in the format #RRGGBB - * - * @param color The color to get the string representation for - * - * @return A string of length 10 characters in the format 0xAARRGGBB - */ + * Return a string representation of the color in the format #RRGGBB + * + * @method RGBtoWebstring + * @param {Number} color The color to get the string representation for + * @return {String} A string of length 10 characters in the format 0xAARRGGBB + */ public static RGBtoWebstring(color: number): string { var argb: any = Phaser.ColorUtils.getRGB(color); @@ -223,12 +240,12 @@ module Phaser { } /** - * Return a string containing a hex representation of the given color - * - * @param color The color channel to get the hex value for, must be a value between 0 and 255) - * - * @return A string of length 2 characters, i.e. 255 = FF, 0 = 00 - */ + * Return a string containing a hex representation of the given color + * + * @method colorToHexstring + * @param {Number} color The color channel to get the hex value for, must be a value between 0 and 255) + * @return {String} A string of length 2 characters, i.e. 255 = FF, 0 = 00 + */ public static colorToHexstring(color: number): string { var digits: string = "0123456789ABCDEF"; @@ -243,15 +260,15 @@ module Phaser { } /** - * Convert a HSV (hue, saturation, lightness) color space value to an RGB color - * - * @param h Hue degree, between 0 and 359 - * @param s Saturation, between 0.0 (grey) and 1.0 - * @param v Value, between 0.0 (black) and 1.0 - * @param alpha Alpha value to set per color (between 0 and 255) - * - * @return 32-bit ARGB color value (0xAARRGGBB) - */ + * Convert a HSV (hue, saturation, lightness) color space value to an RGB color + * + * @method HSVtoRGB + * @param {Number} h Hue degree, between 0 and 359 + * @param {Number} s Saturation, between 0.0 (grey) and 1.0 + * @param {Number} v Value, between 0.0 (black) and 1.0 + * @param {Number} alpha Alpha value to set per color (between 0 and 255) + * @return {Number} 32-bit ARGB color value (0xAARRGGBB) + */ static HSVtoRGB(h: number, s: number, v: number, alpha: number = 255): number { var result: number; @@ -304,12 +321,12 @@ module Phaser { } /** - * Convert an RGB color value to an object containing the HSV color space values: Hue, Saturation and Lightness - * - * @param color In format 0xRRGGBB - * - * @return Object with the properties hue (from 0 to 360), saturation (from 0 to 1.0) and lightness (from 0 to 1.0, also available under .value) - */ + * Convert an RGB color value to an object containing the HSV color space values: Hue, Saturation and Lightness + * + * @method RGBtoHSV + * @param {Number} color In format 0xRRGGBB + * @return {Object} An Object with the properties hue (from 0 to 360), saturation (from 0 to 1.0) and lightness (from 0 to 1.0, also available under .value) + */ public static RGBtoHSV(color: number): any { var rgb: any = Phaser.ColorUtils.getRGB(color); @@ -379,15 +396,14 @@ module Phaser { } /** - * + * Interpolates the two given colours based on the supplied step and currentStep properties. * @method interpolateColor * @param {Number} color1 * @param {Number} color2 * @param {Number} steps * @param {Number} currentStep * @param {Number} alpha - * @return {Number} - * @static + * @return {Number} The interpolated color value. */ public static interpolateColor(color1: number, color2: number, steps: number, currentStep: number, alpha: number = 255): number { @@ -403,31 +419,30 @@ module Phaser { } /** - * + * Interpolates the two given colours based on the supplied step and currentStep properties. * @method interpolateColorWithRGB * @param {Number} color - * @param {Number} r2 - * @param {Number} g2 - * @param {Number} b2 + * @param {Number} r + * @param {Number} g + * @param {Number} b * @param {Number} steps * @param {Number} currentStep - * @return {Number} - * @static + * @return {Number} The interpolated color value. */ - public static interpolateColorWithRGB(color: number, r2: number, g2: number, b2: number, steps: number, currentStep: number): number { + public static interpolateColorWithRGB(color: number, r: number, g: number, b: number, steps: number, currentStep: number): number { var src: any = Phaser.ColorUtils.getRGB(color); - var r: number = (((r2 - src.red) * currentStep) / steps) + src.red; - var g: number = (((g2 - src.green) * currentStep) / steps) + src.green; - var b: number = (((b2 - src.blue) * currentStep) / steps) + src.blue; + var or: number = (((r - src.red) * currentStep) / steps) + src.red; + var og: number = (((g - src.green) * currentStep) / steps) + src.green; + var ob: number = (((b - src.blue) * currentStep) / steps) + src.blue; - return Phaser.ColorUtils.getColor(r, g, b); + return Phaser.ColorUtils.getColor(or, og, ob); } /** - * + * Interpolates the two given colours based on the supplied step and currentStep properties. * @method interpolateRGB * @param {Number} r1 * @param {Number} g1 @@ -437,8 +452,7 @@ module Phaser { * @param {Number} b2 * @param {Number} steps * @param {Number} currentStep - * @return {Number} - * @static + * @return {Number} The interpolated color value. */ public static interpolateRGB(r1: number, g1: number, b1: number, r2: number, g2: number, b2: number, steps: number, currentStep: number): number { @@ -451,16 +465,16 @@ module Phaser { } /** - * Returns a random color value between black and white - *Set the min value to start each channel from the given offset.
- *Set the max value to restrict the maximum color used per channel
- * - * @param min The lowest value to use for the color - * @param max The highest value to use for the color - * @param alpha The alpha value of the returning color (default 255 = fully opaque) - * - * @return 32-bit color value with alpha - */ + * Returns a random color value between black and white + *Set the min value to start each channel from the given offset.
+ *Set the max value to restrict the maximum color used per channel
+ * + * @method getRandomColor + * @param {Number} min The lowest value to use for the color + * @param {Number} max The highest value to use for the color + * @param {Number} alpha The alpha value of the returning color (default 255 = fully opaque) + * @return {Number} 32-bit color value with alpha + */ public static getRandomColor(min: number = 0, max: number = 255, alpha: number = 255): number { // Sanity checks @@ -483,23 +497,23 @@ module Phaser { } /** - * Return the component parts of a color as an Object with the properties alpha, red, green, blue - * - *Alpha will only be set if it exist in the given color (0xAARRGGBB)
- * - * @param color in RGB (0xRRGGBB) or ARGB format (0xAARRGGBB) - * - * @return Object with properties: alpha, red, green, blue - */ + * Return the component parts of a color as an Object with the properties alpha, red, green, blue + * + *Alpha will only be set if it exist in the given color (0xAARRGGBB)
+ * + * @method getRGB + * @param {Number} color in RGB (0xRRGGBB) or ARGB format (0xAARRGGBB) + * @return {Object} An Object with properties: alpha, red, green, blue + */ public static getRGB(color: number): any { return { alpha: color >>> 24, red: color >> 16 & 0xFF, green: color >> 8 & 0xFF, blue: color & 0xFF }; } /** - * + * Returns a CSS friendly string value from the given color. * @method getWebRGB * @param {Number} color - * @return {Any} + * @return {String} A string in the format: 'rgba(r,g,b,a)' */ public static getWebRGB(color: number): any { @@ -513,56 +527,56 @@ module Phaser { } /** - * Given a native color value (in the format 0xAARRGGBB) this will return the Alpha component, as a value between 0 and 255 - * - * @param color In the format 0xAARRGGBB - * - * @return The Alpha component of the color, will be between 0 and 255 (0 being no Alpha, 255 full Alpha) - */ + * Given a native color value (in the format 0xAARRGGBB) this will return the Alpha component, as a value between 0 and 255 + * + * @method getAlpha + * @param {Number} color In the format 0xAARRGGBB + * @return {Number} The Alpha component of the color, will be between 0 and 1 (0 being no Alpha (opaque), 1 full Alpha (transparent)) + */ public static getAlpha(color: number): number { return color >>> 24; } /** - * Given a native color value (in the format 0xAARRGGBB) this will return the Alpha component as a value between 0 and 1 - * - * @param color In the format 0xAARRGGBB - * - * @return The Alpha component of the color, will be between 0 and 1 (0 being no Alpha (opaque), 1 full Alpha (transparent)) - */ + * Given a native color value (in the format 0xAARRGGBB) this will return the Alpha component as a value between 0 and 1 + * + * @method getAlphaFloat + * @param {Number} color In the format 0xAARRGGBB + * @return {Number} The Alpha component of the color, will be between 0 and 1 (0 being no Alpha (opaque), 1 full Alpha (transparent)) + */ public static getAlphaFloat(color: number): number { return (color >>> 24) / 255; } /** - * Given a native color value (in the format 0xAARRGGBB) this will return the Red component, as a value between 0 and 255 - * - * @param color In the format 0xAARRGGBB - * - * @return The Red component of the color, will be between 0 and 255 (0 being no color, 255 full Red) - */ + * Given a native color value (in the format 0xAARRGGBB) this will return the Red component, as a value between 0 and 255 + * + * @method getRed + * @param {Number} color In the format 0xAARRGGBB + * @return {Number} The Red component of the color, will be between 0 and 255 (0 being no color, 255 full Red) + */ public static getRed(color: number): number { return color >> 16 & 0xFF; } /** - * Given a native color value (in the format 0xAARRGGBB) this will return the Green component, as a value between 0 and 255 - * - * @param color In the format 0xAARRGGBB - * - * @return The Green component of the color, will be between 0 and 255 (0 being no color, 255 full Green) - */ + * Given a native color value (in the format 0xAARRGGBB) this will return the Green component, as a value between 0 and 255 + * + * @method getGreen + * @param {Number} color In the format 0xAARRGGBB + * @return {Number} The Green component of the color, will be between 0 and 255 (0 being no color, 255 full Green) + */ public static getGreen(color: number): number { return color >> 8 & 0xFF; } /** - * Given a native color value (in the format 0xAARRGGBB) this will return the Blue component, as a value between 0 and 255 - * - * @param color In the format 0xAARRGGBB - * - * @return The Blue component of the color, will be between 0 and 255 (0 being no color, 255 full Blue) - */ + * Given a native color value (in the format 0xAARRGGBB) this will return the Blue component, as a value between 0 and 255 + * + * @method getBlue + * @param {Number} color In the format 0xAARRGGBB + * @return {Number} The Blue component of the color, will be between 0 and 255 (0 being no color, 255 full Blue) + */ public static getBlue(color: number): number { return color & 0xFF; } diff --git a/Phaser/utils/DebugUtils.ts b/Phaser/utils/DebugUtils.ts index 885eb969..7dbb7b98 100644 --- a/Phaser/utils/DebugUtils.ts +++ b/Phaser/utils/DebugUtils.ts @@ -1,32 +1,85 @@ ///Sprite, taking scaling and rotation into account.
* The coordinates must be given in world space, not local or camera space.
*
- * @param sprite {Sprite} The Sprite to check. It will take scaling and rotation into account.
- * @param x {Number} The x coordinate in world space.
- * @param y {Number} The y coordinate in world space.
- *
- * @return Whether or not the point overlaps this object.
+ * @method overlapsXY
+ * @param {Sprite} sprite The Sprite to check. It will take scaling and rotation into account.
+ * @param {Number} x The x coordinate in world space.
+ * @param {Number} y The y coordinate in world space.
+ * @return {Boolean} Whether or not the point overlaps this object.
*/
- static overlapsXY(sprite: Phaser.Sprite, x: number, y: number): boolean {
+ public static overlapsXY(sprite: Phaser.Sprite, x: number, y: number): boolean {
// if rotation == 0 then just do a rect check instead!
if (sprite.transform.rotation == 0)
@@ -185,23 +213,24 @@ module Phaser {
* Checks to see if the given point overlaps this Sprite, taking scaling and rotation into account.
* The point must be given in world space, not local or camera space.
*
- * @param sprite {Sprite} The Sprite to check. It will take scaling and rotation into account.
- * @param point {Point} The point in world space you want to check.
- *
- * @return Whether or not the point overlaps this object.
+ * @method overlapsPoint
+ * @param {Sprite} sprite The Sprite to check. It will take scaling and rotation into account.
+ * @param {Point} point The point in world space you want to check.
+ * @return {Boolean} Whether or not the point overlaps this object.
*/
- static overlapsPoint(sprite: Phaser.Sprite, point: Phaser.Point): boolean {
+ public static overlapsPoint(sprite: Phaser.Sprite, point: Phaser.Point): boolean {
return Phaser.SpriteUtils.overlapsXY(sprite, point.x, point.y);
}
/**
* 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.
+ * @method onScreen
+ * @param {Sprite} sprite The Sprite to check. It will take scaling and rotation into account.
+ * @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.
*/
- static onScreen(sprite: Phaser.Sprite, camera: Phaser.Camera = null): boolean {
+ public static onScreen(sprite: Phaser.Sprite, camera: Phaser.Camera = null): boolean {
if (camera == null)
{
@@ -217,12 +246,13 @@ module Phaser {
/**
* Call this to figure out the on-screen position of the object.
*
- * @param point {Point} Takes a Point 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.
- *
+ * @method getScreenXY
+ * @param {Sprite} sprite The Sprite to check.
+ * @param {Point} point Takes a Point 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 {Point} The Point you passed in, or a new Point if you didn't pass one, containing the screen X and Y position of this object.
*/
- static getScreenXY(sprite: Phaser.Sprite, point: Phaser.Point = null, camera: Phaser.Camera = null): Phaser.Point {
+ public static getScreenXY(sprite: Phaser.Sprite, point: Phaser.Point = null, camera: Phaser.Camera = null): Phaser.Point {
if (point == null)
{
@@ -258,17 +288,17 @@ module Phaser {
*/
/**
- * Handy for reviving game objects.
- * Resets their existence flags and position.
+ * 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.
+ * @method reset
+ * @param {Sprite} sprite The Sprite to reset.
+ * @param {number} x The new X position of this object.
+ * @param {number} y The new Y position of this object.
+ * @return {Sprite} The reset Sprite object.
*/
- static reset(sprite: Phaser.Sprite, x: number, y: number) {
+ public static reset(sprite: Phaser.Sprite, x: number, y: number):Phaser.Sprite {
sprite.revive();
- //sprite.body.touching = Types.NONE;
- //sprite.body.wasTouching = Types.NONE;
sprite.x = x;
sprite.y = y;
sprite.body.velocity.x = 0;
@@ -276,6 +306,8 @@ module Phaser {
sprite.body.position.x = x;
sprite.body.position.y = y;
+ return sprite;
+
}
/**
@@ -283,37 +315,18 @@ module Phaser {
* 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
+ * @method setBounds
+ * @param {number} x x position of the bound
+ * @param {number} y y position of the bound
+ * @param {number} width width of its bound
+ * @param {number} height height of its bound
*/
- static setBounds(x: number, y: number, width: number, height: number) {
+ public static setBounds(x: number, y: number, width: number, height: number) {
- //this.worldBounds = new Quad(x, y, width, height);
+ // Needed?
}
- /**
- * 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.
- */
- /*
- static makeGraphic(width: number, height: number, color: string = 'rgb(255,255,255)'): Sprite {
-
- this._texture = null;
- this.width = width;
- this.height = height;
- this.fillColor = color;
- this._dynamicTexture = false;
-
- return this;
- }
- */
-
}
}
\ No newline at end of file
diff --git a/Plugins/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/Plugins/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
new file mode 100644
index 00000000..594d24c2
Binary files /dev/null and b/Plugins/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ
diff --git a/Plugins/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/Plugins/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
new file mode 100644
index 00000000..e69de29b
diff --git a/Plugins/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/Plugins/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
new file mode 100644
index 00000000..e69de29b
diff --git a/Plugins/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/Plugins/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
new file mode 100644
index 00000000..e69de29b
diff --git a/SpecialFX/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/SpecialFX/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
new file mode 100644
index 00000000..234c1bd2
Binary files /dev/null and b/SpecialFX/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ
diff --git a/SpecialFX/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/SpecialFX/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
new file mode 100644
index 00000000..e69de29b
diff --git a/SpecialFX/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/SpecialFX/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
new file mode 100644
index 00000000..e69de29b
diff --git a/SpecialFX/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/SpecialFX/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
new file mode 100644
index 00000000..e69de29b