diff --git a/.gitignore b/.gitignore
index bec8828..5bd981c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,4 @@
ehthumbs.db
Thumbs.db
-node_modules/
-package.json
-Gruntfile.js
\ No newline at end of file
+node_modules/
\ No newline at end of file
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..e905c35
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,104 @@
+module.exports = function(grunt) {
+
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('package.json'),
+ clean: ['doc'],
+ concat: {
+ options: {
+ separator: ';'
+ },
+ dist: {
+ src: ['src/Isometric.js', 'src/**/*.js'],
+ dest: 'dist/<%= pkg.name %>.js'
+ }
+ },
+ jshint: {
+ src: ['src/**/*.js'],
+ options: {
+ "globals" : { "Phaser": false, "PIXI": false, "p2": false },
+ // Ignore Environment Globals
+ "browser" : true, // Standard browser globals e.g. `window`, `document`.
+
+ // Development
+ "devel" : true, // Allow developments statements e.g. `console.log();`.
+
+ // ECMAScript Support
+ "es3" : true, // Support legacy browser and javascript environments.
+ "esnext" : false, // This option tells JSHint that your code uses ECMAScript 6 specific syntax.
+ "strict" : false, // Require `use strict` pragma in every file.
+ "globalstrict": false, // Allow global "use strict" (also enables 'strict').
+
+ // Functionality
+ "bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.).
+ "boss" : true, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
+ "camelcase" : true, // Force all variable names to use either camelCase style or UPPER_CASE with underscores.
+ "curly" : true, // Require {} for every new block or scope.
+ "eqeqeq" : false, // Require triple equals i.e. `===`.
+ "eqnull" : true, // Tolerate use of `== null`.
+ "evil" : false, // Tolerate use of `eval`.
+ "expr" : false, // Tolerate `ExpressionStatement` as Programs.
+ "forin" : false, // Tolerate `for in` loops without `hasOwnPrototype`.
+ "freeze" : true, // Prohibits overwriting prototypes of native objects such as Array and Date.
+ "funcscope" : true, // This option suppresses warnings about declaring variables inside of control structures while accessing them later from the outside.
+ "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
+ "latedef" : true, // Prohibit variable use before definition.
+ "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
+ "laxcomma" : false, // This option suppresses warnings about comma-first coding style.
+ "loopfunc" : true, // Allow functions to be defined within loops.
+ "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
+ "notypeof" : false, // This option suppresses warnings about invalid typeof operator values.
+ "shadow" : true, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
+ "smarttabs" : false, // This option suppresses warnings about mixed tabs and spaces when the latter are used for alignmnent only.
+ "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
+ "undef" : true, // Require all non-global variables be declared before they are used.
+ "unused" : true, // This option warns when you define and never use your variables.
+
+ // Styling
+ "indent" : 4, // Specify indentation spacing
+ "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
+ "noempty" : true, // Prohibit use of empty blocks.
+ "nonew" : true, // Prohibit use of constructors for side-effects.
+ "plusplus" : false, // Prohibit use of `++` & `--`.
+ "quotmark" : false, // This option enforces the consistency of quotation marks used throughout your code.
+ "sub" : true, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
+ "trailing" : true // Prohibit trailing whitespaces.
+ }
+ },
+ uglify: {
+ options: {
+ banner: '/* Phaser Isometric <%= pkg.version %> - <%= grunt.template.today("dd-mm-yyyy") %> by Lewis Lane */\n'
+ },
+ dist: {
+ files: {
+ 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
+ }
+ }
+ },
+ watch: {
+ scripts: {
+ files: ['src/**/*.js'],
+ tasks: ['default']
+ }
+ },
+ jsdoc : {
+ docstrap : {
+ src: ['src/**/*.js'],
+ options: {
+ destination: 'doc',
+ template : "node_modules/ink-docstrap/template",
+ configure : "node_modules/ink-docstrap/template/jsdoc.conf.json",
+ private: false
+ }
+ }
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+ grunt.loadNpmTasks('grunt-contrib-concat');
+ grunt.loadNpmTasks('grunt-contrib-clean');
+ grunt.loadNpmTasks('grunt-contrib-watch');
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-jsdoc');
+
+ grunt.registerTask('default', ['concat', 'jshint', 'uglify', 'jsdoc:docstrap']);
+};
\ No newline at end of file
diff --git a/dist/phaser-plugin-isometric.js b/dist/phaser-plugin-isometric.js
index 793af49..3fca08c 100644
--- a/dist/phaser-plugin-isometric.js
+++ b/dist/phaser-plugin-isometric.js
@@ -32,13 +32,14 @@
*/
/**
+ * @class Phaser.Plugin.Isometric
+ *
+ * @classdesc
* Isometric is a comprehensive axonometric plugin for Phaser which provides an API for handling axonometric projection of assets in 3D space to the screen.
* The goal has been to mimic as closely as possible the existing APIs provided by Phaser for standard orthogonal 2D projection, but add a third dimension.
* Also included is an Arcade-based 3D AABB physics engine, which again is closely equivalent in functionality and its API.
- *
- * @class Phaser.Plugin.Isometric
+ *
* @constructor
- *
* @param {Phaser.Game} game The current game instance.
*/
Phaser.Plugin.Isometric = function (game, parent) {
@@ -52,7 +53,7 @@ Phaser.Plugin.Isometric = function (game, parent) {
Phaser.Plugin.Isometric.prototype = Object.create(Phaser.Plugin.prototype);
Phaser.Plugin.Isometric.prototype.constructor = Phaser.Plugin.Isometric;
-Phaser.Plugin.Isometric.VERSION = '0.7.2';
+Phaser.Plugin.Isometric.VERSION = '0.7.3';
// Directional consts
Phaser.Plugin.Isometric.UP = 0;
@@ -70,9 +71,11 @@ Phaser.Plugin.Isometric.ISOARCADE = 'isoarcade';
Phaser.Plugin.Isometric.CLASSIC = 0.5;
Phaser.Plugin.Isometric.TRUE = 0.6154797093263624;
;/**
- * Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
- *
* @class Phaser.Plugin.Isometric.Cube
+ *
+ * @classdesc
+ * Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
+ *
* @constructor
* @param {number} x - The x coordinate of the bottom-back corner of the Cube.
* @param {number} y - The y coordinate of the bottom-back corner of the Cube.
@@ -658,13 +661,26 @@ Phaser.Plugin.Isometric.Cube.intersects = function (a, b) {
return !(a.frontX < b.x || a.frontY < b.y || a.x > b.frontX || a.y > b.frontY || a.z > b.top || a.top < b.z);
};
;/**
- * Phaser IsoSprite constructor
- * @class Phaser.Plugin.Isometric.IsoSprite
- * @constructor
+* @class Phaser.Plugin.Isometric.IsoSprite
+*
+* @classdesc
+* Create a new `IsoSprite` object. IsoSprites are extended versions of standard Sprites that are suitable for axonometric positioning.
+*
+* IsoSprites are simply Sprites that have three new position properties (isoX, isoY and isoZ) and ask the instance of Phaser.Plugin.Isometric.Projector what their position should be in a 2D scene whenever these properties are changed.
+* The IsoSprites retain their 2D position property to prevent any problems and allow you to interact with them as you would a normal Sprite. The upside of this simplicity is that things should behave predictably for those already used to Phaser.
+*
+* @constructor
+* @extends Phaser.Sprite
+* @param {Phaser.Game} game - A reference to the currently running game.
+* @param {number} x - The x coordinate (in 3D space) to position the IsoSprite at.
+* @param {number} y - The y coordinate (in 3D space) to position the IsoSprite at.
+* @param {number} z - The z coordinate (in 3D space) to position the IsoSprite at.
+* @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the IsoSprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
+* @param {string|number} frame - If this IsoSprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
*/
-Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent) {
+Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame) {
- Phaser.Sprite.call(this, game, x, y, key, frame, parent);
+ Phaser.Sprite.call(this, game, x, y, key, frame);
/**
* @property {number} type - The const type of this object.
@@ -679,7 +695,7 @@ Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent)
this._isoPosition = new Phaser.Plugin.Isometric.Point3(x, y, z);
/**
- * @property {number} snap - Snap this IsoSprite's position to this value; handy for keeping pixel art snapped to whole pixels.
+ * @property {number} snap - Snap this IsoSprite's position to the specified value; handy for keeping pixel art snapped to whole pixels.
* @default
*/
this.snap = 0;
@@ -687,18 +703,21 @@ Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent)
/**
* @property {number} _depth - Internal cached depth value.
* @readonly
+ * @private
*/
this._depth = 0;
/**
* @property {boolean} _depthChanged - Internal invalidation control for depth management.
* @readonly
+ * @private
*/
this._depthChanged = true;
/**
* @property {boolean} _isoPositionChanged - Internal invalidation control for positioning.
* @readonly
+ * @private
*/
this._isoPositionChanged = true;
@@ -742,7 +761,7 @@ Phaser.Plugin.Isometric.IsoSprite.prototype._project = function () {
/**
* The axonometric position of the IsoSprite on the x axis. Increasing the x coordinate will move the object down and to the right on the screen.
*
- * @name Phaser.Sprite#isoX
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoX
* @property {number} isoX - The axonometric position of the IsoSprite on the x axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoX", {
@@ -758,7 +777,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoX", {
/**
* The axonometric position of the IsoSprite on the y axis. Increasing the y coordinate will move the object down and to the left on the screen.
*
- * @name Phaser.Sprite#isoY
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoY
* @property {number} isoY - The axonometric position of the IsoSprite on the y axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoY", {
@@ -774,7 +793,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoY", {
/**
* The axonometric position of the IsoSprite on the z axis. Increasing the z coordinate will move the object directly upwards on the screen.
*
- * @name Phaser.Sprite#isoZ
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoZ
* @property {number} isoZ - The axonometric position of the IsoSprite on the z axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoZ", {
@@ -790,7 +809,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoZ", {
/**
* A Point3 object representing the axonometric position of the IsoSprite.
*
- * @name Phaser.Sprite#isoPosition
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoPosition
* @property {Point3} isoPosition - The axonometric position of the IsoSprite on the z axis.
* @readonly
*/
@@ -803,14 +822,14 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoPosition"
/**
* The non-unit distance of the IsoSprite from the 'front' of the scene. Used to correctly depth sort a group of IsoSprites.
*
- * @name Phaser.Sprite#depth
+ * @name Phaser.Plugin.Isometric.IsoSprite#depth
* @property {number} depth - A calculated value used for depth sorting.
* @readonly
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "depth", {
get: function () {
if (this._depthChanged === true) {
- this._depth = (this._isoPosition.x + this._isoPosition.y) + (this._isoPosition.z * 0.95);
+ this._depth = (this._isoPosition.x + this._isoPosition.y);
this._depthChanged = false;
}
return this._depth;
@@ -856,17 +875,404 @@ Phaser.GameObjectFactory.prototype.isoSprite = function (x, y, z, key, frame, gr
return group.add(new Phaser.Plugin.Isometric.IsoSprite(this.game, x, y, z, key, frame));
+};
+;/**
+ * Octree Constructor
+ *
+ * @class Phaser.Plugin.Isometric.Octree
+ * @classdesc A Octree implementation based on Phaser.QuadTree.
+ * Original version at https://github.com/timohausmann/quadtree-js/
+ *
+ * @constructor
+ * @param {number} x - The bottom-back coordinate of the octree.
+ * @param {number} y - The bottom-back coordinate of the octree.
+ * @param {number} z - The bottom-back coordinate of the octree.
+ * @param {number} widthX - The width X (breadth) of the octree.
+ * @param {number} widthY - The width Y (depth) of the octree.
+ * @param {number} height - The height (Z) of the octree.
+ * @param {number} [maxObjects=10] - The maximum number of objects per node.
+ * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
+ * @param {number} [level=0] - Which level is this?
+ */
+Phaser.Plugin.Isometric.Octree = function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
+
+ /**
+ * @property {number} maxObjects - The maximum number of objects per node.
+ * @default
+ */
+ this.maxObjects = 10;
+
+ /**
+ * @property {number} maxLevels - The maximum number of levels to break down to.
+ * @default
+ */
+ this.maxLevels = 4;
+
+ /**
+ * @property {number} level - The current level.
+ */
+ this.level = 0;
+
+ /**
+ * @property {object} bounds - Object that contains the octree bounds.
+ */
+ this.bounds = {};
+
+ /**
+ * @property {array} objects - Array of octree children.
+ */
+ this.objects = [];
+
+ /**
+ * @property {array} nodes - Array of associated child nodes.
+ */
+ this.nodes = [];
+
+ /**
+ * @property {array} _empty - Internal empty array.
+ * @private
+ */
+ this._empty = [];
+
+ this.reset(x, y, z, widthX, widthY, height, maxObjects, maxLevels, level);
+
+};
+
+Phaser.Plugin.Isometric.Octree.prototype = {
+
+ /**
+ * Resets the QuadTree.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#reset
+ * @param {number} x - The bottom-back coordinate of the octree.
+ * @param {number} y - The bottom-back coordinate of the octree.
+ * @param {number} z - The bottom-back coordinate of the octree.
+ * @param {number} widthX - The width X (breadth) of the octree.
+ * @param {number} widthY - The width Y (depth) of the octree.
+ * @param {number} height - The height (Z) of the octree.
+ * @param {number} [maxObjects=10] - The maximum number of objects per node.
+ * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
+ * @param {number} [level=0] - Which level is this?
+ */
+ reset: function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
+
+ this.maxObjects = maxObjects || 10;
+ this.maxLevels = maxLevels || 4;
+ this.level = level || 0;
+
+ this.bounds = {
+ x: Math.round(x),
+ y: Math.round(y),
+ z: Math.round(z),
+ widthX: widthX,
+ widthY: widthY,
+ height: height,
+ subWidthX: Math.floor(widthX * 0.5),
+ subWidthY: Math.floor(widthY * 0.5),
+ subHeight: Math.floor(height * 0.5),
+ frontX: Math.round(x) + Math.floor(widthX * 0.5),
+ frontY: Math.round(y) + Math.floor(widthY * 0.5),
+ top: Math.round(z) + Math.floor(height * 0.5)
+ };
+
+ this.objects.length = 0;
+ this.nodes.length = 0;
+
+ },
+
+ /**
+ * Populates this octree with the children of the given Group. In order to be added the child must exist and have a body property.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#populate
+ * @param {Phaser.Group} group - The Group to add to the octree.
+ */
+ populate: function (group) {
+
+ group.forEach(this.populateHandler, this, true);
+
+ },
+
+ /**
+ * Handler for the populate method.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#populateHandler
+ * @param {Phaser.Plugin.Isometric.IsoSprite|object} sprite - The Sprite to check.
+ */
+ populateHandler: function (sprite) {
+
+ if (sprite.body && sprite.exists) {
+ this.insert(sprite.body);
+ }
+
+ },
+
+ /**
+ * Split the node into 8 subnodes
+ *
+ * @method Phaser.Plugin.Isometric.Octree#split
+ */
+ split: function () {
+
+ // bottom four octants
+ // -x-y-z
+ this.nodes[0] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x-y-z
+ this.nodes[1] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // -x+y-z
+ this.nodes[2] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x+y-z
+ this.nodes[3] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+
+ // top four octants
+ // -x-y+z
+ this.nodes[4] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x-y+z
+ this.nodes[5] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // -x+y+z
+ this.nodes[6] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x+y+z
+ this.nodes[7] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ },
+
+ /**
+ * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#insert
+ * @param {Phaser.Plugin.Isometric.Body|Phaser.Plugin.Isometric.Cube|object} body - The Body object to insert into the octree. Can be any object so long as it exposes x, y, z, frontX, frontY and top properties.
+ */
+ insert: function (body) {
+
+ var i = 0;
+ var index;
+
+ // if we have subnodes ...
+ if (this.nodes[0] !== null) {
+ index = this.getIndex(body);
+
+ if (index !== -1) {
+ this.nodes[index].insert(body);
+ return;
+ }
+ }
+
+ this.objects.push(body);
+
+ if (this.objects.length > this.maxObjects && this.level < this.maxLevels) {
+ // Split if we don't already have subnodes
+ if (this.nodes[0] === null) {
+ this.split();
+ }
+
+ // Add objects to subnodes
+ while (i < this.objects.length) {
+ index = this.getIndex(this.objects[i]);
+
+ if (index !== -1) {
+ // this is expensive - see what we can do about it
+ this.nodes[index].insert(this.objects.splice(i, 1)[0]);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ },
+
+ /**
+ * Determine which node the object belongs to.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#getIndex
+ * @param {Phaser.Plugin.Isometric.Cube|object} cube - The bounds in which to check.
+ * @return {number} index - Index of the subnode (0-7), or -1 if cube cannot completely fit within a subnode and is part of the parent node.
+ */
+ getIndex: function (cube) {
+
+ // default is that cube doesn't fit, i.e. it straddles the internal octants
+ var index = -1;
+
+ if (cube.x < this.bounds.frontX && cube.frontX < this.bounds.frontX) {
+ if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into -x-y-z octant
+ index = 0;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into -x-y+z octant
+ index = 4;
+ }
+ } else if (cube.y > this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into -x+y-z octant
+ index = 2;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into -x+y+z octant
+ index = 6;
+ }
+ }
+ } else if (cube.x > this.bounds.frontX) {
+ if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into +x-y-z octant
+ index = 1;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into +x-y+z octant
+ index = 5;
+ }
+ } else if (cube.y > this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into +x+y-z octant
+ index = 3;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into +x+y+z octant
+ index = 7;
+ }
+ }
+ }
+
+
+ return index;
+
+ },
+
+ /**
+ * Return all objects that could collide with the given IsoSprite or Cube.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#retrieve
+ * @param {Phaser.Plugin.Isometric.IsoSprite|Phaser.Plugin.Isometric.Cube} source - The source object to check the Octree against. Either a IsoSprite or Cube.
+ * @return {array} - Array with all detected objects.
+ */
+ retrieve: function (source) {
+
+ var returnObjects, index;
+
+ if (source instanceof Phaser.Plugin.Isometric.Cube) {
+ returnObjects = this.objects;
+
+ index = this.getIndex(source);
+ } else {
+ if (!source.body) {
+ return this._empty;
+ }
+
+ returnObjects = this.objects;
+
+ index = this.getIndex(source.body);
+ }
+
+ if (this.nodes[0]) {
+ // If cube fits into a subnode ..
+ if (index !== -1) {
+ returnObjects = returnObjects.concat(this.nodes[index].retrieve(source));
+ } else {
+ // If cube does not fit into a subnode, check it against all subnodes (unrolled for speed)
+ returnObjects = returnObjects.concat(this.nodes[0].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[1].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[2].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[3].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[4].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[5].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[6].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[7].retrieve(source));
+ }
+ }
+
+ return returnObjects;
+
+ },
+
+ /**
+ * Clear the octree.
+ * @method Phaser.Plugin.Isometric.Octree#clear
+ */
+ clear: function () {
+
+ this.objects.length = 0;
+
+ var i = this.nodes.length;
+
+ while (i--) {
+ this.nodes[i].clear();
+ this.nodes.splice(i, 1);
+ }
+
+ this.nodes.length = 0;
+ }
+
+};
+
+Phaser.Plugin.Isometric.Octree.prototype.constructor = Phaser.Plugin.Isometric.Octree;
+
+/**
+ * Visually renders an Octree to the display.
+ *
+ * @method Phaser.Utils.Debug#octree
+ * @param {Phaser.Plugin.Isometric.Octree} octree - The octree to render.
+ * @param {string} color - The color of the lines in the quadtree.
+ */
+Phaser.Utils.Debug.prototype.octree = function (octree, color) {
+
+ color = color || 'rgba(255,0,0,0.3)';
+
+ this.start();
+
+ var bounds = octree.bounds,
+ i, points;
+
+ if (octree.nodes.length === 0) {
+
+ this.context.strokeStyle = color;
+
+ var cube = new Phaser.Plugin.Isometric.Cube(bounds.x, bounds.y, bounds.z, bounds.widthX, bounds.widthY, bounds.height);
+ var corners = cube.getCorners();
+
+ points = corners.slice(0, corners.length);
+ points = points.map(function (p) {
+ return this.game.iso.project(p);
+ });
+
+ this.context.moveTo(points[0].x, points[0].y);
+ this.context.beginPath();
+ this.context.strokeStyle = color;
+
+ this.context.lineTo(points[1].x, points[1].y);
+ this.context.lineTo(points[3].x, points[3].y);
+ this.context.lineTo(points[2].x, points[2].y);
+ this.context.lineTo(points[6].x, points[6].y);
+ this.context.lineTo(points[4].x, points[4].y);
+ this.context.lineTo(points[5].x, points[5].y);
+ this.context.lineTo(points[1].x, points[1].y);
+ this.context.lineTo(points[0].x, points[0].y);
+ this.context.lineTo(points[4].x, points[4].y);
+ this.context.moveTo(points[0].x, points[0].y);
+ this.context.lineTo(points[2].x, points[2].y);
+ this.context.moveTo(points[3].x, points[3].y);
+ this.context.lineTo(points[7].x, points[7].y);
+ this.context.lineTo(points[6].x, points[6].y);
+ this.context.moveTo(points[7].x, points[7].y);
+ this.context.lineTo(points[5].x, points[5].y);
+ this.context.stroke();
+ this.context.closePath();
+
+ for (i = 0; i < octree.objects.length; i++) {
+ this.body(octree.objects[i].sprite, 'rgb(0,255,0)', false);
+ }
+ } else {
+ for (i = 0; i < octree.nodes.length; i++) {
+ this.octree(octree.nodes[i]);
+ }
+ }
+
+ this.stop();
+
};
;/**
* @class Phaser.Plugin.Isometric.Point3
+ *
* @classdesc
* The Point3 object represents a location in a three-dimensional coordinate system,
* where x and y represent the horizontal axes and z represents the vertical axis.
* The following code creates a point at (0,0,0):
* `var myPoint = new Phaser.Plugin.Isometric.Point3();`
- */
-
-/**
+ *
* Creates a new Point3 object. If you pass no parameters a Point3 is created set to (0, 0, 0).
*
* @constructor
@@ -1158,9 +1564,11 @@ Phaser.Plugin.Isometric.Point3.equals = function (a, b) {
};
;/**
- * Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
- *
* @class Phaser.Plugin.Isometric.Projector
+ *
+ * @classdesc
+ * Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
+ *
* @constructor
* @param {Phaser.Game} game - The current game object.
* @param {number} projectionRatio - The ratio of the axonometric projection.
@@ -1234,11 +1642,12 @@ Phaser.Plugin.Isometric.Projector.prototype = {
};
;/**
+ * @class Phaser.Plugin.Isometric.Body
+ *
+ * @classdesc
* The Physics Body is linked to a single IsoSprite. All physics operations should be performed against the body rather than
* the IsoSprite itself. For example you can set the velocity, acceleration, bounce values etc all on the Body.
- *
- * @class Phaser.Plugin.Isometric.Body
- * @classdesc IsoArcade Physics Body Constructor
+ *
* @constructor
* @param {Phaser.Plugin.Isometric.IsoSprite} sprite - The IsoSprite object this physics body belongs to.
*/
@@ -1947,7 +2356,7 @@ Phaser.Plugin.Isometric.Body.prototype = {
this.position.x = x + ((this.widthX * -this.sprite.anchor.x) + this.widthX * 0.5) + this.offset.x;
this.position.y = y + ((this.widthY * this.sprite.anchor.x) - this.widthY * 0.5) + this.offset.y;
- this.position.z = z - ((this.height * -this.sprite.anchor.y * 2) + this.height) + this.offset.z;
+ this.position.z = z - (Math.abs(this.sprite.height) * (1 - this.sprite.anchor.y)) + (Math.abs(this.sprite.width * 0.5)) + this.offset.z;
this.prev.x = this.position.x;
this.prev.y = this.position.y;
@@ -1961,6 +2370,8 @@ Phaser.Plugin.Isometric.Body.prototype = {
this.center.setTo(this.position.x + this.halfWidthX, this.position.y + this.halfWidthY, this.position.z + this.halfHeight);
+ this.sprite._isoPositionChanged = true;
+
},
/**
@@ -2325,395 +2736,6 @@ Phaser.Plugin.Isometric.Body.renderBodyInfo = function (debug, body) {
Phaser.Plugin.Isometric.Body.prototype.constructor = Phaser.Plugin.Isometric.Body;
-/**
- * Octree Constructor
- *
- * @class Phaser.Plugin.Isometric.Octree
- * @classdesc A Octree implementation. The original code was a conversion of the Java code posted to GameDevTuts.
- * However I've tweaked it massively to add node indexing, removed lots of temp. var creation and significantly increased performance as a result.
- * Original version at https://github.com/timohausmann/quadtree-js/
- * @constructor
- * @param {number} x - The bottom-back coordinate of the octree.
- * @param {number} y - The bottom-back coordinate of the octree.
- * @param {number} z - The bottom-back coordinate of the octree.
- * @param {number} widthX - The width X (breadth) of the octree.
- * @param {number} widthY - The width Y (depth) of the octree.
- * @param {number} height - The height (Z) of the octree.
- * @param {number} [maxObjects=10] - The maximum number of objects per node.
- * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
- * @param {number} [level=0] - Which level is this?
- */
-Phaser.Plugin.Isometric.Octree = function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
-
- /**
- * @property {number} maxObjects - The maximum number of objects per node.
- * @default
- */
- this.maxObjects = 10;
-
- /**
- * @property {number} maxLevels - The maximum number of levels to break down to.
- * @default
- */
- this.maxLevels = 4;
-
- /**
- * @property {number} level - The current level.
- */
- this.level = 0;
-
- /**
- * @property {object} bounds - Object that contains the octree bounds.
- */
- this.bounds = {};
-
- /**
- * @property {array} objects - Array of octree children.
- */
- this.objects = [];
-
- /**
- * @property {array} nodes - Array of associated child nodes.
- */
- this.nodes = [];
-
- /**
- * @property {array} _empty - Internal empty array.
- * @private
- */
- this._empty = [];
-
- this.reset(x, y, z, widthX, widthY, height, maxObjects, maxLevels, level);
-
-};
-
-Phaser.Plugin.Isometric.Octree.prototype = {
-
- /**
- * Resets the QuadTree.
- *
- * @method Phaser.Plugin.Isometric.Octree#reset
- * @param {number} x - The bottom-back coordinate of the octree.
- * @param {number} y - The bottom-back coordinate of the octree.
- * @param {number} z - The bottom-back coordinate of the octree.
- * @param {number} widthX - The width X (breadth) of the octree.
- * @param {number} widthY - The width Y (depth) of the octree.
- * @param {number} height - The height (Z) of the octree.
- * @param {number} [maxObjects=10] - The maximum number of objects per node.
- * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
- * @param {number} [level=0] - Which level is this?
- */
- reset: function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
-
- this.maxObjects = maxObjects || 10;
- this.maxLevels = maxLevels || 4;
- this.level = level || 0;
-
- this.bounds = {
- x: Math.round(x),
- y: Math.round(y),
- z: Math.round(z),
- widthX: widthX,
- widthY: widthY,
- height: height,
- subWidthX: Math.floor(widthX * 0.5),
- subWidthY: Math.floor(widthY * 0.5),
- subHeight: Math.floor(height * 0.5),
- frontX: Math.round(x) + Math.floor(widthX * 0.5),
- frontY: Math.round(y) + Math.floor(widthY * 0.5),
- top: Math.round(z) + Math.floor(height * 0.5)
- };
-
- this.objects.length = 0;
- this.nodes.length = 0;
-
- },
-
- /**
- * Populates this octree with the children of the given Group. In order to be added the child must exist and have a body property.
- *
- * @method Phaser.Plugin.Isometric.Octree#populate
- * @param {Phaser.Group} group - The Group to add to the octree.
- */
- populate: function (group) {
-
- group.forEach(this.populateHandler, this, true);
-
- },
-
- /**
- * Handler for the populate method.
- *
- * @method Phaser.Plugin.Isometric.Octree#populateHandler
- * @param {Phaser.Plugin.Isometric.IsoSprite|object} sprite - The Sprite to check.
- */
- populateHandler: function (sprite) {
-
- if (sprite.body && sprite.exists) {
- this.insert(sprite.body);
- }
-
- },
-
- /**
- * Split the node into 8 subnodes
- *
- * @method Phaser.Plugin.Isometric.Octree#split
- */
- split: function () {
-
- // bottom four octants
- // -x-y-z
- this.nodes[0] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x-y-z
- this.nodes[1] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // -x+y-z
- this.nodes[2] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x+y-z
- this.nodes[3] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
-
- // top four octants
- // -x-y+z
- this.nodes[4] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x-y+z
- this.nodes[5] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // -x+y+z
- this.nodes[6] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x+y+z
- this.nodes[7] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- },
-
- /**
- * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.
- *
- * @method Phaser.Plugin.Isometric.Octree#insert
- * @param {Phaser.Plugin.Isometric.Body|Phaser.Plugin.Isometric.Cube|object} body - The Body object to insert into the octree. Can be any object so long as it exposes x, y, z, frontX, frontY and top properties.
- */
- insert: function (body) {
-
- var i = 0;
- var index;
-
- // if we have subnodes ...
- if (this.nodes[0] !== null) {
- index = this.getIndex(body);
-
- if (index !== -1) {
- this.nodes[index].insert(body);
- return;
- }
- }
-
- this.objects.push(body);
-
- if (this.objects.length > this.maxObjects && this.level < this.maxLevels) {
- // Split if we don't already have subnodes
- if (this.nodes[0] === null) {
- this.split();
- }
-
- // Add objects to subnodes
- while (i < this.objects.length) {
- index = this.getIndex(this.objects[i]);
-
- if (index !== -1) {
- // this is expensive - see what we can do about it
- this.nodes[index].insert(this.objects.splice(i, 1)[0]);
- } else {
- i++;
- }
- }
- }
-
- },
-
- /**
- * Determine which node the object belongs to.
- *
- * @method Phaser.Plugin.Isometric.Octree#getIndex
- * @param {Phaser.Plugin.Isometric.Cube|object} cube - The bounds in which to check.
- * @return {number} index - Index of the subnode (0-7), or -1 if cube cannot completely fit within a subnode and is part of the parent node.
- */
- getIndex: function (cube) {
-
- // default is that cube doesn't fit, i.e. it straddles the internal octants
- var index = -1;
-
- if (cube.x < this.bounds.frontX && cube.frontX < this.bounds.frontX) {
- if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into -x-y-z octant
- index = 0;
- } else if (cube.z > this.bounds.top) {
- // cube fits into -x-y+z octant
- index = 4;
- }
- } else if (cube.y > this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into -x+y-z octant
- index = 2;
- } else if (cube.z > this.bounds.top) {
- // cube fits into -x+y+z octant
- index = 6;
- }
- }
- } else if (cube.x > this.bounds.frontX) {
- if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into +x-y-z octant
- index = 1;
- } else if (cube.z > this.bounds.top) {
- // cube fits into +x-y+z octant
- index = 5;
- }
- } else if (cube.y > this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into +x+y-z octant
- index = 3;
- } else if (cube.z > this.bounds.top) {
- // cube fits into +x+y+z octant
- index = 7;
- }
- }
- }
-
-
- return index;
-
- },
-
- /**
- * Return all objects that could collide with the given IsoSprite or Cube.
- *
- * @method Phaser.Plugin.Isometric.Octree#retrieve
- * @param {Phaser.Plugin.Isometric.IsoSprite|Phaser.Plugin.Isometric.Cube} source - The source object to check the Octree against. Either a IsoSprite or Cube.
- * @return {array} - Array with all detected objects.
- */
- retrieve: function (source) {
-
- var returnObjects, index;
-
- if (source instanceof Phaser.Plugin.Isometric.Cube) {
- returnObjects = this.objects;
-
- index = this.getIndex(source);
- } else {
- if (!source.body) {
- return this._empty;
- }
-
- returnObjects = this.objects;
-
- index = this.getIndex(source.body);
- }
-
- if (this.nodes[0]) {
- // If cube fits into a subnode ..
- if (index !== -1) {
- returnObjects = returnObjects.concat(this.nodes[index].retrieve(source));
- } else {
- // If cube does not fit into a subnode, check it against all subnodes (unrolled for speed)
- returnObjects = returnObjects.concat(this.nodes[0].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[1].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[2].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[3].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[4].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[5].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[6].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[7].retrieve(source));
- }
- }
-
- return returnObjects;
-
- },
-
- /**
- * Clear the octree.
- * @method Phaser.Plugin.Isometric.Octree#clear
- */
- clear: function () {
-
- this.objects.length = 0;
-
- var i = this.nodes.length;
-
- while (i--) {
- this.nodes[i].clear();
- this.nodes.splice(i, 1);
- }
-
- this.nodes.length = 0;
- }
-
-};
-
-Phaser.Plugin.Isometric.Octree.prototype.constructor = Phaser.Plugin.Isometric.Octree;
-
-/**
- * Visually renders an Octree to the display.
- *
- * @method Phaser.Utils.Debug#octree
- * @param {Phaser.Plugin.Isometric.Octree} octree - The octree to render.
- * @param {string} color - The color of the lines in the quadtree.
- */
-Phaser.Utils.Debug.prototype.octree = function (octree, color) {
-
- color = color || 'rgba(255,0,0,0.3)';
-
- this.start();
-
- var bounds = octree.bounds,
- i, points;
-
- if (octree.nodes.length === 0) {
-
- this.context.strokeStyle = color;
-
- var cube = new Phaser.Plugin.Isometric.Cube(bounds.x, bounds.y, bounds.z, bounds.widthX, bounds.widthY, bounds.height);
- var corners = cube.getCorners();
-
- points = corners.slice(0, corners.length);
- points = points.map(function (p) {
- return this.game.iso.project(p);
- });
-
- this.context.moveTo(points[0].x, points[0].y);
- this.context.beginPath();
- this.context.strokeStyle = color;
-
- this.context.lineTo(points[1].x, points[1].y);
- this.context.lineTo(points[3].x, points[3].y);
- this.context.lineTo(points[2].x, points[2].y);
- this.context.lineTo(points[6].x, points[6].y);
- this.context.lineTo(points[4].x, points[4].y);
- this.context.lineTo(points[5].x, points[5].y);
- this.context.lineTo(points[1].x, points[1].y);
- this.context.lineTo(points[0].x, points[0].y);
- this.context.lineTo(points[4].x, points[4].y);
- this.context.moveTo(points[0].x, points[0].y);
- this.context.lineTo(points[2].x, points[2].y);
- this.context.moveTo(points[3].x, points[3].y);
- this.context.lineTo(points[7].x, points[7].y);
- this.context.lineTo(points[6].x, points[6].y);
- this.context.moveTo(points[7].x, points[7].y);
- this.context.lineTo(points[5].x, points[5].y);
- this.context.stroke();
- this.context.closePath();
-
- for (i = 0; i < octree.objects.length; i++) {
- this.body(octree.objects[i].sprite, 'rgb(0,255,0)', false);
- }
- } else {
- for (i = 0; i < octree.nodes.length; i++) {
- this.octree(octree.nodes[i]);
- }
- }
-
- this.stop();
-
-};
-
Phaser.Utils.Debug.prototype.body = (function (_super) {
return function (sprite, color, filled) {
diff --git a/dist/phaser-plugin-isometric.min.js b/dist/phaser-plugin-isometric.min.js
index 8f596c3..982939c 100644
--- a/dist/phaser-plugin-isometric.min.js
+++ b/dist/phaser-plugin-isometric.min.js
@@ -1,3 +1,3 @@
-/* Phaser Isometric 0.7.2 - 06-08-2014 by Lewis Lane */
-Phaser.Plugin.Isometric=function(a,b){Phaser.Plugin.call(this,a,b),this.game.iso=this.game.iso||new Phaser.Plugin.Isometric.Projector(this.game,Phaser.Plugin.Isometric.CLASSIC)},Phaser.Plugin.Isometric.prototype=Object.create(Phaser.Plugin.prototype),Phaser.Plugin.Isometric.prototype.constructor=Phaser.Plugin.Isometric,Phaser.Plugin.Isometric.VERSION="0.7.2",Phaser.Plugin.Isometric.UP=0,Phaser.Plugin.Isometric.DOWN=1,Phaser.Plugin.Isometric.FORWARDX=2,Phaser.Plugin.Isometric.FORWARDY=3,Phaser.Plugin.Isometric.BACKWARDX=4,Phaser.Plugin.Isometric.BACKWARDY=5,Phaser.Plugin.Isometric.ISOSPRITE="isosprite",Phaser.Plugin.Isometric.ISOARCADE="isoarcade",Phaser.Plugin.Isometric.CLASSIC=.5,Phaser.Plugin.Isometric.TRUE=.6154797093263624,Phaser.Plugin.Isometric.Cube=function(a,b,c,d,e,f){a=a||0,b=b||0,c=c||0,d=d||0,e=e||0,f=f||0,this.x=a,this.y=b,this.z=c,this.widthX=d,this.widthY=e,this.height=f,this._corners=[new Phaser.Plugin.Isometric.Point3(this.x,this.y,this.z),new Phaser.Plugin.Isometric.Point3(this.x,this.y,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x,this.y+this.widthY,this.z),new Phaser.Plugin.Isometric.Point3(this.x,this.y+this.widthY,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y,this.z),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y+this.widthY,this.z),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y+this.widthY,this.z+this.height)]},Phaser.Plugin.Isometric.Cube.prototype.constructor=Phaser.Plugin.Isometric.Cube,Phaser.Plugin.Isometric.Cube.prototype={setTo:function(a,b,c,d,e,f){return this.x=a,this.y=b,this.z=c,this.widthX=d,this.widthY=e,this.height=f,this},copyFrom:function(a){this.setTo(a.x,a.y,a.z,a.widthX,a.widthY,a.height)},copyTo:function(a){return a.x=this.x,a.y=this.y,a.z=this.z,a.widthX=this.widthX,a.widthY=this.widthY,a.height=this.height,a},size:function(a){return Phaser.Plugin.Isometric.Cube.size(this,a)},clone:function(a){return Phaser.Plugin.Isometric.Cube.clone(this,a)},intersects:function(a){return Phaser.Plugin.Isometric.Cube.intersects(this,a)},getCorners:function(){return this._corners[0].setTo(this.x,this.y,this.z),this._corners[1].setTo(this.x,this.y,this.z+this.height),this._corners[2].setTo(this.x,this.y+this.widthY,this.z),this._corners[3].setTo(this.x,this.y+this.widthY,this.z+this.height),this._corners[4].setTo(this.x+this.widthX,this.y,this.z),this._corners[5].setTo(this.x+this.widthX,this.y,this.z+this.height),this._corners[6].setTo(this.x+this.widthX,this.y+this.widthY,this.z),this._corners[7].setTo(this.x+this.widthX,this.y+this.widthY,this.z+this.height),this._corners},toString:function(){return"[{Cube (x="+this.x+" y="+this.y+" z="+this.z+" widthX="+this.widthX+" widthY="+this.widthY+" height="+this.height+" empty="+this.empty+")}]"}},Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"halfWidthX",{get:function(){return Math.round(.5*this.widthX)}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"halfWidthY",{get:function(){return Math.round(.5*this.widthY)}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"halfHeight",{get:function(){return Math.round(.5*this.height)}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"bottom",{get:function(){return this.z},set:function(a){this.height=a>=this.top?0:this.top-a,this.z=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"top",{get:function(){return this.z+this.height},set:function(a){this.height=a<=this.z?0:a-this.z}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"backX",{get:function(){return this.x},set:function(a){this.widthX=a>=this.frontX?0:this.frontX-a,this.x=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"backY",{get:function(){return this.y},set:function(a){this.widthY=a>=this.frontY?0:this.frontY-a,this.y=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"frontX",{get:function(){return this.x+this.widthX},set:function(a){this.widthX=a<=this.x?0:a-this.x}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"frontY",{get:function(){return this.y+this.widthY},set:function(a){this.widthY=a<=this.y?0:a-this.y}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"volume",{get:function(){return this.widthX*this.widthY*this.height}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"centerX",{get:function(){return this.x+this.halfWidthX},set:function(a){this.x=a-this.halfWidthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"centerY",{get:function(){return this.y+this.halfWidthY},set:function(a){this.y=a-this.halfWidthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"centerZ",{get:function(){return this.z+this.halfHeight},set:function(a){this.z=a-this.halfHeight}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"randomX",{get:function(){return this.x+Math.random()*this.widthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"randomY",{get:function(){return this.y+Math.random()*this.widthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"randomZ",{get:function(){return this.z+Math.random()*this.height}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"empty",{get:function(){return!this.widthX||!this.widthY||!this.height},set:function(a){a===!0&&this.setTo(0,0,0,0,0,0)}}),Phaser.Plugin.Isometric.Cube.size=function(a,b){return"undefined"==typeof b||null===b?b=new Phaser.Plugin.Isometric.Point3(a.widthX,a.widthY,a.height):b.setTo(a.widthX,a.widthY,a.height),b},Phaser.Plugin.Isometric.Cube.clone=function(a,b){return"undefined"==typeof b||null===b?b=new Phaser.Plugin.Isometric.Cube(a.x,a.y,a.z,a.widthX,a.widthY,a.height):b.setTo(a.x,a.y,a.z,a.widthX,a.widthY,a.height),b},Phaser.Plugin.Isometric.Cube.contains=function(a,b,c,d){return a.widthX<=0||a.widthY<=0||a.height<=0?!1:b>=a.x&&b<=a.right&&c>=a.y&&c<=a.back&&d>=a.z&&d<=a.top},Phaser.Plugin.Isometric.Cube.containsPoint3=function(a,b){return Phaser.Plugin.Isometric.Cube.contains(a,b.x,b.y,b.z)},Phaser.Plugin.Isometric.Cube.containsCube=function(a,b){return a.volume>b.volume?!1:a.x>=b.x&&a.y>=b.y&&a.z>=b.z&&a.frontX<=b.frontX&&a.frontY<=b.frontY&&a.top<=b.top},Phaser.Plugin.Isometric.Cube.intersects=function(a,b){return a.widthX<=0||a.widthY<=0||a.height<=0||b.widthX<=0||b.widthY<=0||b.height<=0?!1:!(a.frontXb.frontX||a.y>b.frontY||a.z>b.top||a.top0&&(this.position.x=Phaser.Math.snapTo(this.position.x,this.snap),this.position.y=Phaser.Math.snapTo(this.position.y,this.snap)),this._isoPositionChanged=!1)},Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoX",{get:function(){return this._isoPosition.x},set:function(a){this._isoPosition.x=a,this._depthChanged=this._isoPositionChanged=!0}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoY",{get:function(){return this._isoPosition.y},set:function(a){this._isoPosition.y=a,this._depthChanged=this._isoPositionChanged=!0}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoZ",{get:function(){return this._isoPosition.z},set:function(a){this._isoPosition.z=a,this._depthChanged=this._isoPositionChanged=!0}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoPosition",{get:function(){return this._isoPosition}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"depth",{get:function(){return this._depthChanged===!0&&(this._depth=this._isoPosition.x+this._isoPosition.y+.95*this._isoPosition.z,this._depthChanged=!1),this._depth}}),Phaser.GameObjectCreator.prototype.isoSprite=function(a,b,c,d,e){return new Phaser.Plugin.Isometric.IsoSprite(this.game,a,b,c,d,e)},Phaser.GameObjectFactory.prototype.isoSprite=function(a,b,c,d,e,f){return"undefined"==typeof f&&(f=this.world),f.add(new Phaser.Plugin.Isometric.IsoSprite(this.game,a,b,c,d,e))},Phaser.Plugin.Isometric.Point3=function(a,b,c){a=a||0,b=b||0,c=c||0,this.x=a,this.y=b,this.z=c},Phaser.Plugin.Isometric.Point3.prototype={copyFrom:function(a){return this.setTo(a.x,a.y,a.z)},copyTo:function(a){return a.x=this.x,a.y=this.y,a.z=this.z,a},equals:function(a){return a.x===this.x&&a.y===this.y&&a.z===this.z},set:function(a,b,c){return this.x=a||0,this.y=b||(0!==b?this.x:0),this.z=c||("undefined"==typeof b?this.x:0),this},setTo:function(a,b,c){return this.set(a,b,c)},add:function(a,b){return this.x+=a||0,this.y+=b||0,this},subtract:function(a,b,c){return this.x-=a||0,this.y-=b||0,this.z-=c||0,this},multiply:function(a,b,c){return this.x*=a||1,this.y*=b||1,this.z*=c||1,this},divide:function(a,b,c){return this.x/=a||1,this.y/=b||1,this.z/=c||1,this}},Phaser.Plugin.Isometric.Point3.prototype.constructor=Phaser.Plugin.Isometric.Point3,Phaser.Plugin.Isometric.Point3.add=function(a,b,c){return"undefined"==typeof c&&(c=new Phaser.Plugin.Isometric.Point3),c.x=a.x+b.x,c.y=a.y+b.y,c.z=a.z+b.z,c},Phaser.Plugin.Isometric.Point3.subtract=function(a,b,c){return"undefined"==typeof c&&(c=new Phaser.Plugin.Isometric.Point3),c.x=a.x-b.x,c.y=a.y-b.y,c.z=a.z-b.z,c},Phaser.Plugin.Isometric.Point3.multiply=function(a,b,c){return"undefined"==typeof c&&(c=new Phaser.Plugin.Isometric.Point3),c.x=a.x*b.x,c.y=a.y*b.y,c.z=a.z*b.z,c},Phaser.Plugin.Isometric.Point3.divide=function(a,b,c){return"undefined"==typeof c&&(c=new Phaser.Plugin.Isometric.Point3),c.x=a.x/b.x,c.y=a.y/b.y,c.z=a.z/b.z,c},Phaser.Plugin.Isometric.Point3.equals=function(a,b){return a.x===b.x&&a.y===b.y&&a.z===b.z},Phaser.Plugin.Isometric.Projector=function(a,b){this.game=a,this.projectionRatio=b||Phaser.Plugin.Isometric.CLASSIC,this.anchor=new Phaser.Point(.5,0)},Phaser.Plugin.Isometric.Projector.prototype={project:function(a,b){return"undefined"==typeof b&&(b=new Phaser.Point),b.x=a.x-a.y,b.y=(a.x+a.y)*this.projectionRatio-a.z,b.x+=this.game.world.width*this.anchor.x,b.y+=this.game.world.height*this.anchor.y,b},projectXY:function(a,b){return"undefined"==typeof b&&(b=new Phaser.Point),b.x=a.x-a.y,b.y=(a.x+a.y)*this.projectionRatio,b.x+=this.game.world.width*this.anchor.x,b.y+=this.game.world.height*this.anchor.y,b}},Phaser.Plugin.Isometric.Body=function(a){this.sprite=a,this.game=a.game,this.type=Phaser.Plugin.Isometric.ISOARCADE,this.enable=!0,this.offset=new Phaser.Plugin.Isometric.Point3,this.position=new Phaser.Plugin.Isometric.Point3(a.isoX,a.isoY,a.isoZ),this.prev=new Phaser.Plugin.Isometric.Point3(this.position.x,this.position.y,this.position.z),this.allowRotation=!0,this.rotation=a.rotation,this.preRotation=a.rotation,this.sourceWidthX=a.texture.frame.width,this.sourceWidthY=a.texture.frame.width,this.sourceHeight=a.texture.frame.height,this.widthX=.5*a.width,this.widthY=.5*a.width,this.height=a.height-.5*a.width,this.halfWidthX=Math.abs(.5*this.widthX),this.halfWidthY=Math.abs(.5*this.widthY),this.halfHeight=Math.abs(.5*this.height),this.center=new Phaser.Plugin.Isometric.Point3(a.isoX+this.halfWidthX,a.isoY+this.halfWidthY,a.isoZ+this.halfHeight),this.velocity=new Phaser.Plugin.Isometric.Point3,this.newVelocity=new Phaser.Plugin.Isometric.Point3,this.deltaMax=new Phaser.Plugin.Isometric.Point3,this.acceleration=new Phaser.Plugin.Isometric.Point3,this.drag=new Phaser.Plugin.Isometric.Point3,this.allowGravity=!0,this.gravity=new Phaser.Plugin.Isometric.Point3,this.bounce=new Phaser.Plugin.Isometric.Point3,this.maxVelocity=new Phaser.Plugin.Isometric.Point3(1e4,1e4,1e4),this.angularVelocity=0,this.angularAcceleration=0,this.angularDrag=0,this.maxAngular=1e3,this.mass=1,this.angle=0,this.speed=0,this.facing=Phaser.NONE,this.immovable=!1,this.moves=!0,this.customSeparateX=!1,this.customSeparateY=!1,this.customSeparateZ=!1,this.overlapX=0,this.overlapY=0,this.overlapZ=0,this.embedded=!1,this.collideWorldBounds=!1,this.checkCollision={none:!1,any:!0,up:!0,down:!0,frontX:!0,frontY:!0,backX:!0,backY:!0},this.touching={none:!0,up:!1,down:!1,frontX:!1,frontY:!1,backX:!1,backY:!1},this.wasTouching={none:!0,up:!1,down:!1,frontX:!1,frontY:!1,backX:!1,backY:!1},this.blocked={up:!1,down:!1,frontX:!1,frontY:!1,backX:!1,backY:!1},this.phase=0,this.skipTree=!1,this._reset=!0,this._sx=a.scale.x,this._sy=a.scale.y,this._dx=0,this._dy=0,this._dz=0,this._corners=[new Phaser.Plugin.Isometric.Point3(this.x,this.y,this.z),new Phaser.Plugin.Isometric.Point3(this.x,this.y,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x,this.y+this.widthY,this.z),new Phaser.Plugin.Isometric.Point3(this.x,this.y+this.widthY,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y,this.z),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y+this.widthY,this.z),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y+this.widthY,this.z+this.height)]},Phaser.Plugin.Isometric.Body.prototype={updateBounds:function(){var a=Math.abs(this.sprite.scale.x),b=Math.abs(this.sprite.scale.y);(a!==this._sx||b!==this._sy)&&(this.widthX=.5*this.sprite.width*a,this.widthY=.5*this.sprite.width*a,this.height=(this.sprite.height-.5*this.sprite.width)*b,this.halfWidthX=Math.floor(2*this.widthX),this.halfWidthY=Math.floor(2*this.widthY),this.halfHeight=Math.floor(2*this.height),this._sx=a,this._sy=b,this.center.setTo(this.position.x+this.halfWidthX,this.position.y+this.halfWidthY,this.position.z+this.halfHeight),this._reset=!0)},preUpdate:function(){this.enable&&(this.phase=1,this.wasTouching.none=this.touching.none,this.wasTouching.up=this.touching.up,this.wasTouching.down=this.touching.down,this.wasTouching.backX=this.touching.backX,this.wasTouching.backY=this.touching.backY,this.wasTouching.frontX=this.touching.frontX,this.wasTouching.frontY=this.touching.frontY,this.touching.none=!0,this.touching.up=!1,this.touching.down=!1,this.touching.backX=!1,this.touching.backY=!1,this.touching.frontX=!1,this.touching.frontY=!1,this.blocked.up=!1,this.blocked.down=!1,this.blocked.backX=!1,this.blocked.frontX=!1,this.blocked.backY=!1,this.blocked.backX=!1,this.embedded=!1,this.updateBounds(),this.position.x=this.sprite.isoX+(this.widthX*-this.sprite.anchor.x+.5*this.widthX)+this.offset.x,this.position.y=this.sprite.isoY+(this.widthY*this.sprite.anchor.x-.5*this.widthY)+this.offset.y,this.position.z=this.sprite.isoZ-Math.abs(this.sprite.height)*(1-this.sprite.anchor.y)+Math.abs(.5*this.sprite.width)+this.offset.z,this.rotation=this.sprite.angle,this.preRotation=this.rotation,(this._reset||1===this.sprite._cache[4])&&(this.prev.x=this.position.x,this.prev.y=this.position.y,this.prev.z=this.position.z),this.moves&&(this.game.physics.isoArcade.updateMotion(this),this.newVelocity.set(this.velocity.x*this.game.time.physicsElapsed,this.velocity.y*this.game.time.physicsElapsed,this.velocity.z*this.game.time.physicsElapsed),this.position.x+=this.newVelocity.x,this.position.y+=this.newVelocity.y,this.position.z+=this.newVelocity.z,(this.position.x!==this.prev.x||this.position.y!==this.prev.y||this.position.z!==this.prev.z)&&(this.speed=Math.sqrt(this.velocity.x*this.velocity.x+this.velocity.y*this.velocity.y+this.velocity.z*this.velocity.z),this.angle=Math.atan2(this.velocity.y,this.velocity.x)),this.collideWorldBounds&&this.checkWorldBounds()),this._dx=this.deltaX(),this._dy=this.deltaY(),this._dz=this.deltaZ(),this._reset=!1)},postUpdate:function(){this.enable&&2!==this.phase&&(this.phase=2,this.deltaX()<0?this.facing=Phaser.Plugin.Isometric.BACKWARDX:this.deltaX()>0&&(this.facing=Phaser.Plugin.Isometric.FORWARDX),this.deltaY()<0?this.facing=Phaser.Plugin.Isometric.BACKWARDY:this.deltaY()>0&&(this.facing=Phaser.Plugin.Isometric.FORWARDY),this.deltaZ()<0?this.facing=Phaser.Plugin.Isometric.DOWN:this.deltaZ()>0&&(this.facing=Phaser.Plugin.Isometric.UP),this.moves&&(this._dx=this.deltaX(),this._dy=this.deltaY(),this._dz=this.deltaZ(),0!==this.deltaMax.x&&0!==this._dx&&(this._dx<0&&this._dx<-this.deltaMax.x?this._dx=-this.deltaMax.x:this._dx>0&&this._dx>this.deltaMax.x&&(this._dx=this.deltaMax.x)),0!==this.deltaMax.y&&0!==this._dy&&(this._dy<0&&this._dy<-this.deltaMax.y?this._dy=-this.deltaMax.y:this._dy>0&&this._dy>this.deltaMax.y&&(this._dy=this.deltaMax.y)),0!==this.deltaMax.z&&0!==this._dz&&(this._dz<0&&this._dz<-this.deltaMax.z?this._dz=-this.deltaMax.z:this._dz>0&&this._dz>this.deltaMax.z&&(this._dz=this.deltaMax.z)),this.sprite.isoX+=this._dx,this.sprite.isoY+=this._dy,this.sprite.isoZ+=this._dz),this.center.setTo(this.position.x+this.halfWidthX,this.position.y+this.halfWidthY,this.position.z+this.halfHeight),this.allowRotation&&(this.sprite.angle+=this.deltaR()),this.prev.x=this.position.x,this.prev.y=this.position.y,this.prev.z=this.position.z)},destroy:function(){this.sprite=null},checkWorldBounds:function(){this.position.xthis.game.physics.isoArcade.bounds.frontX&&this.game.physics.isoArcade.checkCollision.frontX&&(this.position.x=this.game.physics.isoArcade.bounds.frontX-this.widthX,this.velocity.x*=-this.bounce.x,this.blocked.frontX=!0),this.position.ythis.game.physics.isoArcade.bounds.frontY&&this.game.physics.isoArcade.checkCollision.frontY&&(this.position.y=this.game.physics.isoArcade.bounds.frontY-this.widthY,this.velocity.y*=-this.bounce.y,this.blocked.frontY=!0),this.position.zthis.game.physics.isoArcade.bounds.top&&this.game.physics.isoArcade.checkCollision.up&&(this.position.z=this.game.physics.isoArcade.bounds.top-this.height,this.velocity.z*=-this.bounce.z,this.blocked.up=!0)},setSize:function(a,b,c,d,e,f){"undefined"==typeof d&&(d=this.offset.x),"undefined"==typeof e&&(e=this.offset.y),"undefined"==typeof f&&(f=this.offset.z),this.sourceWidthX=a,this.sourceWidthY=b,this.sourceHeight=c,this.widthX=this.sourceWidthX*this._sx,this.widthY=this.sourceWidthY*this._sx,this.height=this.sourceHeight*this._sy,this.halfWidthX=Math.floor(.5*this.widthX),this.halfWidthY=Math.floor(.5*this.widthY),this.halfHeight=Math.floor(.5*this.height),this.offset.setTo(d,e,f),this.center.setTo(this.position.x+this.halfWidthX,this.position.y+this.halfWidthY,this.position.z+this.halfHeight)},reset:function(a,b,c){this.velocity.set(0),this.acceleration.set(0),this.angularVelocity=0,this.angularAcceleration=0,this.position.x=a+(this.widthX*-this.sprite.anchor.x+.5*this.widthX)+this.offset.x,this.position.y=b+(this.widthY*this.sprite.anchor.x-.5*this.widthY)+this.offset.y,this.position.z=c-(this.height*-this.sprite.anchor.y*2+this.height)+this.offset.z,this.prev.x=this.position.x,this.prev.y=this.position.y,this.prev.z=this.position.z,this.rotation=this.sprite.angle,this.preRotation=this.rotation,this._sx=this.sprite.scale.x,this._sy=this.sprite.scale.y,this.center.setTo(this.position.x+this.halfWidthX,this.position.y+this.halfWidthY,this.position.z+this.halfHeight)},hitTest:function(a,b,c){return Phaser.Plugin.Isometric.Cube.contains(this,a,b,c)},onFloor:function(){return this.blocked.down},onWall:function(){return this.blocked.frontX||this.blocked.frontY||this.blocked.backX||this.blocked.backY},deltaAbsX:function(){return this.deltaX()>0?this.deltaX():-this.deltaX()},deltaAbsY:function(){return this.deltaY()>0?this.deltaY():-this.deltaY()},deltaAbsZ:function(){return this.deltaZ()>0?this.deltaZ():-this.deltaZ()},deltaX:function(){return this.position.x-this.prev.x},deltaY:function(){return this.position.y-this.prev.y},deltaZ:function(){return this.position.z-this.prev.z},deltaR:function(){return this.rotation-this.preRotation},getCorners:function(){return this._corners[0].setTo(this.x,this.y,this.z),this._corners[1].setTo(this.x,this.y,this.z+this.height),this._corners[2].setTo(this.x,this.y+this.widthY,this.z),this._corners[3].setTo(this.x,this.y+this.widthY,this.z+this.height),this._corners[4].setTo(this.x+this.widthX,this.y,this.z),this._corners[5].setTo(this.x+this.widthX,this.y,this.z+this.height),this._corners[6].setTo(this.x+this.widthX,this.y+this.widthY,this.z),this._corners[7].setTo(this.x+this.widthX,this.y+this.widthY,this.z+this.height),this._corners}},Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"top",{get:function(){return this.position.z+this.height}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"frontX",{get:function(){return this.position.x+this.widthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"right",{get:function(){return this.position.x+this.widthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"frontY",{get:function(){return this.position.y+this.widthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"bottom",{get:function(){return this.position.y+this.widthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"x",{get:function(){return this.position.x},set:function(a){this.position.x=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"y",{get:function(){return this.position.y},set:function(a){this.position.y=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"z",{get:function(){return this.position.z},set:function(a){this.position.z=a}}),Phaser.Plugin.Isometric.Body.render=function(a,b,c,d){"undefined"==typeof d&&(d=!0),c=c||"rgba(0,255,0,0.4)";var e=[],f=b.getCorners(),g=-b.sprite.game.camera.x,h=-b.sprite.game.camera.y;if(d){e=[f[1],f[3],f[2],f[6],f[4],f[5],f[1]],e=e.map(function(a){var b=this.game.iso.project(a);return b.x+=g,b.y+=h,b}),a.beginPath(),a.fillStyle=c,a.moveTo(e[0].x,e[0].y);for(var i=1;ithis.maxObjects&&this.levelthis.bounds.top&&(b=4):a.y>this.bounds.frontY&&(a.zthis.bounds.top&&(b=6)):a.x>this.bounds.frontX&&(a.ythis.bounds.top&&(b=5):a.y>this.bounds.frontY&&(a.zthis.bounds.top&&(b=7))),b},retrieve:function(a){var b,c;if(a instanceof Phaser.Plugin.Isometric.Cube)b=this.objects,c=this.getIndex(a);else{if(!a.body)return this._empty;b=this.objects,c=this.getIndex(a.body)}return this.nodes[0]&&(-1!==c?b=b.concat(this.nodes[c].retrieve(a)):(b=b.concat(this.nodes[0].retrieve(a)),b=b.concat(this.nodes[1].retrieve(a)),b=b.concat(this.nodes[2].retrieve(a)),b=b.concat(this.nodes[3].retrieve(a)),b=b.concat(this.nodes[4].retrieve(a)),b=b.concat(this.nodes[5].retrieve(a)),b=b.concat(this.nodes[6].retrieve(a)),b=b.concat(this.nodes[7].retrieve(a)))),b},clear:function(){this.objects.length=0;for(var a=this.nodes.length;a--;)this.nodes[a].clear(),this.nodes.splice(a,1);this.nodes.length=0}},Phaser.Plugin.Isometric.Octree.prototype.constructor=Phaser.Plugin.Isometric.Octree,Phaser.Utils.Debug.prototype.octree=function(a,b){b=b||"rgba(255,0,0,0.3)",this.start();var c,d,e=a.bounds;if(0===a.nodes.length){this.context.strokeStyle=b;var f=new Phaser.Plugin.Isometric.Cube(e.x,e.y,e.z,e.widthX,e.widthY,e.height),g=f.getCorners();for(d=g.slice(0,g.length),d=d.map(function(a){return this.game.iso.project(a)}),this.context.moveTo(d[0].x,d[0].y),this.context.beginPath(),this.context.strokeStyle=b,this.context.lineTo(d[1].x,d[1].y),this.context.lineTo(d[3].x,d[3].y),this.context.lineTo(d[2].x,d[2].y),this.context.lineTo(d[6].x,d[6].y),this.context.lineTo(d[4].x,d[4].y),this.context.lineTo(d[5].x,d[5].y),this.context.lineTo(d[1].x,d[1].y),this.context.lineTo(d[0].x,d[0].y),this.context.lineTo(d[4].x,d[4].y),this.context.moveTo(d[0].x,d[0].y),this.context.lineTo(d[2].x,d[2].y),this.context.moveTo(d[3].x,d[3].y),this.context.lineTo(d[7].x,d[7].y),this.context.lineTo(d[6].x,d[6].y),this.context.moveTo(d[7].x,d[7].y),this.context.lineTo(d[5].x,d[5].y),this.context.stroke(),this.context.closePath(),c=0;c0&&this.enable(a[c],!0));else a instanceof Phaser.Group?this.enable(a.children,b):(this.enableBody(a),b&&a.hasOwnProperty("children")&&a.children.length>0&&this.enable(a.children,!0))
+/* Phaser Isometric 0.7.3 - 07-08-2014 by Lewis Lane */
+Phaser.Plugin.Isometric=function(a,b){Phaser.Plugin.call(this,a,b),this.game.iso=this.game.iso||new Phaser.Plugin.Isometric.Projector(this.game,Phaser.Plugin.Isometric.CLASSIC)},Phaser.Plugin.Isometric.prototype=Object.create(Phaser.Plugin.prototype),Phaser.Plugin.Isometric.prototype.constructor=Phaser.Plugin.Isometric,Phaser.Plugin.Isometric.VERSION="0.7.3",Phaser.Plugin.Isometric.UP=0,Phaser.Plugin.Isometric.DOWN=1,Phaser.Plugin.Isometric.FORWARDX=2,Phaser.Plugin.Isometric.FORWARDY=3,Phaser.Plugin.Isometric.BACKWARDX=4,Phaser.Plugin.Isometric.BACKWARDY=5,Phaser.Plugin.Isometric.ISOSPRITE="isosprite",Phaser.Plugin.Isometric.ISOARCADE="isoarcade",Phaser.Plugin.Isometric.CLASSIC=.5,Phaser.Plugin.Isometric.TRUE=.6154797093263624,Phaser.Plugin.Isometric.Cube=function(a,b,c,d,e,f){a=a||0,b=b||0,c=c||0,d=d||0,e=e||0,f=f||0,this.x=a,this.y=b,this.z=c,this.widthX=d,this.widthY=e,this.height=f,this._corners=[new Phaser.Plugin.Isometric.Point3(this.x,this.y,this.z),new Phaser.Plugin.Isometric.Point3(this.x,this.y,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x,this.y+this.widthY,this.z),new Phaser.Plugin.Isometric.Point3(this.x,this.y+this.widthY,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y,this.z),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y,this.z+this.height),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y+this.widthY,this.z),new Phaser.Plugin.Isometric.Point3(this.x+this.widthX,this.y+this.widthY,this.z+this.height)]},Phaser.Plugin.Isometric.Cube.prototype.constructor=Phaser.Plugin.Isometric.Cube,Phaser.Plugin.Isometric.Cube.prototype={setTo:function(a,b,c,d,e,f){return this.x=a,this.y=b,this.z=c,this.widthX=d,this.widthY=e,this.height=f,this},copyFrom:function(a){this.setTo(a.x,a.y,a.z,a.widthX,a.widthY,a.height)},copyTo:function(a){return a.x=this.x,a.y=this.y,a.z=this.z,a.widthX=this.widthX,a.widthY=this.widthY,a.height=this.height,a},size:function(a){return Phaser.Plugin.Isometric.Cube.size(this,a)},clone:function(a){return Phaser.Plugin.Isometric.Cube.clone(this,a)},intersects:function(a){return Phaser.Plugin.Isometric.Cube.intersects(this,a)},getCorners:function(){return this._corners[0].setTo(this.x,this.y,this.z),this._corners[1].setTo(this.x,this.y,this.z+this.height),this._corners[2].setTo(this.x,this.y+this.widthY,this.z),this._corners[3].setTo(this.x,this.y+this.widthY,this.z+this.height),this._corners[4].setTo(this.x+this.widthX,this.y,this.z),this._corners[5].setTo(this.x+this.widthX,this.y,this.z+this.height),this._corners[6].setTo(this.x+this.widthX,this.y+this.widthY,this.z),this._corners[7].setTo(this.x+this.widthX,this.y+this.widthY,this.z+this.height),this._corners},toString:function(){return"[{Cube (x="+this.x+" y="+this.y+" z="+this.z+" widthX="+this.widthX+" widthY="+this.widthY+" height="+this.height+" empty="+this.empty+")}]"}},Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"halfWidthX",{get:function(){return Math.round(.5*this.widthX)}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"halfWidthY",{get:function(){return Math.round(.5*this.widthY)}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"halfHeight",{get:function(){return Math.round(.5*this.height)}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"bottom",{get:function(){return this.z},set:function(a){this.height=a>=this.top?0:this.top-a,this.z=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"top",{get:function(){return this.z+this.height},set:function(a){this.height=a<=this.z?0:a-this.z}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"backX",{get:function(){return this.x},set:function(a){this.widthX=a>=this.frontX?0:this.frontX-a,this.x=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"backY",{get:function(){return this.y},set:function(a){this.widthY=a>=this.frontY?0:this.frontY-a,this.y=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"frontX",{get:function(){return this.x+this.widthX},set:function(a){this.widthX=a<=this.x?0:a-this.x}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"frontY",{get:function(){return this.y+this.widthY},set:function(a){this.widthY=a<=this.y?0:a-this.y}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"volume",{get:function(){return this.widthX*this.widthY*this.height}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"centerX",{get:function(){return this.x+this.halfWidthX},set:function(a){this.x=a-this.halfWidthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"centerY",{get:function(){return this.y+this.halfWidthY},set:function(a){this.y=a-this.halfWidthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"centerZ",{get:function(){return this.z+this.halfHeight},set:function(a){this.z=a-this.halfHeight}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"randomX",{get:function(){return this.x+Math.random()*this.widthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"randomY",{get:function(){return this.y+Math.random()*this.widthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"randomZ",{get:function(){return this.z+Math.random()*this.height}}),Object.defineProperty(Phaser.Plugin.Isometric.Cube.prototype,"empty",{get:function(){return!this.widthX||!this.widthY||!this.height},set:function(a){a===!0&&this.setTo(0,0,0,0,0,0)}}),Phaser.Plugin.Isometric.Cube.size=function(a,b){return"undefined"==typeof b||null===b?b=new Phaser.Plugin.Isometric.Point3(a.widthX,a.widthY,a.height):b.setTo(a.widthX,a.widthY,a.height),b},Phaser.Plugin.Isometric.Cube.clone=function(a,b){return"undefined"==typeof b||null===b?b=new Phaser.Plugin.Isometric.Cube(a.x,a.y,a.z,a.widthX,a.widthY,a.height):b.setTo(a.x,a.y,a.z,a.widthX,a.widthY,a.height),b},Phaser.Plugin.Isometric.Cube.contains=function(a,b,c,d){return a.widthX<=0||a.widthY<=0||a.height<=0?!1:b>=a.x&&b<=a.right&&c>=a.y&&c<=a.back&&d>=a.z&&d<=a.top},Phaser.Plugin.Isometric.Cube.containsPoint3=function(a,b){return Phaser.Plugin.Isometric.Cube.contains(a,b.x,b.y,b.z)},Phaser.Plugin.Isometric.Cube.containsCube=function(a,b){return a.volume>b.volume?!1:a.x>=b.x&&a.y>=b.y&&a.z>=b.z&&a.frontX<=b.frontX&&a.frontY<=b.frontY&&a.top<=b.top},Phaser.Plugin.Isometric.Cube.intersects=function(a,b){return a.widthX<=0||a.widthY<=0||a.height<=0||b.widthX<=0||b.widthY<=0||b.height<=0?!1:!(a.frontXb.frontX||a.y>b.frontY||a.z>b.top||a.top0&&(this.position.x=Phaser.Math.snapTo(this.position.x,this.snap),this.position.y=Phaser.Math.snapTo(this.position.y,this.snap)),this._isoPositionChanged=!1)},Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoX",{get:function(){return this._isoPosition.x},set:function(a){this._isoPosition.x=a,this._depthChanged=this._isoPositionChanged=!0}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoY",{get:function(){return this._isoPosition.y},set:function(a){this._isoPosition.y=a,this._depthChanged=this._isoPositionChanged=!0}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoZ",{get:function(){return this._isoPosition.z},set:function(a){this._isoPosition.z=a,this._depthChanged=this._isoPositionChanged=!0}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"isoPosition",{get:function(){return this._isoPosition}}),Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype,"depth",{get:function(){return this._depthChanged===!0&&(this._depth=this._isoPosition.x+this._isoPosition.y,this._depthChanged=!1),this._depth}}),Phaser.GameObjectCreator.prototype.isoSprite=function(a,b,c,d,e){return new Phaser.Plugin.Isometric.IsoSprite(this.game,a,b,c,d,e)},Phaser.GameObjectFactory.prototype.isoSprite=function(a,b,c,d,e,f){return"undefined"==typeof f&&(f=this.world),f.add(new Phaser.Plugin.Isometric.IsoSprite(this.game,a,b,c,d,e))},Phaser.Plugin.Isometric.Octree=function(a,b,c,d,e,f,g,h,i){this.maxObjects=10,this.maxLevels=4,this.level=0,this.bounds={},this.objects=[],this.nodes=[],this._empty=[],this.reset(a,b,c,d,e,f,g,h,i)},Phaser.Plugin.Isometric.Octree.prototype={reset:function(a,b,c,d,e,f,g,h,i){this.maxObjects=g||10,this.maxLevels=h||4,this.level=i||0,this.bounds={x:Math.round(a),y:Math.round(b),z:Math.round(c),widthX:d,widthY:e,height:f,subWidthX:Math.floor(.5*d),subWidthY:Math.floor(.5*e),subHeight:Math.floor(.5*f),frontX:Math.round(a)+Math.floor(.5*d),frontY:Math.round(b)+Math.floor(.5*e),top:Math.round(c)+Math.floor(.5*f)},this.objects.length=0,this.nodes.length=0},populate:function(a){a.forEach(this.populateHandler,this,!0)},populateHandler:function(a){a.body&&a.exists&&this.insert(a.body)},split:function(){this.nodes[0]=new Phaser.Plugin.Isometric.Octree(this.bounds.x,this.bounds.y,this.bounds.z,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1),this.nodes[1]=new Phaser.Plugin.Isometric.Octree(this.bounds.frontX,this.bounds.y,this.bounds.z,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1),this.nodes[2]=new Phaser.Plugin.Isometric.Octree(this.bounds.x,this.bounds.frontY,this.bounds.z,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1),this.nodes[3]=new Phaser.Plugin.Isometric.Octree(this.bounds.frontX,this.bounds.frontY,this.bounds.z,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1),this.nodes[4]=new Phaser.Plugin.Isometric.Octree(this.bounds.x,this.bounds.y,this.bounds.top,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1),this.nodes[5]=new Phaser.Plugin.Isometric.Octree(this.bounds.frontX,this.bounds.y,this.bounds.top,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1),this.nodes[6]=new Phaser.Plugin.Isometric.Octree(this.bounds.x,this.bounds.frontY,this.bounds.top,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1),this.nodes[7]=new Phaser.Plugin.Isometric.Octree(this.bounds.frontX,this.bounds.frontY,this.bounds.top,this.bounds.subWidthX,this.bounds.subWidthY,this.bounds.subHeight,this.maxLevels,this.level+1)},insert:function(a){var b,c=0;if(null!==this.nodes[0]&&(b=this.getIndex(a),-1!==b))return void this.nodes[b].insert(a);if(this.objects.push(a),this.objects.length>this.maxObjects&&this.levelthis.bounds.top&&(b=4):a.y>this.bounds.frontY&&(a.zthis.bounds.top&&(b=6)):a.x>this.bounds.frontX&&(a.ythis.bounds.top&&(b=5):a.y>this.bounds.frontY&&(a.zthis.bounds.top&&(b=7))),b},retrieve:function(a){var b,c;if(a instanceof Phaser.Plugin.Isometric.Cube)b=this.objects,c=this.getIndex(a);else{if(!a.body)return this._empty;b=this.objects,c=this.getIndex(a.body)}return this.nodes[0]&&(-1!==c?b=b.concat(this.nodes[c].retrieve(a)):(b=b.concat(this.nodes[0].retrieve(a)),b=b.concat(this.nodes[1].retrieve(a)),b=b.concat(this.nodes[2].retrieve(a)),b=b.concat(this.nodes[3].retrieve(a)),b=b.concat(this.nodes[4].retrieve(a)),b=b.concat(this.nodes[5].retrieve(a)),b=b.concat(this.nodes[6].retrieve(a)),b=b.concat(this.nodes[7].retrieve(a)))),b},clear:function(){this.objects.length=0;for(var a=this.nodes.length;a--;)this.nodes[a].clear(),this.nodes.splice(a,1);this.nodes.length=0}},Phaser.Plugin.Isometric.Octree.prototype.constructor=Phaser.Plugin.Isometric.Octree,Phaser.Utils.Debug.prototype.octree=function(a,b){b=b||"rgba(255,0,0,0.3)",this.start();var c,d,e=a.bounds;if(0===a.nodes.length){this.context.strokeStyle=b;var f=new Phaser.Plugin.Isometric.Cube(e.x,e.y,e.z,e.widthX,e.widthY,e.height),g=f.getCorners();for(d=g.slice(0,g.length),d=d.map(function(a){return this.game.iso.project(a)}),this.context.moveTo(d[0].x,d[0].y),this.context.beginPath(),this.context.strokeStyle=b,this.context.lineTo(d[1].x,d[1].y),this.context.lineTo(d[3].x,d[3].y),this.context.lineTo(d[2].x,d[2].y),this.context.lineTo(d[6].x,d[6].y),this.context.lineTo(d[4].x,d[4].y),this.context.lineTo(d[5].x,d[5].y),this.context.lineTo(d[1].x,d[1].y),this.context.lineTo(d[0].x,d[0].y),this.context.lineTo(d[4].x,d[4].y),this.context.moveTo(d[0].x,d[0].y),this.context.lineTo(d[2].x,d[2].y),this.context.moveTo(d[3].x,d[3].y),this.context.lineTo(d[7].x,d[7].y),this.context.lineTo(d[6].x,d[6].y),this.context.moveTo(d[7].x,d[7].y),this.context.lineTo(d[5].x,d[5].y),this.context.stroke(),this.context.closePath(),c=0;c0&&(this.facing=Phaser.Plugin.Isometric.FORWARDX),this.deltaY()<0?this.facing=Phaser.Plugin.Isometric.BACKWARDY:this.deltaY()>0&&(this.facing=Phaser.Plugin.Isometric.FORWARDY),this.deltaZ()<0?this.facing=Phaser.Plugin.Isometric.DOWN:this.deltaZ()>0&&(this.facing=Phaser.Plugin.Isometric.UP),this.moves&&(this._dx=this.deltaX(),this._dy=this.deltaY(),this._dz=this.deltaZ(),0!==this.deltaMax.x&&0!==this._dx&&(this._dx<0&&this._dx<-this.deltaMax.x?this._dx=-this.deltaMax.x:this._dx>0&&this._dx>this.deltaMax.x&&(this._dx=this.deltaMax.x)),0!==this.deltaMax.y&&0!==this._dy&&(this._dy<0&&this._dy<-this.deltaMax.y?this._dy=-this.deltaMax.y:this._dy>0&&this._dy>this.deltaMax.y&&(this._dy=this.deltaMax.y)),0!==this.deltaMax.z&&0!==this._dz&&(this._dz<0&&this._dz<-this.deltaMax.z?this._dz=-this.deltaMax.z:this._dz>0&&this._dz>this.deltaMax.z&&(this._dz=this.deltaMax.z)),this.sprite.isoX+=this._dx,this.sprite.isoY+=this._dy,this.sprite.isoZ+=this._dz),this.center.setTo(this.position.x+this.halfWidthX,this.position.y+this.halfWidthY,this.position.z+this.halfHeight),this.allowRotation&&(this.sprite.angle+=this.deltaR()),this.prev.x=this.position.x,this.prev.y=this.position.y,this.prev.z=this.position.z)},destroy:function(){this.sprite=null},checkWorldBounds:function(){this.position.xthis.game.physics.isoArcade.bounds.frontX&&this.game.physics.isoArcade.checkCollision.frontX&&(this.position.x=this.game.physics.isoArcade.bounds.frontX-this.widthX,this.velocity.x*=-this.bounce.x,this.blocked.frontX=!0),this.position.ythis.game.physics.isoArcade.bounds.frontY&&this.game.physics.isoArcade.checkCollision.frontY&&(this.position.y=this.game.physics.isoArcade.bounds.frontY-this.widthY,this.velocity.y*=-this.bounce.y,this.blocked.frontY=!0),this.position.zthis.game.physics.isoArcade.bounds.top&&this.game.physics.isoArcade.checkCollision.up&&(this.position.z=this.game.physics.isoArcade.bounds.top-this.height,this.velocity.z*=-this.bounce.z,this.blocked.up=!0)},setSize:function(a,b,c,d,e,f){"undefined"==typeof d&&(d=this.offset.x),"undefined"==typeof e&&(e=this.offset.y),"undefined"==typeof f&&(f=this.offset.z),this.sourceWidthX=a,this.sourceWidthY=b,this.sourceHeight=c,this.widthX=this.sourceWidthX*this._sx,this.widthY=this.sourceWidthY*this._sx,this.height=this.sourceHeight*this._sy,this.halfWidthX=Math.floor(.5*this.widthX),this.halfWidthY=Math.floor(.5*this.widthY),this.halfHeight=Math.floor(.5*this.height),this.offset.setTo(d,e,f),this.center.setTo(this.position.x+this.halfWidthX,this.position.y+this.halfWidthY,this.position.z+this.halfHeight)},reset:function(a,b,c){this.velocity.set(0),this.acceleration.set(0),this.angularVelocity=0,this.angularAcceleration=0,this.position.x=a+(this.widthX*-this.sprite.anchor.x+.5*this.widthX)+this.offset.x,this.position.y=b+(this.widthY*this.sprite.anchor.x-.5*this.widthY)+this.offset.y,this.position.z=c-Math.abs(this.sprite.height)*(1-this.sprite.anchor.y)+Math.abs(.5*this.sprite.width)+this.offset.z,this.prev.x=this.position.x,this.prev.y=this.position.y,this.prev.z=this.position.z,this.rotation=this.sprite.angle,this.preRotation=this.rotation,this._sx=this.sprite.scale.x,this._sy=this.sprite.scale.y,this.center.setTo(this.position.x+this.halfWidthX,this.position.y+this.halfWidthY,this.position.z+this.halfHeight),this.sprite._isoPositionChanged=!0},hitTest:function(a,b,c){return Phaser.Plugin.Isometric.Cube.contains(this,a,b,c)},onFloor:function(){return this.blocked.down},onWall:function(){return this.blocked.frontX||this.blocked.frontY||this.blocked.backX||this.blocked.backY},deltaAbsX:function(){return this.deltaX()>0?this.deltaX():-this.deltaX()},deltaAbsY:function(){return this.deltaY()>0?this.deltaY():-this.deltaY()},deltaAbsZ:function(){return this.deltaZ()>0?this.deltaZ():-this.deltaZ()},deltaX:function(){return this.position.x-this.prev.x},deltaY:function(){return this.position.y-this.prev.y},deltaZ:function(){return this.position.z-this.prev.z},deltaR:function(){return this.rotation-this.preRotation},getCorners:function(){return this._corners[0].setTo(this.x,this.y,this.z),this._corners[1].setTo(this.x,this.y,this.z+this.height),this._corners[2].setTo(this.x,this.y+this.widthY,this.z),this._corners[3].setTo(this.x,this.y+this.widthY,this.z+this.height),this._corners[4].setTo(this.x+this.widthX,this.y,this.z),this._corners[5].setTo(this.x+this.widthX,this.y,this.z+this.height),this._corners[6].setTo(this.x+this.widthX,this.y+this.widthY,this.z),this._corners[7].setTo(this.x+this.widthX,this.y+this.widthY,this.z+this.height),this._corners}},Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"top",{get:function(){return this.position.z+this.height}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"frontX",{get:function(){return this.position.x+this.widthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"right",{get:function(){return this.position.x+this.widthX}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"frontY",{get:function(){return this.position.y+this.widthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"bottom",{get:function(){return this.position.y+this.widthY}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"x",{get:function(){return this.position.x},set:function(a){this.position.x=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"y",{get:function(){return this.position.y},set:function(a){this.position.y=a}}),Object.defineProperty(Phaser.Plugin.Isometric.Body.prototype,"z",{get:function(){return this.position.z},set:function(a){this.position.z=a}}),Phaser.Plugin.Isometric.Body.render=function(a,b,c,d){"undefined"==typeof d&&(d=!0),c=c||"rgba(0,255,0,0.4)";var e=[],f=b.getCorners(),g=-b.sprite.game.camera.x,h=-b.sprite.game.camera.y;if(d){e=[f[1],f[3],f[2],f[6],f[4],f[5],f[1]],e=e.map(function(a){var b=this.game.iso.project(a);return b.x+=g,b.y+=h,b}),a.beginPath(),a.fillStyle=c,a.moveTo(e[0].x,e[0].y);for(var i=1;i0&&this.enable(a[c],!0));else a instanceof Phaser.Group?this.enable(a.children,b):(this.enableBody(a),b&&a.hasOwnProperty("children")&&a.children.length>0&&this.enable(a.children,!0))
},enableBody:function(a){a.hasOwnProperty("body")&&null===a.body&&(a.body=new Phaser.Plugin.Isometric.Body(a))},updateMotion:function(a){this._velocityDelta=this.computeVelocity(0,a,a.angularVelocity,a.angularAcceleration,a.angularDrag,a.maxAngular)-a.angularVelocity,a.angularVelocity+=this._velocityDelta,a.rotation+=a.angularVelocity*this.game.time.physicsElapsed,a.velocity.x=this.computeVelocity(1,a,a.velocity.x,a.acceleration.x,a.drag.x,a.maxVelocity.x),a.velocity.y=this.computeVelocity(2,a,a.velocity.y,a.acceleration.y,a.drag.y,a.maxVelocity.y),a.velocity.z=this.computeVelocity(3,a,a.velocity.z,a.acceleration.z,a.drag.z,a.maxVelocity.z)},computeVelocity:function(a,b,c,d,e,f){return f=f||1e4,1===a&&b.allowGravity?c+=(this.gravity.x+b.gravity.x)*this.game.time.physicsElapsed:2===a&&b.allowGravity?c+=(this.gravity.y+b.gravity.y)*this.game.time.physicsElapsed:3===a&&b.allowGravity&&(c+=(this.gravity.z+b.gravity.z)*this.game.time.physicsElapsed),d?c+=d*this.game.time.physicsElapsed:e&&(this._drag=e*this.game.time.physicsElapsed,c-this._drag>0?c-=this._drag:c+this._drag<0?c+=this._drag:c=0),c>f?c=f:-f>c&&(c=-f),c},overlap:function(a,b,c,d,e){if(c=c||null,d=d||null,e=e||c,this._result=!1,this._total=0,Array.isArray(b))for(var f=0,g=b.length;g>f;f++)this.collideHandler(a,b[f],c,d,e,!0);else this.collideHandler(a,b,c,d,e,!0);return this._total>0},collide:function(a,b,c,d,e){return c=c||null,d=d||null,e=e||c,this._result=!1,this._total=0,this.collideHandler(a,b,c,d,e,!1),this._total>0},collideHandler:function(a,b,c,d,e,f){return b||a.type!==Phaser.GROUP&&!Array.isArray(a)?void(a&&b&&(a.exists||a.length)&&(b.exists||b.length)&&(a.type===Phaser.Plugin.Isometric.ISOSPRITE?b.type===Phaser.Plugin.Isometric.ISOSPRITE?this.collideSpriteVsSprite(a,b,c,d,e,f):(b.type===Phaser.GROUP||Array.isArray(b))&&this.collideSpriteVsGroup(a,b,c,d,e,f):(a.type===Phaser.GROUP||Array.isArray(a))&&(b.type===Phaser.Plugin.Isometric.ISOSPRITE?this.collideSpriteVsGroup(b,a,c,d,e,f):(b.type===Phaser.GROUP||Array.isArray(b))&&this.collideGroupVsGroup(a,b,c,d,e,f)))):void this.collideGroupVsSelf(a,c,d,e,f)},collideSpriteVsSprite:function(a,b,c,d,e,f){return a.body&&b.body?(this.separate(a.body,b.body,d,e,f)&&(c&&c.call(e,a,b),this._total++),!0):!1},collideSpriteVsGroup:function(a,b,c,d,e,f){var g,h;if(0!==b.length&&a.body)if(a.body.skipTree||this.skipTree)for(g=0,h=b.children.length;h>g;g++)b.children[g]&&b.children[g].exists&&this.collideSpriteVsSprite(a,b.children[g],c,d,e,f);else for(this.useQuadTree?(this.quadTree.clear(),this.quadTree.reset(this.bounds.x,this.bounds.y,this.bounds.widthX,this.bounds.widthY,this.maxObjects,this.maxLevels),this.quadTree.populate(b),this._potentials=this.quadTree.retrieve(a)):(this.octree.clear(),this.octree.reset(this.bounds.x,this.bounds.y,this.bounds.z,this.bounds.widthX,this.bounds.widthY,this.bounds.height,this.maxObjects,this.maxLevels),this.octree.populate(b),this._potentials=this.octree.retrieve(a)),g=0,h=this._potentials.length;h>g;g++)this.separate(a.body,this._potentials[g],d,e,f)&&(c&&c.call(e,a,this._potentials[g].sprite),this._total++)},collideGroupVsSelf:function(a,b,c,d,e){if(0!==a.length)for(var f=a.children.length,g=0;f>g;g++)for(var h=g+1;f>=h;h++)a.children[g]&&a.children[h]&&a.children[g].exists&&a.children[h].exists&&this.collideSpriteVsSprite(a.children[g],a.children[h],b,c,d,e)},collideGroupVsGroup:function(a,b,c,d,e,f){if(0!==a.length&&0!==b.length)for(var g=0,h=a.children.length;h>g;g++)a.children[g].exists&&this.collideSpriteVsGroup(a.children[g],b,c,d,e,f)},separate:function(a,b,c,d,e){return a.enable&&b.enable&&this.intersects(a,b)?c&&c.call(d,a.sprite,b.sprite)===!1?!1:e?!0:(this._result=this.forceXY||Math.abs(this.gravity.z+a.gravity.z)=b.frontX?!1:a.y>=b.frontY?!1:a.top<=b.z?!1:a.z>=b.top?!1:!0},separateX:function(a,b,c){return a.immovable&&b.immovable?!1:(this._overlap=0,this.intersects(a,b)&&(this._maxOverlap=a.deltaAbsX()+b.deltaAbsX()+this.OVERLAP_BIAS,0===a.deltaX()&&0===b.deltaX()?(a.embedded=!0,b.embedded=!0):a.deltaX()>b.deltaX()?(this._overlap=a.frontX-b.x,this._overlap>this._maxOverlap||a.checkCollision.frontX===!1||b.checkCollision.backX===!1?this._overlap=0:(a.touching.none=!1,a.touching.frontX=!0,b.touching.none=!1,b.touching.backX=!0)):a.deltaX()this._maxOverlap||a.checkCollision.backX===!1||b.checkCollision.frontX===!1?this._overlap=0:(a.touching.none=!1,a.touching.backX=!0,b.touching.none=!1,b.touching.frontX=!0)),0!==this._overlap)?(a.overlapX=this._overlap,b.overlapX=this._overlap,c||a.customSeparateX||b.customSeparateX?!0:(this._velocity1=a.velocity.x,this._velocity2=b.velocity.x,a.immovable||b.immovable?a.immovable?b.immovable||(b.x+=this._overlap,b.velocity.x=this._velocity1-this._velocity2*b.bounce.x):(a.x=a.x-this._overlap,a.velocity.x=this._velocity2-this._velocity1*a.bounce.x):(this._overlap*=.5,a.x=a.x-this._overlap,b.x+=this._overlap,this._newVelocity1=Math.sqrt(this._velocity2*this._velocity2*b.mass/a.mass)*(this._velocity2>0?1:-1),this._newVelocity2=Math.sqrt(this._velocity1*this._velocity1*a.mass/b.mass)*(this._velocity1>0?1:-1),this._average=.5*(this._newVelocity1+this._newVelocity2),this._newVelocity1-=this._average,this._newVelocity2-=this._average,a.velocity.x=this._average+this._newVelocity1*a.bounce.x,b.velocity.x=this._average+this._newVelocity2*b.bounce.x),!0)):!1)},separateY:function(a,b,c){return a.immovable&&b.immovable?!1:(this._overlap=0,this.intersects(a,b)&&(this._maxOverlap=a.deltaAbsY()+b.deltaAbsY()+this.OVERLAP_BIAS,0===a.deltaY()&&0===b.deltaY()?(a.embedded=!0,b.embedded=!0):a.deltaY()>b.deltaY()?(this._overlap=a.frontY-b.y,this._overlap>this._maxOverlap||a.checkCollision.frontY===!1||b.checkCollision.backY===!1?this._overlap=0:(a.touching.none=!1,a.touching.frontY=!0,b.touching.none=!1,b.touching.backY=!0)):a.deltaY()this._maxOverlap||a.checkCollision.backY===!1||b.checkCollision.frontY===!1?this._overlap=0:(a.touching.none=!1,a.touching.backY=!0,b.touching.none=!1,b.touching.frontY=!0)),0!==this._overlap)?(a.overlapY=this._overlap,b.overlapY=this._overlap,c||a.customSeparateY||b.customSeparateY?!0:(this._velocity1=a.velocity.y,this._velocity2=b.velocity.y,a.immovable||b.immovable?a.immovable?b.immovable||(b.y+=this._overlap,b.velocity.y=this._velocity1-this._velocity2*b.bounce.y):(a.y=a.y-this._overlap,a.velocity.y=this._velocity2-this._velocity1*a.bounce.y):(this._overlap*=.5,a.y=a.y-this._overlap,b.y+=this._overlap,this._newVelocity1=Math.sqrt(this._velocity2*this._velocity2*b.mass/a.mass)*(this._velocity2>0?1:-1),this._newVelocity2=Math.sqrt(this._velocity1*this._velocity1*a.mass/b.mass)*(this._velocity1>0?1:-1),this._average=.5*(this._newVelocity1+this._newVelocity2),this._newVelocity1-=this._average,this._newVelocity2-=this._average,a.velocity.y=this._average+this._newVelocity1*a.bounce.y,b.velocity.y=this._average+this._newVelocity2*b.bounce.y),!0)):!1)},separateZ:function(a,b,c){return a.immovable&&b.immovable?!1:(this._overlap=0,this.intersects(a,b)&&(this._maxOverlap=a.deltaAbsZ()+b.deltaAbsZ()+this.OVERLAP_BIAS,0===a.deltaZ()&&0===b.deltaZ()?(a.embedded=!0,b.embedded=!0):a.deltaZ()>b.deltaZ()?(this._overlap=a.top-b.z,this._overlap>this._maxOverlap||a.checkCollision.down===!1||b.checkCollision.up===!1?this._overlap=0:(a.touching.none=!1,a.touching.down=!0,b.touching.none=!1,b.touching.up=!0)):a.deltaZ()this._maxOverlap||a.checkCollision.up===!1||b.checkCollision.down===!1?this._overlap=0:(a.touching.none=!1,a.touching.up=!0,b.touching.none=!1,b.touching.down=!0)),0!==this._overlap)?(a.overlapZ=this._overlap,b.overlapZ=this._overlap,c||a.customSeparateY||b.customSeparateZ?!0:(this._velocity1=a.velocity.z,this._velocity2=b.velocity.z,a.immovable||b.immovable?a.immovable?b.immovable||(b.z+=this._overlap,b.velocity.z=this._velocity1-this._velocity2*b.bounce.z,a.moves&&(b.x+=a.x-a.prev.x,a.y+=b.y-b.prev.y)):(a.z=a.z-this._overlap,a.velocity.z=this._velocity2-this._velocity1*a.bounce.z,b.moves&&(a.x+=b.x-b.prev.x,a.y+=b.y-b.prev.y)):(this._overlap*=.5,a.z=a.z-this._overlap,b.z+=this._overlap,this._newVelocity1=Math.sqrt(this._velocity2*this._velocity2*b.mass/a.mass)*(this._velocity2>0?1:-1),this._newVelocity2=Math.sqrt(this._velocity1*this._velocity1*a.mass/b.mass)*(this._velocity1>0?1:-1),this._average=.5*(this._newVelocity1+this._newVelocity2),this._newVelocity1-=this._average,this._newVelocity2-=this._average,a.velocity.z=this._average+this._newVelocity1*a.bounce.z,b.velocity.z=this._average+this._newVelocity2*b.bounce.z),!0)):!1)},distanceBetween:function(a,b){return this._dx=a.x-b.x,this._dy=a.y-b.y,this._dz=a.z-b.z,Math.sqrt(this._dx*this._dx+this._dy*this._dy+this._dz*this._dz)},distanceToXY:function(a,b,c){return this._dx=a.x-b,this._dy=a.y-c,Math.sqrt(this._dx*this._dx+this._dy*this._dy)},distanceToXYZ:function(a,b,c,d){return this._dx=a.x-b,this._dy=a.y-c,this._dz=a.y-d,Math.sqrt(this._dx*this._dx+this._dy*this._dy+this._dz*this._dz)}},Phaser.Physics.prototype.isoArcade=null,Phaser.Physics.prototype.parseConfig=function(a){return function(){return this.config.hasOwnProperty("isoArcade")&&this.config.isoArcade===!0&&Phaser.Plugin.Isometric.hasOwnProperty("IsoArcade")&&(this.isoArcade=new Phaser.Plugin.Isometric(this.game,this.config)),a.call(this)}}(Phaser.Physics.prototype.parseConfig),Phaser.Physics.prototype.startSystem=function(a){return function(b){return b===Phaser.Plugin.Isometric.ISOARCADE&&null===this.isoArcade&&(this.isoArcade=new Phaser.Plugin.Isometric.Arcade(this.game),this.setBoundsToWorld()),a.call(this,b)}}(Phaser.Physics.prototype.startSystem),Phaser.Physics.prototype.enable=function(a){return function(b,c){return c===Phaser.Plugin.Isometric.ISOARCADE&&this.isoArcade&&this.isoArcade.enable(b),a.call(this,b,c)}}(Phaser.Physics.prototype.enable),Phaser.Physics.prototype.setBoundsToWorld=function(a){return function(){return this.isoArcade&&this.isoArcade.setBoundsToWorld(),a.call(this)}}(Phaser.Physics.prototype.setBoundsToWorld),Phaser.Physics.prototype.destroy=function(a){return function(){return this.isoArcade=null,a.call(this)}}(Phaser.Physics.prototype.destroy);
\ No newline at end of file
diff --git a/doc/Body.js.html b/doc/Body.js.html
index 0083748..81648f6 100644
--- a/doc/Body.js.html
+++ b/doc/Body.js.html
@@ -82,11 +82,12 @@
/**
+ * @class Phaser.Plugin.Isometric.Body
+ *
+ * @classdesc
* The Physics Body is linked to a single IsoSprite. All physics operations should be performed against the body rather than
* the IsoSprite itself. For example you can set the velocity, acceleration, bounce values etc all on the Body.
- *
- * @class Phaser.Plugin.Isometric.Body
- * @classdesc IsoArcade Physics Body Constructor
+ *
* @constructor
* @param {Phaser.Plugin.Isometric.IsoSprite} sprite - The IsoSprite object this physics body belongs to.
*/
@@ -795,7 +796,7 @@ Phaser.Plugin.Isometric.Body.prototype = {
this.position.x = x + ((this.widthX * -this.sprite.anchor.x) + this.widthX * 0.5) + this.offset.x;
this.position.y = y + ((this.widthY * this.sprite.anchor.x) - this.widthY * 0.5) + this.offset.y;
- this.position.z = z - ((this.height * -this.sprite.anchor.y * 2) + this.height) + this.offset.z;
+ this.position.z = z - (Math.abs(this.sprite.height) * (1 - this.sprite.anchor.y)) + (Math.abs(this.sprite.width * 0.5)) + this.offset.z;
this.prev.x = this.position.x;
this.prev.y = this.position.y;
@@ -809,6 +810,8 @@ Phaser.Plugin.Isometric.Body.prototype = {
this.center.setTo(this.position.x + this.halfWidthX, this.position.y + this.halfWidthY, this.position.z + this.halfHeight);
+ this.sprite._isoPositionChanged = true;
+
},
/**
@@ -1173,395 +1176,6 @@ Phaser.Plugin.Isometric.Body.renderBodyInfo = function (debug, body) {
Phaser.Plugin.Isometric.Body.prototype.constructor = Phaser.Plugin.Isometric.Body;
-/**
- * Octree Constructor
- *
- * @class Phaser.Plugin.Isometric.Octree
- * @classdesc A Octree implementation. The original code was a conversion of the Java code posted to GameDevTuts.
- * However I've tweaked it massively to add node indexing, removed lots of temp. var creation and significantly increased performance as a result.
- * Original version at https://github.com/timohausmann/quadtree-js/
- * @constructor
- * @param {number} x - The bottom-back coordinate of the octree.
- * @param {number} y - The bottom-back coordinate of the octree.
- * @param {number} z - The bottom-back coordinate of the octree.
- * @param {number} widthX - The width X (breadth) of the octree.
- * @param {number} widthY - The width Y (depth) of the octree.
- * @param {number} height - The height (Z) of the octree.
- * @param {number} [maxObjects=10] - The maximum number of objects per node.
- * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
- * @param {number} [level=0] - Which level is this?
- */
-Phaser.Plugin.Isometric.Octree = function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
-
- /**
- * @property {number} maxObjects - The maximum number of objects per node.
- * @default
- */
- this.maxObjects = 10;
-
- /**
- * @property {number} maxLevels - The maximum number of levels to break down to.
- * @default
- */
- this.maxLevels = 4;
-
- /**
- * @property {number} level - The current level.
- */
- this.level = 0;
-
- /**
- * @property {object} bounds - Object that contains the octree bounds.
- */
- this.bounds = {};
-
- /**
- * @property {array} objects - Array of octree children.
- */
- this.objects = [];
-
- /**
- * @property {array} nodes - Array of associated child nodes.
- */
- this.nodes = [];
-
- /**
- * @property {array} _empty - Internal empty array.
- * @private
- */
- this._empty = [];
-
- this.reset(x, y, z, widthX, widthY, height, maxObjects, maxLevels, level);
-
-};
-
-Phaser.Plugin.Isometric.Octree.prototype = {
-
- /**
- * Resets the QuadTree.
- *
- * @method Phaser.Plugin.Isometric.Octree#reset
- * @param {number} x - The bottom-back coordinate of the octree.
- * @param {number} y - The bottom-back coordinate of the octree.
- * @param {number} z - The bottom-back coordinate of the octree.
- * @param {number} widthX - The width X (breadth) of the octree.
- * @param {number} widthY - The width Y (depth) of the octree.
- * @param {number} height - The height (Z) of the octree.
- * @param {number} [maxObjects=10] - The maximum number of objects per node.
- * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
- * @param {number} [level=0] - Which level is this?
- */
- reset: function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
-
- this.maxObjects = maxObjects || 10;
- this.maxLevels = maxLevels || 4;
- this.level = level || 0;
-
- this.bounds = {
- x: Math.round(x),
- y: Math.round(y),
- z: Math.round(z),
- widthX: widthX,
- widthY: widthY,
- height: height,
- subWidthX: Math.floor(widthX * 0.5),
- subWidthY: Math.floor(widthY * 0.5),
- subHeight: Math.floor(height * 0.5),
- frontX: Math.round(x) + Math.floor(widthX * 0.5),
- frontY: Math.round(y) + Math.floor(widthY * 0.5),
- top: Math.round(z) + Math.floor(height * 0.5)
- };
-
- this.objects.length = 0;
- this.nodes.length = 0;
-
- },
-
- /**
- * Populates this octree with the children of the given Group. In order to be added the child must exist and have a body property.
- *
- * @method Phaser.Plugin.Isometric.Octree#populate
- * @param {Phaser.Group} group - The Group to add to the octree.
- */
- populate: function (group) {
-
- group.forEach(this.populateHandler, this, true);
-
- },
-
- /**
- * Handler for the populate method.
- *
- * @method Phaser.Plugin.Isometric.Octree#populateHandler
- * @param {Phaser.Plugin.Isometric.IsoSprite|object} sprite - The Sprite to check.
- */
- populateHandler: function (sprite) {
-
- if (sprite.body && sprite.exists) {
- this.insert(sprite.body);
- }
-
- },
-
- /**
- * Split the node into 8 subnodes
- *
- * @method Phaser.Plugin.Isometric.Octree#split
- */
- split: function () {
-
- // bottom four octants
- // -x-y-z
- this.nodes[0] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x-y-z
- this.nodes[1] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // -x+y-z
- this.nodes[2] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x+y-z
- this.nodes[3] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
-
- // top four octants
- // -x-y+z
- this.nodes[4] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x-y+z
- this.nodes[5] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // -x+y+z
- this.nodes[6] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x+y+z
- this.nodes[7] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- },
-
- /**
- * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.
- *
- * @method Phaser.Plugin.Isometric.Octree#insert
- * @param {Phaser.Plugin.Isometric.Body|Phaser.Plugin.Isometric.Cube|object} body - The Body object to insert into the octree. Can be any object so long as it exposes x, y, z, frontX, frontY and top properties.
- */
- insert: function (body) {
-
- var i = 0;
- var index;
-
- // if we have subnodes ...
- if (this.nodes[0] !== null) {
- index = this.getIndex(body);
-
- if (index !== -1) {
- this.nodes[index].insert(body);
- return;
- }
- }
-
- this.objects.push(body);
-
- if (this.objects.length > this.maxObjects && this.level < this.maxLevels) {
- // Split if we don't already have subnodes
- if (this.nodes[0] === null) {
- this.split();
- }
-
- // Add objects to subnodes
- while (i < this.objects.length) {
- index = this.getIndex(this.objects[i]);
-
- if (index !== -1) {
- // this is expensive - see what we can do about it
- this.nodes[index].insert(this.objects.splice(i, 1)[0]);
- } else {
- i++;
- }
- }
- }
-
- },
-
- /**
- * Determine which node the object belongs to.
- *
- * @method Phaser.Plugin.Isometric.Octree#getIndex
- * @param {Phaser.Plugin.Isometric.Cube|object} cube - The bounds in which to check.
- * @return {number} index - Index of the subnode (0-7), or -1 if cube cannot completely fit within a subnode and is part of the parent node.
- */
- getIndex: function (cube) {
-
- // default is that cube doesn't fit, i.e. it straddles the internal octants
- var index = -1;
-
- if (cube.x < this.bounds.frontX && cube.frontX < this.bounds.frontX) {
- if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into -x-y-z octant
- index = 0;
- } else if (cube.z > this.bounds.top) {
- // cube fits into -x-y+z octant
- index = 4;
- }
- } else if (cube.y > this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into -x+y-z octant
- index = 2;
- } else if (cube.z > this.bounds.top) {
- // cube fits into -x+y+z octant
- index = 6;
- }
- }
- } else if (cube.x > this.bounds.frontX) {
- if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into +x-y-z octant
- index = 1;
- } else if (cube.z > this.bounds.top) {
- // cube fits into +x-y+z octant
- index = 5;
- }
- } else if (cube.y > this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into +x+y-z octant
- index = 3;
- } else if (cube.z > this.bounds.top) {
- // cube fits into +x+y+z octant
- index = 7;
- }
- }
- }
-
-
- return index;
-
- },
-
- /**
- * Return all objects that could collide with the given IsoSprite or Cube.
- *
- * @method Phaser.Plugin.Isometric.Octree#retrieve
- * @param {Phaser.Plugin.Isometric.IsoSprite|Phaser.Plugin.Isometric.Cube} source - The source object to check the Octree against. Either a IsoSprite or Cube.
- * @return {array} - Array with all detected objects.
- */
- retrieve: function (source) {
-
- var returnObjects, index;
-
- if (source instanceof Phaser.Plugin.Isometric.Cube) {
- returnObjects = this.objects;
-
- index = this.getIndex(source);
- } else {
- if (!source.body) {
- return this._empty;
- }
-
- returnObjects = this.objects;
-
- index = this.getIndex(source.body);
- }
-
- if (this.nodes[0]) {
- // If cube fits into a subnode ..
- if (index !== -1) {
- returnObjects = returnObjects.concat(this.nodes[index].retrieve(source));
- } else {
- // If cube does not fit into a subnode, check it against all subnodes (unrolled for speed)
- returnObjects = returnObjects.concat(this.nodes[0].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[1].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[2].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[3].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[4].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[5].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[6].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[7].retrieve(source));
- }
- }
-
- return returnObjects;
-
- },
-
- /**
- * Clear the octree.
- * @method Phaser.Plugin.Isometric.Octree#clear
- */
- clear: function () {
-
- this.objects.length = 0;
-
- var i = this.nodes.length;
-
- while (i--) {
- this.nodes[i].clear();
- this.nodes.splice(i, 1);
- }
-
- this.nodes.length = 0;
- }
-
-};
-
-Phaser.Plugin.Isometric.Octree.prototype.constructor = Phaser.Plugin.Isometric.Octree;
-
-/**
- * Visually renders an Octree to the display.
- *
- * @method Phaser.Utils.Debug#octree
- * @param {Phaser.Plugin.Isometric.Octree} octree - The octree to render.
- * @param {string} color - The color of the lines in the quadtree.
- */
-Phaser.Utils.Debug.prototype.octree = function (octree, color) {
-
- color = color || 'rgba(255,0,0,0.3)';
-
- this.start();
-
- var bounds = octree.bounds,
- i, points;
-
- if (octree.nodes.length === 0) {
-
- this.context.strokeStyle = color;
-
- var cube = new Phaser.Plugin.Isometric.Cube(bounds.x, bounds.y, bounds.z, bounds.widthX, bounds.widthY, bounds.height);
- var corners = cube.getCorners();
-
- points = corners.slice(0, corners.length);
- points = points.map(function (p) {
- return this.game.iso.project(p);
- });
-
- this.context.moveTo(points[0].x, points[0].y);
- this.context.beginPath();
- this.context.strokeStyle = color;
-
- this.context.lineTo(points[1].x, points[1].y);
- this.context.lineTo(points[3].x, points[3].y);
- this.context.lineTo(points[2].x, points[2].y);
- this.context.lineTo(points[6].x, points[6].y);
- this.context.lineTo(points[4].x, points[4].y);
- this.context.lineTo(points[5].x, points[5].y);
- this.context.lineTo(points[1].x, points[1].y);
- this.context.lineTo(points[0].x, points[0].y);
- this.context.lineTo(points[4].x, points[4].y);
- this.context.moveTo(points[0].x, points[0].y);
- this.context.lineTo(points[2].x, points[2].y);
- this.context.moveTo(points[3].x, points[3].y);
- this.context.lineTo(points[7].x, points[7].y);
- this.context.lineTo(points[6].x, points[6].y);
- this.context.moveTo(points[7].x, points[7].y);
- this.context.lineTo(points[5].x, points[5].y);
- this.context.stroke();
- this.context.closePath();
-
- for (i = 0; i < octree.objects.length; i++) {
- this.body(octree.objects[i].sprite, 'rgb(0,255,0)', false);
- }
- } else {
- for (i = 0; i < octree.nodes.length; i++) {
- this.octree(octree.nodes[i]);
- }
- }
-
- this.stop();
-
-};
-
Phaser.Utils.Debug.prototype.body = (function (_super) {
return function (sprite, color, filled) {
@@ -1610,7 +1224,7 @@ Phaser.Utils.Debug.prototype.bodyInfo = (function (_super) {
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Cube.js.html b/doc/Cube.js.html
index 59062a1..1fab372 100644
--- a/doc/Cube.js.html
+++ b/doc/Cube.js.html
@@ -82,9 +82,11 @@
/**
- * Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
- *
* @class Phaser.Plugin.Isometric.Cube
+ *
+ * @classdesc
+ * Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
+ *
* @constructor
* @param {number} x - The x coordinate of the bottom-back corner of the Cube.
* @param {number} y - The y coordinate of the bottom-back corner of the Cube.
@@ -690,7 +692,7 @@ Phaser.Plugin.Isometric.Cube.intersects = function (a, b) {
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/IsoSprite.js.html b/doc/IsoSprite.js.html
index 9083892..0ab7dd1 100644
--- a/doc/IsoSprite.js.html
+++ b/doc/IsoSprite.js.html
@@ -82,13 +82,26 @@
/**
- * Phaser IsoSprite constructor
- * @class Phaser.Plugin.Isometric.IsoSprite
- * @constructor
+* @class Phaser.Plugin.Isometric.IsoSprite
+*
+* @classdesc
+* Create a new `IsoSprite` object. IsoSprites are extended versions of standard Sprites that are suitable for axonometric positioning.
+*
+* IsoSprites are simply Sprites that have three new position properties (isoX, isoY and isoZ) and ask the instance of Phaser.Plugin.Isometric.Projector what their position should be in a 2D scene whenever these properties are changed.
+* The IsoSprites retain their 2D position property to prevent any problems and allow you to interact with them as you would a normal Sprite. The upside of this simplicity is that things should behave predictably for those already used to Phaser.
+*
+* @constructor
+* @extends Phaser.Sprite
+* @param {Phaser.Game} game - A reference to the currently running game.
+* @param {number} x - The x coordinate (in 3D space) to position the IsoSprite at.
+* @param {number} y - The y coordinate (in 3D space) to position the IsoSprite at.
+* @param {number} z - The z coordinate (in 3D space) to position the IsoSprite at.
+* @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the IsoSprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
+* @param {string|number} frame - If this IsoSprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
*/
-Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent) {
+Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame) {
- Phaser.Sprite.call(this, game, x, y, key, frame, parent);
+ Phaser.Sprite.call(this, game, x, y, key, frame);
/**
* @property {number} type - The const type of this object.
@@ -103,7 +116,7 @@ Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent)
this._isoPosition = new Phaser.Plugin.Isometric.Point3(x, y, z);
/**
- * @property {number} snap - Snap this IsoSprite's position to this value; handy for keeping pixel art snapped to whole pixels.
+ * @property {number} snap - Snap this IsoSprite's position to the specified value; handy for keeping pixel art snapped to whole pixels.
* @default
*/
this.snap = 0;
@@ -111,18 +124,21 @@ Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent)
/**
* @property {number} _depth - Internal cached depth value.
* @readonly
+ * @private
*/
this._depth = 0;
/**
* @property {boolean} _depthChanged - Internal invalidation control for depth management.
* @readonly
+ * @private
*/
this._depthChanged = true;
/**
* @property {boolean} _isoPositionChanged - Internal invalidation control for positioning.
* @readonly
+ * @private
*/
this._isoPositionChanged = true;
@@ -166,7 +182,7 @@ Phaser.Plugin.Isometric.IsoSprite.prototype._project = function () {
/**
* The axonometric position of the IsoSprite on the x axis. Increasing the x coordinate will move the object down and to the right on the screen.
*
- * @name Phaser.Sprite#isoX
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoX
* @property {number} isoX - The axonometric position of the IsoSprite on the x axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoX", {
@@ -182,7 +198,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoX", {
/**
* The axonometric position of the IsoSprite on the y axis. Increasing the y coordinate will move the object down and to the left on the screen.
*
- * @name Phaser.Sprite#isoY
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoY
* @property {number} isoY - The axonometric position of the IsoSprite on the y axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoY", {
@@ -198,7 +214,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoY", {
/**
* The axonometric position of the IsoSprite on the z axis. Increasing the z coordinate will move the object directly upwards on the screen.
*
- * @name Phaser.Sprite#isoZ
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoZ
* @property {number} isoZ - The axonometric position of the IsoSprite on the z axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoZ", {
@@ -214,7 +230,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoZ", {
/**
* A Point3 object representing the axonometric position of the IsoSprite.
*
- * @name Phaser.Sprite#isoPosition
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoPosition
* @property {Point3} isoPosition - The axonometric position of the IsoSprite on the z axis.
* @readonly
*/
@@ -227,14 +243,14 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoPosition"
/**
* The non-unit distance of the IsoSprite from the 'front' of the scene. Used to correctly depth sort a group of IsoSprites.
*
- * @name Phaser.Sprite#depth
+ * @name Phaser.Plugin.Isometric.IsoSprite#depth
* @property {number} depth - A calculated value used for depth sorting.
* @readonly
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "depth", {
get: function () {
if (this._depthChanged === true) {
- this._depth = (this._isoPosition.x + this._isoPosition.y) + (this._isoPosition.z * 0.95);
+ this._depth = (this._isoPosition.x + this._isoPosition.y);
this._depthChanged = false;
}
return this._depth;
@@ -302,7 +318,7 @@ Phaser.GameObjectFactory.prototype.isoSprite = function (x, y, z, key, frame, gr
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Isometric.js.html b/doc/Isometric.js.html
index abee997..9072627 100644
--- a/doc/Isometric.js.html
+++ b/doc/Isometric.js.html
@@ -115,13 +115,14 @@
*/
/**
+ * @class Phaser.Plugin.Isometric
+ *
+ * @classdesc
* Isometric is a comprehensive axonometric plugin for Phaser which provides an API for handling axonometric projection of assets in 3D space to the screen.
* The goal has been to mimic as closely as possible the existing APIs provided by Phaser for standard orthogonal 2D projection, but add a third dimension.
* Also included is an Arcade-based 3D AABB physics engine, which again is closely equivalent in functionality and its API.
- *
- * @class Phaser.Plugin.Isometric
+ *
* @constructor
- *
* @param {Phaser.Game} game The current game instance.
*/
Phaser.Plugin.Isometric = function (game, parent) {
@@ -135,7 +136,7 @@ Phaser.Plugin.Isometric = function (game, parent) {
Phaser.Plugin.Isometric.prototype = Object.create(Phaser.Plugin.prototype);
Phaser.Plugin.Isometric.prototype.constructor = Phaser.Plugin.Isometric;
-Phaser.Plugin.Isometric.VERSION = '0.7.2';
+Phaser.Plugin.Isometric.VERSION = '0.7.3';
// Directional consts
Phaser.Plugin.Isometric.UP = 0;
@@ -173,7 +174,7 @@ Phaser.Plugin.Isometric.TRUE = 0.6154797093263624;
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Octree.js.html b/doc/Octree.js.html
new file mode 100644
index 0000000..fd1656e
--- /dev/null
+++ b/doc/Octree.js.html
@@ -0,0 +1,573 @@
+
+
+
+
+
+ Phaser Isometric Source: Octree.js
+
+
+
+
+
+
+
+
+
+
/**
+ * Octree Constructor
+ *
+ * @class Phaser.Plugin.Isometric.Octree
+ * @classdesc A Octree implementation based on Phaser.QuadTree.
+ * Original version at https://github.com/timohausmann/quadtree-js/
+ *
+ * @constructor
+ * @param {number} x - The bottom-back coordinate of the octree.
+ * @param {number} y - The bottom-back coordinate of the octree.
+ * @param {number} z - The bottom-back coordinate of the octree.
+ * @param {number} widthX - The width X (breadth) of the octree.
+ * @param {number} widthY - The width Y (depth) of the octree.
+ * @param {number} height - The height (Z) of the octree.
+ * @param {number} [maxObjects=10] - The maximum number of objects per node.
+ * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
+ * @param {number} [level=0] - Which level is this?
+ */
+Phaser.Plugin.Isometric.Octree = function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
+
+ /**
+ * @property {number} maxObjects - The maximum number of objects per node.
+ * @default
+ */
+ this.maxObjects = 10;
+
+ /**
+ * @property {number} maxLevels - The maximum number of levels to break down to.
+ * @default
+ */
+ this.maxLevels = 4;
+
+ /**
+ * @property {number} level - The current level.
+ */
+ this.level = 0;
+
+ /**
+ * @property {object} bounds - Object that contains the octree bounds.
+ */
+ this.bounds = {};
+
+ /**
+ * @property {array} objects - Array of octree children.
+ */
+ this.objects = [];
+
+ /**
+ * @property {array} nodes - Array of associated child nodes.
+ */
+ this.nodes = [];
+
+ /**
+ * @property {array} _empty - Internal empty array.
+ * @private
+ */
+ this._empty = [];
+
+ this.reset(x, y, z, widthX, widthY, height, maxObjects, maxLevels, level);
+
+};
+
+Phaser.Plugin.Isometric.Octree.prototype = {
+
+ /**
+ * Resets the QuadTree.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#reset
+ * @param {number} x - The bottom-back coordinate of the octree.
+ * @param {number} y - The bottom-back coordinate of the octree.
+ * @param {number} z - The bottom-back coordinate of the octree.
+ * @param {number} widthX - The width X (breadth) of the octree.
+ * @param {number} widthY - The width Y (depth) of the octree.
+ * @param {number} height - The height (Z) of the octree.
+ * @param {number} [maxObjects=10] - The maximum number of objects per node.
+ * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
+ * @param {number} [level=0] - Which level is this?
+ */
+ reset: function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
+
+ this.maxObjects = maxObjects || 10;
+ this.maxLevels = maxLevels || 4;
+ this.level = level || 0;
+
+ this.bounds = {
+ x: Math.round(x),
+ y: Math.round(y),
+ z: Math.round(z),
+ widthX: widthX,
+ widthY: widthY,
+ height: height,
+ subWidthX: Math.floor(widthX * 0.5),
+ subWidthY: Math.floor(widthY * 0.5),
+ subHeight: Math.floor(height * 0.5),
+ frontX: Math.round(x) + Math.floor(widthX * 0.5),
+ frontY: Math.round(y) + Math.floor(widthY * 0.5),
+ top: Math.round(z) + Math.floor(height * 0.5)
+ };
+
+ this.objects.length = 0;
+ this.nodes.length = 0;
+
+ },
+
+ /**
+ * Populates this octree with the children of the given Group. In order to be added the child must exist and have a body property.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#populate
+ * @param {Phaser.Group} group - The Group to add to the octree.
+ */
+ populate: function (group) {
+
+ group.forEach(this.populateHandler, this, true);
+
+ },
+
+ /**
+ * Handler for the populate method.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#populateHandler
+ * @param {Phaser.Plugin.Isometric.IsoSprite|object} sprite - The Sprite to check.
+ */
+ populateHandler: function (sprite) {
+
+ if (sprite.body && sprite.exists) {
+ this.insert(sprite.body);
+ }
+
+ },
+
+ /**
+ * Split the node into 8 subnodes
+ *
+ * @method Phaser.Plugin.Isometric.Octree#split
+ */
+ split: function () {
+
+ // bottom four octants
+ // -x-y-z
+ this.nodes[0] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x-y-z
+ this.nodes[1] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // -x+y-z
+ this.nodes[2] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x+y-z
+ this.nodes[3] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+
+ // top four octants
+ // -x-y+z
+ this.nodes[4] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x-y+z
+ this.nodes[5] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // -x+y+z
+ this.nodes[6] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x+y+z
+ this.nodes[7] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ },
+
+ /**
+ * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#insert
+ * @param {Phaser.Plugin.Isometric.Body|Phaser.Plugin.Isometric.Cube|object} body - The Body object to insert into the octree. Can be any object so long as it exposes x, y, z, frontX, frontY and top properties.
+ */
+ insert: function (body) {
+
+ var i = 0;
+ var index;
+
+ // if we have subnodes ...
+ if (this.nodes[0] !== null) {
+ index = this.getIndex(body);
+
+ if (index !== -1) {
+ this.nodes[index].insert(body);
+ return;
+ }
+ }
+
+ this.objects.push(body);
+
+ if (this.objects.length > this.maxObjects && this.level < this.maxLevels) {
+ // Split if we don't already have subnodes
+ if (this.nodes[0] === null) {
+ this.split();
+ }
+
+ // Add objects to subnodes
+ while (i < this.objects.length) {
+ index = this.getIndex(this.objects[i]);
+
+ if (index !== -1) {
+ // this is expensive - see what we can do about it
+ this.nodes[index].insert(this.objects.splice(i, 1)[0]);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ },
+
+ /**
+ * Determine which node the object belongs to.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#getIndex
+ * @param {Phaser.Plugin.Isometric.Cube|object} cube - The bounds in which to check.
+ * @return {number} index - Index of the subnode (0-7), or -1 if cube cannot completely fit within a subnode and is part of the parent node.
+ */
+ getIndex: function (cube) {
+
+ // default is that cube doesn't fit, i.e. it straddles the internal octants
+ var index = -1;
+
+ if (cube.x < this.bounds.frontX && cube.frontX < this.bounds.frontX) {
+ if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into -x-y-z octant
+ index = 0;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into -x-y+z octant
+ index = 4;
+ }
+ } else if (cube.y > this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into -x+y-z octant
+ index = 2;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into -x+y+z octant
+ index = 6;
+ }
+ }
+ } else if (cube.x > this.bounds.frontX) {
+ if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into +x-y-z octant
+ index = 1;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into +x-y+z octant
+ index = 5;
+ }
+ } else if (cube.y > this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into +x+y-z octant
+ index = 3;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into +x+y+z octant
+ index = 7;
+ }
+ }
+ }
+
+
+ return index;
+
+ },
+
+ /**
+ * Return all objects that could collide with the given IsoSprite or Cube.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#retrieve
+ * @param {Phaser.Plugin.Isometric.IsoSprite|Phaser.Plugin.Isometric.Cube} source - The source object to check the Octree against. Either a IsoSprite or Cube.
+ * @return {array} - Array with all detected objects.
+ */
+ retrieve: function (source) {
+
+ var returnObjects, index;
+
+ if (source instanceof Phaser.Plugin.Isometric.Cube) {
+ returnObjects = this.objects;
+
+ index = this.getIndex(source);
+ } else {
+ if (!source.body) {
+ return this._empty;
+ }
+
+ returnObjects = this.objects;
+
+ index = this.getIndex(source.body);
+ }
+
+ if (this.nodes[0]) {
+ // If cube fits into a subnode ..
+ if (index !== -1) {
+ returnObjects = returnObjects.concat(this.nodes[index].retrieve(source));
+ } else {
+ // If cube does not fit into a subnode, check it against all subnodes (unrolled for speed)
+ returnObjects = returnObjects.concat(this.nodes[0].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[1].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[2].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[3].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[4].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[5].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[6].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[7].retrieve(source));
+ }
+ }
+
+ return returnObjects;
+
+ },
+
+ /**
+ * Clear the octree.
+ * @method Phaser.Plugin.Isometric.Octree#clear
+ */
+ clear: function () {
+
+ this.objects.length = 0;
+
+ var i = this.nodes.length;
+
+ while (i--) {
+ this.nodes[i].clear();
+ this.nodes.splice(i, 1);
+ }
+
+ this.nodes.length = 0;
+ }
+
+};
+
+Phaser.Plugin.Isometric.Octree.prototype.constructor = Phaser.Plugin.Isometric.Octree;
+
+/**
+ * Visually renders an Octree to the display.
+ *
+ * @method Phaser.Utils.Debug#octree
+ * @param {Phaser.Plugin.Isometric.Octree} octree - The octree to render.
+ * @param {string} color - The color of the lines in the quadtree.
+ */
+Phaser.Utils.Debug.prototype.octree = function (octree, color) {
+
+ color = color || 'rgba(255,0,0,0.3)';
+
+ this.start();
+
+ var bounds = octree.bounds,
+ i, points;
+
+ if (octree.nodes.length === 0) {
+
+ this.context.strokeStyle = color;
+
+ var cube = new Phaser.Plugin.Isometric.Cube(bounds.x, bounds.y, bounds.z, bounds.widthX, bounds.widthY, bounds.height);
+ var corners = cube.getCorners();
+
+ points = corners.slice(0, corners.length);
+ points = points.map(function (p) {
+ return this.game.iso.project(p);
+ });
+
+ this.context.moveTo(points[0].x, points[0].y);
+ this.context.beginPath();
+ this.context.strokeStyle = color;
+
+ this.context.lineTo(points[1].x, points[1].y);
+ this.context.lineTo(points[3].x, points[3].y);
+ this.context.lineTo(points[2].x, points[2].y);
+ this.context.lineTo(points[6].x, points[6].y);
+ this.context.lineTo(points[4].x, points[4].y);
+ this.context.lineTo(points[5].x, points[5].y);
+ this.context.lineTo(points[1].x, points[1].y);
+ this.context.lineTo(points[0].x, points[0].y);
+ this.context.lineTo(points[4].x, points[4].y);
+ this.context.moveTo(points[0].x, points[0].y);
+ this.context.lineTo(points[2].x, points[2].y);
+ this.context.moveTo(points[3].x, points[3].y);
+ this.context.lineTo(points[7].x, points[7].y);
+ this.context.lineTo(points[6].x, points[6].y);
+ this.context.moveTo(points[7].x, points[7].y);
+ this.context.lineTo(points[5].x, points[5].y);
+ this.context.stroke();
+ this.context.closePath();
+
+ for (i = 0; i < octree.objects.length; i++) {
+ this.body(octree.objects[i].sprite, 'rgb(0,255,0)', false);
+ }
+ } else {
+ for (i = 0; i < octree.nodes.length; i++) {
+ this.octree(octree.nodes[i]);
+ }
+ }
+
+ this.stop();
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/Phaser.Plugin.Isometric.Arcade.html b/doc/Phaser.Plugin.Isometric.Arcade.html
index f6802f4..852fc5b 100644
--- a/doc/Phaser.Plugin.Isometric.Arcade.html
+++ b/doc/Phaser.Plugin.Isometric.Arcade.html
@@ -4091,7 +4091,7 @@ NOTE: This function is not recursive, and will not test against children of obje
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Phaser.Plugin.Isometric.Body.html b/doc/Phaser.Plugin.Isometric.Body.html
index 98e840e..f95fc8c 100644
--- a/doc/Phaser.Plugin.Isometric.Body.html
+++ b/doc/Phaser.Plugin.Isometric.Body.html
@@ -86,7 +86,8 @@
Body
-
IsoArcade Physics Body Constructor
+
The Physics Body is linked to a single IsoSprite. All physics operations should be performed against the body rather than
+the IsoSprite itself. For example you can set the velocity, acceleration, bounce values etc all on the Body.
@@ -104,11 +105,6 @@
-
-
The Physics Body is linked to a single IsoSprite. All physics operations should be performed against the body rather than
-the IsoSprite itself. For example you can set the velocity, acceleration, bounce values etc all on the Body.
-
-
@@ -193,7 +189,7 @@ the IsoSprite itself. For example you can set the velocity, acceleration, bounce
@@ -9605,7 +9601,7 @@ is the position of the Body relative to the center of the Sprite.
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Phaser.Plugin.Isometric.Cube.html b/doc/Phaser.Plugin.Isometric.Cube.html
index da933ef..4bb4c07 100644
--- a/doc/Phaser.Plugin.Isometric.Cube.html
+++ b/doc/Phaser.Plugin.Isometric.Cube.html
@@ -86,7 +86,7 @@
Cube
-
Phaser.Plugin.Isometric.Cube
+
Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
@@ -104,10 +104,6 @@
-
-
Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
@@ -5302,7 +5298,7 @@ This method checks the x, y, z, widthX, widthY, and height properties of the Cub
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Phaser.Plugin.Isometric.IsoSprite.html b/doc/Phaser.Plugin.Isometric.IsoSprite.html
index 2e5b415..7ce3fde 100644
--- a/doc/Phaser.Plugin.Isometric.IsoSprite.html
+++ b/doc/Phaser.Plugin.Isometric.IsoSprite.html
@@ -86,7 +86,9 @@
IsoSprite
-
Phaser.Plugin.Isometric.IsoSprite
+
Create a new IsoSprite object. IsoSprites are extended versions of standard Sprites that are suitable for axonometric positioning.
+
IsoSprites are simply Sprites that have three new position properties (isoX, isoY and isoZ) and ask the instance of Phaser.Plugin.Isometric.Projector what their position should be in a 2D scene whenever these properties are changed.
+The IsoSprites retain their 2D position property to prevent any problems and allow you to interact with them as you would a normal Sprite. The upside of this simplicity is that things should behave predictably for those already used to Phaser.
This is the image or texture used by the IsoSprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
+
+
+
+
+
+
+
frame
+
+
+
+
+
+string
+|
+
+number
+
+
+
+
+
+
+
+
+
+
If this IsoSprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
@@ -846,7 +1264,7 @@
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Phaser.Plugin.Isometric.Octree.html b/doc/Phaser.Plugin.Isometric.Octree.html
index 3488dcd..0d80abf 100644
--- a/doc/Phaser.Plugin.Isometric.Octree.html
+++ b/doc/Phaser.Plugin.Isometric.Octree.html
@@ -86,8 +86,7 @@
Octree
-
A Octree implementation. The original code was a conversion of the Java code posted to GameDevTuts.
-However I've tweaked it massively to add node indexing, removed lots of temp. var creation and significantly increased performance as a result.
+
@@ -2518,7 +2517,7 @@ Original version at https
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Phaser.Plugin.Isometric.Point3.html b/doc/Phaser.Plugin.Isometric.Point3.html
index 2c44787..6469d28 100644
--- a/doc/Phaser.Plugin.Isometric.Point3.html
+++ b/doc/Phaser.Plugin.Isometric.Point3.html
@@ -89,3194 +89,8 @@
The Point3 object represents a location in a three-dimensional coordinate system,
where x and y represent the horizontal axes and z represents the vertical axis.
The following code creates a point at (0,0,0):
-var myPoint = new Phaser.Plugin.Isometric.Point3();
Sets the x, y and z values of this Point3 object to the given values.
-If you omit the y and z value then the x value will be applied to all three, for example:
-Point3.set(2) is the same as Point3.set(2, 2, 2)
-If however you set both x and y, but no z, the z value will be set to 0.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
-
-
-
-
-
Name
-
-
-
Type
-
-
-
Argument
-
-
-
-
-
Description
-
-
-
-
-
-
-
-
-
x
-
-
-
-
-
-number
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
The x value of this point.
-
-
-
-
-
-
-
y
-
-
-
-
-
-number
-
-
-
-
-
-
-
-
- <optional>
-
-
-
-
-
-
-
-
-
-
-
The y value of this point. If not given the x value will be used in its place.
-
-
-
-
-
-
-
z
-
-
-
-
-
-number
-
-
-
-
-
-
-
-
- <optional>
-
-
-
-
-
-
-
-
-
-
-
The z value of this point. If not given and the y value is also not given, the x value will be used in its place.
Sets the x, y and z values of this Point3 object to the given values.
-If you omit the y and z value then the x value will be applied to all three, for example:
-Point3.setTo(2) is the same as Point3.setTo(2, 2, 2)
-If however you set both x and y, but no z, the z value will be set to 0.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
-
-
-
-
-
Name
-
-
-
Type
-
-
-
Argument
-
-
-
-
-
Description
-
-
-
-
-
-
-
-
-
x
-
-
-
-
-
-number
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
The x value of this point.
-
-
-
-
-
-
-
y
-
-
-
-
-
-number
-
-
-
-
-
-
-
-
- <optional>
-
-
-
-
-
-
-
-
-
-
-
The y value of this point. If not given the x value will be used in its place.
-
-
-
-
-
-
-
z
-
-
-
-
-
-number
-
-
-
-
-
-
-
-
- <optional>
-
-
-
-
-
-
-
-
-
-
-
The z value of this point. If not given and the y value is also not given, the x value will be used in its place.
@@ -6618,7 +3428,7 @@ If however you set both x and y, but no z, the z value will be set to 0.
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Phaser.Plugin.Isometric.Projector.html b/doc/Phaser.Plugin.Isometric.Projector.html
index 4c4d0c5..d16ad65 100644
--- a/doc/Phaser.Plugin.Isometric.Projector.html
+++ b/doc/Phaser.Plugin.Isometric.Projector.html
@@ -86,7 +86,7 @@
Projector
-
Phaser.Plugin.Isometric.Projector
+
Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
@@ -104,10 +104,6 @@
-
-
Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
@@ -982,7 +978,7 @@
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Phaser.Plugin.Isometric.html b/doc/Phaser.Plugin.Isometric.html
index 04cc409..77ea6d7 100644
--- a/doc/Phaser.Plugin.Isometric.html
+++ b/doc/Phaser.Plugin.Isometric.html
@@ -84,7 +84,9 @@
Isometric
-
Phaser.Plugin.Isometric
+
Isometric is a comprehensive axonometric plugin for Phaser which provides an API for handling axonometric projection of assets in 3D space to the screen.
+The goal has been to mimic as closely as possible the existing APIs provided by Phaser for standard orthogonal 2D projection, but add a third dimension.
+Also included is an Arcade-based 3D AABB physics engine, which again is closely equivalent in functionality and its API.
@@ -102,12 +104,6 @@
-
-
Isometric is a comprehensive axonometric plugin for Phaser which provides an API for handling axonometric projection of assets in 3D space to the screen.
-The goal has been to mimic as closely as possible the existing APIs provided by Phaser for standard orthogonal 2D projection, but add a third dimension.
-Also included is an Arcade-based 3D AABB physics engine, which again is closely equivalent in functionality and its API.
-
-
@@ -192,7 +188,7 @@ Also included is an Arcade-based 3D AABB physics engine, which again is closely
@@ -287,7 +280,7 @@ Also included is an Arcade-based 3D AABB physics engine, which again is closely
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Point3.js.html b/doc/Point3.js.html
index edcf269..aa93921 100644
--- a/doc/Point3.js.html
+++ b/doc/Point3.js.html
@@ -83,14 +83,13 @@
/**
* @class Phaser.Plugin.Isometric.Point3
+ *
* @classdesc
* The Point3 object represents a location in a three-dimensional coordinate system,
* where x and y represent the horizontal axes and z represents the vertical axis.
* The following code creates a point at (0,0,0):
* `var myPoint = new Phaser.Plugin.Isometric.Point3();`
- */
-
-/**
+ *
* Creates a new Point3 object. If you pass no parameters a Point3 is created set to (0, 0, 0).
*
* @constructor
@@ -402,7 +401,7 @@ Phaser.Plugin.Isometric.Point3.equals = function (a, b) {
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/Projector.js.html b/doc/Projector.js.html
index 6b8897f..f84319a 100644
--- a/doc/Projector.js.html
+++ b/doc/Projector.js.html
@@ -82,9 +82,11 @@
/**
- * Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
- *
* @class Phaser.Plugin.Isometric.Projector
+ *
+ * @classdesc
+ * Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
+ *
* @constructor
* @param {Phaser.Game} game - The current game object.
* @param {number} projectionRatio - The ratio of the axonometric projection.
@@ -178,7 +180,7 @@ Phaser.Plugin.Isometric.Projector.prototype = {
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/World.js.html b/doc/World.js.html
index b35c1d0..f5d730d 100644
--- a/doc/World.js.html
+++ b/doc/World.js.html
@@ -1179,7 +1179,7 @@ Phaser.Physics.prototype.destroy = (function (_super) {
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/classes.list.html b/doc/classes.list.html
index e84a3cb..3d97d14 100644
--- a/doc/classes.list.html
+++ b/doc/classes.list.html
@@ -160,9 +160,6 @@
@@ -197,7 +194,7 @@
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/doc/index.html b/doc/index.html
index b5bc516..49f0144 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -118,7 +118,7 @@
Documentation generated by JSDoc 3.2.2
- on Wed Aug 6th 2014 using the DocStrap template.
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9e5ebe5
--- /dev/null
+++ b/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "phaser-plugin-isometric",
+ "version": "0.7.3",
+ "devDependencies": {
+ "grunt": "~0.4.5",
+ "grunt-contrib-clean": "^0.5.0",
+ "grunt-contrib-jshint": "^0.9.2",
+ "grunt-contrib-uglify": "^0.4.0",
+ "grunt-contrib-concat": "^0.4.0",
+ "grunt-contrib-watch": "*",
+ "grunt-jsdoc": "~0.5.6"
+ }
+}
diff --git a/src/Cube.js b/src/Cube.js
index 53a79ad..d53d2db 100644
--- a/src/Cube.js
+++ b/src/Cube.js
@@ -1,7 +1,9 @@
/**
- * Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
- *
* @class Phaser.Plugin.Isometric.Cube
+ *
+ * @classdesc
+ * Creates a new Cube object with the bottom-back corner specified by the x, y and z parameters, with the specified breadth (widthX), depth (widthY) and height parameters. If you call this function without parameters, a Cube with x, y, z, breadth, depth and height properties set to 0 is created.
+ *
* @constructor
* @param {number} x - The x coordinate of the bottom-back corner of the Cube.
* @param {number} y - The y coordinate of the bottom-back corner of the Cube.
diff --git a/src/IsoSprite.js b/src/IsoSprite.js
index 580c8bb..9d7fe73 100644
--- a/src/IsoSprite.js
+++ b/src/IsoSprite.js
@@ -1,11 +1,24 @@
/**
- * Phaser IsoSprite constructor
- * @class Phaser.Plugin.Isometric.IsoSprite
- * @constructor
+* @class Phaser.Plugin.Isometric.IsoSprite
+*
+* @classdesc
+* Create a new `IsoSprite` object. IsoSprites are extended versions of standard Sprites that are suitable for axonometric positioning.
+*
+* IsoSprites are simply Sprites that have three new position properties (isoX, isoY and isoZ) and ask the instance of Phaser.Plugin.Isometric.Projector what their position should be in a 2D scene whenever these properties are changed.
+* The IsoSprites retain their 2D position property to prevent any problems and allow you to interact with them as you would a normal Sprite. The upside of this simplicity is that things should behave predictably for those already used to Phaser.
+*
+* @constructor
+* @extends Phaser.Sprite
+* @param {Phaser.Game} game - A reference to the currently running game.
+* @param {number} x - The x coordinate (in 3D space) to position the IsoSprite at.
+* @param {number} y - The y coordinate (in 3D space) to position the IsoSprite at.
+* @param {number} z - The z coordinate (in 3D space) to position the IsoSprite at.
+* @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the IsoSprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
+* @param {string|number} frame - If this IsoSprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
*/
-Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent) {
+Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame) {
- Phaser.Sprite.call(this, game, x, y, key, frame, parent);
+ Phaser.Sprite.call(this, game, x, y, key, frame);
/**
* @property {number} type - The const type of this object.
@@ -20,7 +33,7 @@ Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent)
this._isoPosition = new Phaser.Plugin.Isometric.Point3(x, y, z);
/**
- * @property {number} snap - Snap this IsoSprite's position to this value; handy for keeping pixel art snapped to whole pixels.
+ * @property {number} snap - Snap this IsoSprite's position to the specified value; handy for keeping pixel art snapped to whole pixels.
* @default
*/
this.snap = 0;
@@ -28,18 +41,21 @@ Phaser.Plugin.Isometric.IsoSprite = function (game, x, y, z, key, frame, parent)
/**
* @property {number} _depth - Internal cached depth value.
* @readonly
+ * @private
*/
this._depth = 0;
/**
* @property {boolean} _depthChanged - Internal invalidation control for depth management.
* @readonly
+ * @private
*/
this._depthChanged = true;
/**
* @property {boolean} _isoPositionChanged - Internal invalidation control for positioning.
* @readonly
+ * @private
*/
this._isoPositionChanged = true;
@@ -83,7 +99,7 @@ Phaser.Plugin.Isometric.IsoSprite.prototype._project = function () {
/**
* The axonometric position of the IsoSprite on the x axis. Increasing the x coordinate will move the object down and to the right on the screen.
*
- * @name Phaser.Sprite#isoX
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoX
* @property {number} isoX - The axonometric position of the IsoSprite on the x axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoX", {
@@ -99,7 +115,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoX", {
/**
* The axonometric position of the IsoSprite on the y axis. Increasing the y coordinate will move the object down and to the left on the screen.
*
- * @name Phaser.Sprite#isoY
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoY
* @property {number} isoY - The axonometric position of the IsoSprite on the y axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoY", {
@@ -115,7 +131,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoY", {
/**
* The axonometric position of the IsoSprite on the z axis. Increasing the z coordinate will move the object directly upwards on the screen.
*
- * @name Phaser.Sprite#isoZ
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoZ
* @property {number} isoZ - The axonometric position of the IsoSprite on the z axis.
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoZ", {
@@ -131,7 +147,7 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoZ", {
/**
* A Point3 object representing the axonometric position of the IsoSprite.
*
- * @name Phaser.Sprite#isoPosition
+ * @name Phaser.Plugin.Isometric.IsoSprite#isoPosition
* @property {Point3} isoPosition - The axonometric position of the IsoSprite on the z axis.
* @readonly
*/
@@ -144,14 +160,14 @@ Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "isoPosition"
/**
* The non-unit distance of the IsoSprite from the 'front' of the scene. Used to correctly depth sort a group of IsoSprites.
*
- * @name Phaser.Sprite#depth
+ * @name Phaser.Plugin.Isometric.IsoSprite#depth
* @property {number} depth - A calculated value used for depth sorting.
* @readonly
*/
Object.defineProperty(Phaser.Plugin.Isometric.IsoSprite.prototype, "depth", {
get: function () {
if (this._depthChanged === true) {
- this._depth = (this._isoPosition.x + this._isoPosition.y) + (this._isoPosition.z * 0.95);
+ this._depth = (this._isoPosition.x + this._isoPosition.y);
this._depthChanged = false;
}
return this._depth;
diff --git a/src/Isometric.js b/src/Isometric.js
index 60bf330..a4b7c1b 100644
--- a/src/Isometric.js
+++ b/src/Isometric.js
@@ -32,13 +32,14 @@
*/
/**
+ * @class Phaser.Plugin.Isometric
+ *
+ * @classdesc
* Isometric is a comprehensive axonometric plugin for Phaser which provides an API for handling axonometric projection of assets in 3D space to the screen.
* The goal has been to mimic as closely as possible the existing APIs provided by Phaser for standard orthogonal 2D projection, but add a third dimension.
* Also included is an Arcade-based 3D AABB physics engine, which again is closely equivalent in functionality and its API.
- *
- * @class Phaser.Plugin.Isometric
+ *
* @constructor
- *
* @param {Phaser.Game} game The current game instance.
*/
Phaser.Plugin.Isometric = function (game, parent) {
@@ -52,7 +53,7 @@ Phaser.Plugin.Isometric = function (game, parent) {
Phaser.Plugin.Isometric.prototype = Object.create(Phaser.Plugin.prototype);
Phaser.Plugin.Isometric.prototype.constructor = Phaser.Plugin.Isometric;
-Phaser.Plugin.Isometric.VERSION = '0.7.2';
+Phaser.Plugin.Isometric.VERSION = '0.7.3';
// Directional consts
Phaser.Plugin.Isometric.UP = 0;
diff --git a/src/Octree.js b/src/Octree.js
new file mode 100644
index 0000000..f0c5fe7
--- /dev/null
+++ b/src/Octree.js
@@ -0,0 +1,388 @@
+/**
+ * Octree Constructor
+ *
+ * @class Phaser.Plugin.Isometric.Octree
+ * @classdesc A Octree implementation based on Phaser.QuadTree.
+ * Original version at https://github.com/timohausmann/quadtree-js/
+ *
+ * @constructor
+ * @param {number} x - The bottom-back coordinate of the octree.
+ * @param {number} y - The bottom-back coordinate of the octree.
+ * @param {number} z - The bottom-back coordinate of the octree.
+ * @param {number} widthX - The width X (breadth) of the octree.
+ * @param {number} widthY - The width Y (depth) of the octree.
+ * @param {number} height - The height (Z) of the octree.
+ * @param {number} [maxObjects=10] - The maximum number of objects per node.
+ * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
+ * @param {number} [level=0] - Which level is this?
+ */
+Phaser.Plugin.Isometric.Octree = function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
+
+ /**
+ * @property {number} maxObjects - The maximum number of objects per node.
+ * @default
+ */
+ this.maxObjects = 10;
+
+ /**
+ * @property {number} maxLevels - The maximum number of levels to break down to.
+ * @default
+ */
+ this.maxLevels = 4;
+
+ /**
+ * @property {number} level - The current level.
+ */
+ this.level = 0;
+
+ /**
+ * @property {object} bounds - Object that contains the octree bounds.
+ */
+ this.bounds = {};
+
+ /**
+ * @property {array} objects - Array of octree children.
+ */
+ this.objects = [];
+
+ /**
+ * @property {array} nodes - Array of associated child nodes.
+ */
+ this.nodes = [];
+
+ /**
+ * @property {array} _empty - Internal empty array.
+ * @private
+ */
+ this._empty = [];
+
+ this.reset(x, y, z, widthX, widthY, height, maxObjects, maxLevels, level);
+
+};
+
+Phaser.Plugin.Isometric.Octree.prototype = {
+
+ /**
+ * Resets the QuadTree.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#reset
+ * @param {number} x - The bottom-back coordinate of the octree.
+ * @param {number} y - The bottom-back coordinate of the octree.
+ * @param {number} z - The bottom-back coordinate of the octree.
+ * @param {number} widthX - The width X (breadth) of the octree.
+ * @param {number} widthY - The width Y (depth) of the octree.
+ * @param {number} height - The height (Z) of the octree.
+ * @param {number} [maxObjects=10] - The maximum number of objects per node.
+ * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
+ * @param {number} [level=0] - Which level is this?
+ */
+ reset: function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
+
+ this.maxObjects = maxObjects || 10;
+ this.maxLevels = maxLevels || 4;
+ this.level = level || 0;
+
+ this.bounds = {
+ x: Math.round(x),
+ y: Math.round(y),
+ z: Math.round(z),
+ widthX: widthX,
+ widthY: widthY,
+ height: height,
+ subWidthX: Math.floor(widthX * 0.5),
+ subWidthY: Math.floor(widthY * 0.5),
+ subHeight: Math.floor(height * 0.5),
+ frontX: Math.round(x) + Math.floor(widthX * 0.5),
+ frontY: Math.round(y) + Math.floor(widthY * 0.5),
+ top: Math.round(z) + Math.floor(height * 0.5)
+ };
+
+ this.objects.length = 0;
+ this.nodes.length = 0;
+
+ },
+
+ /**
+ * Populates this octree with the children of the given Group. In order to be added the child must exist and have a body property.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#populate
+ * @param {Phaser.Group} group - The Group to add to the octree.
+ */
+ populate: function (group) {
+
+ group.forEach(this.populateHandler, this, true);
+
+ },
+
+ /**
+ * Handler for the populate method.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#populateHandler
+ * @param {Phaser.Plugin.Isometric.IsoSprite|object} sprite - The Sprite to check.
+ */
+ populateHandler: function (sprite) {
+
+ if (sprite.body && sprite.exists) {
+ this.insert(sprite.body);
+ }
+
+ },
+
+ /**
+ * Split the node into 8 subnodes
+ *
+ * @method Phaser.Plugin.Isometric.Octree#split
+ */
+ split: function () {
+
+ // bottom four octants
+ // -x-y-z
+ this.nodes[0] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x-y-z
+ this.nodes[1] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // -x+y-z
+ this.nodes[2] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x+y-z
+ this.nodes[3] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+
+ // top four octants
+ // -x-y+z
+ this.nodes[4] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x-y+z
+ this.nodes[5] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // -x+y+z
+ this.nodes[6] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ // +x+y+z
+ this.nodes[7] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
+ },
+
+ /**
+ * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#insert
+ * @param {Phaser.Plugin.Isometric.Body|Phaser.Plugin.Isometric.Cube|object} body - The Body object to insert into the octree. Can be any object so long as it exposes x, y, z, frontX, frontY and top properties.
+ */
+ insert: function (body) {
+
+ var i = 0;
+ var index;
+
+ // if we have subnodes ...
+ if (this.nodes[0] !== null) {
+ index = this.getIndex(body);
+
+ if (index !== -1) {
+ this.nodes[index].insert(body);
+ return;
+ }
+ }
+
+ this.objects.push(body);
+
+ if (this.objects.length > this.maxObjects && this.level < this.maxLevels) {
+ // Split if we don't already have subnodes
+ if (this.nodes[0] === null) {
+ this.split();
+ }
+
+ // Add objects to subnodes
+ while (i < this.objects.length) {
+ index = this.getIndex(this.objects[i]);
+
+ if (index !== -1) {
+ // this is expensive - see what we can do about it
+ this.nodes[index].insert(this.objects.splice(i, 1)[0]);
+ } else {
+ i++;
+ }
+ }
+ }
+
+ },
+
+ /**
+ * Determine which node the object belongs to.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#getIndex
+ * @param {Phaser.Plugin.Isometric.Cube|object} cube - The bounds in which to check.
+ * @return {number} index - Index of the subnode (0-7), or -1 if cube cannot completely fit within a subnode and is part of the parent node.
+ */
+ getIndex: function (cube) {
+
+ // default is that cube doesn't fit, i.e. it straddles the internal octants
+ var index = -1;
+
+ if (cube.x < this.bounds.frontX && cube.frontX < this.bounds.frontX) {
+ if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into -x-y-z octant
+ index = 0;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into -x-y+z octant
+ index = 4;
+ }
+ } else if (cube.y > this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into -x+y-z octant
+ index = 2;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into -x+y+z octant
+ index = 6;
+ }
+ }
+ } else if (cube.x > this.bounds.frontX) {
+ if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into +x-y-z octant
+ index = 1;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into +x-y+z octant
+ index = 5;
+ }
+ } else if (cube.y > this.bounds.frontY) {
+ if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
+ // cube fits into +x+y-z octant
+ index = 3;
+ } else if (cube.z > this.bounds.top) {
+ // cube fits into +x+y+z octant
+ index = 7;
+ }
+ }
+ }
+
+
+ return index;
+
+ },
+
+ /**
+ * Return all objects that could collide with the given IsoSprite or Cube.
+ *
+ * @method Phaser.Plugin.Isometric.Octree#retrieve
+ * @param {Phaser.Plugin.Isometric.IsoSprite|Phaser.Plugin.Isometric.Cube} source - The source object to check the Octree against. Either a IsoSprite or Cube.
+ * @return {array} - Array with all detected objects.
+ */
+ retrieve: function (source) {
+
+ var returnObjects, index;
+
+ if (source instanceof Phaser.Plugin.Isometric.Cube) {
+ returnObjects = this.objects;
+
+ index = this.getIndex(source);
+ } else {
+ if (!source.body) {
+ return this._empty;
+ }
+
+ returnObjects = this.objects;
+
+ index = this.getIndex(source.body);
+ }
+
+ if (this.nodes[0]) {
+ // If cube fits into a subnode ..
+ if (index !== -1) {
+ returnObjects = returnObjects.concat(this.nodes[index].retrieve(source));
+ } else {
+ // If cube does not fit into a subnode, check it against all subnodes (unrolled for speed)
+ returnObjects = returnObjects.concat(this.nodes[0].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[1].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[2].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[3].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[4].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[5].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[6].retrieve(source));
+ returnObjects = returnObjects.concat(this.nodes[7].retrieve(source));
+ }
+ }
+
+ return returnObjects;
+
+ },
+
+ /**
+ * Clear the octree.
+ * @method Phaser.Plugin.Isometric.Octree#clear
+ */
+ clear: function () {
+
+ this.objects.length = 0;
+
+ var i = this.nodes.length;
+
+ while (i--) {
+ this.nodes[i].clear();
+ this.nodes.splice(i, 1);
+ }
+
+ this.nodes.length = 0;
+ }
+
+};
+
+Phaser.Plugin.Isometric.Octree.prototype.constructor = Phaser.Plugin.Isometric.Octree;
+
+/**
+ * Visually renders an Octree to the display.
+ *
+ * @method Phaser.Utils.Debug#octree
+ * @param {Phaser.Plugin.Isometric.Octree} octree - The octree to render.
+ * @param {string} color - The color of the lines in the quadtree.
+ */
+Phaser.Utils.Debug.prototype.octree = function (octree, color) {
+
+ color = color || 'rgba(255,0,0,0.3)';
+
+ this.start();
+
+ var bounds = octree.bounds,
+ i, points;
+
+ if (octree.nodes.length === 0) {
+
+ this.context.strokeStyle = color;
+
+ var cube = new Phaser.Plugin.Isometric.Cube(bounds.x, bounds.y, bounds.z, bounds.widthX, bounds.widthY, bounds.height);
+ var corners = cube.getCorners();
+
+ points = corners.slice(0, corners.length);
+ points = points.map(function (p) {
+ return this.game.iso.project(p);
+ });
+
+ this.context.moveTo(points[0].x, points[0].y);
+ this.context.beginPath();
+ this.context.strokeStyle = color;
+
+ this.context.lineTo(points[1].x, points[1].y);
+ this.context.lineTo(points[3].x, points[3].y);
+ this.context.lineTo(points[2].x, points[2].y);
+ this.context.lineTo(points[6].x, points[6].y);
+ this.context.lineTo(points[4].x, points[4].y);
+ this.context.lineTo(points[5].x, points[5].y);
+ this.context.lineTo(points[1].x, points[1].y);
+ this.context.lineTo(points[0].x, points[0].y);
+ this.context.lineTo(points[4].x, points[4].y);
+ this.context.moveTo(points[0].x, points[0].y);
+ this.context.lineTo(points[2].x, points[2].y);
+ this.context.moveTo(points[3].x, points[3].y);
+ this.context.lineTo(points[7].x, points[7].y);
+ this.context.lineTo(points[6].x, points[6].y);
+ this.context.moveTo(points[7].x, points[7].y);
+ this.context.lineTo(points[5].x, points[5].y);
+ this.context.stroke();
+ this.context.closePath();
+
+ for (i = 0; i < octree.objects.length; i++) {
+ this.body(octree.objects[i].sprite, 'rgb(0,255,0)', false);
+ }
+ } else {
+ for (i = 0; i < octree.nodes.length; i++) {
+ this.octree(octree.nodes[i]);
+ }
+ }
+
+ this.stop();
+
+};
diff --git a/src/Point3.js b/src/Point3.js
index dbc0814..db20986 100644
--- a/src/Point3.js
+++ b/src/Point3.js
@@ -1,13 +1,12 @@
/**
* @class Phaser.Plugin.Isometric.Point3
+ *
* @classdesc
* The Point3 object represents a location in a three-dimensional coordinate system,
* where x and y represent the horizontal axes and z represents the vertical axis.
* The following code creates a point at (0,0,0):
* `var myPoint = new Phaser.Plugin.Isometric.Point3();`
- */
-
-/**
+ *
* Creates a new Point3 object. If you pass no parameters a Point3 is created set to (0, 0, 0).
*
* @constructor
diff --git a/src/Projector.js b/src/Projector.js
index c121178..903950f 100644
--- a/src/Projector.js
+++ b/src/Projector.js
@@ -1,7 +1,9 @@
/**
- * Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
- *
* @class Phaser.Plugin.Isometric.Projector
+ *
+ * @classdesc
+ * Creates a new Isometric Projector object, which has helpers for projecting x, y and z coordinates into axonometric x and y equivalents.
+ *
* @constructor
* @param {Phaser.Game} game - The current game object.
* @param {number} projectionRatio - The ratio of the axonometric projection.
diff --git a/src/physics/Body.js b/src/physics/Body.js
index e2bb8b4..0e8daf8 100644
--- a/src/physics/Body.js
+++ b/src/physics/Body.js
@@ -1,9 +1,10 @@
/**
+ * @class Phaser.Plugin.Isometric.Body
+ *
+ * @classdesc
* The Physics Body is linked to a single IsoSprite. All physics operations should be performed against the body rather than
* the IsoSprite itself. For example you can set the velocity, acceleration, bounce values etc all on the Body.
- *
- * @class Phaser.Plugin.Isometric.Body
- * @classdesc IsoArcade Physics Body Constructor
+ *
* @constructor
* @param {Phaser.Plugin.Isometric.IsoSprite} sprite - The IsoSprite object this physics body belongs to.
*/
@@ -712,7 +713,7 @@ Phaser.Plugin.Isometric.Body.prototype = {
this.position.x = x + ((this.widthX * -this.sprite.anchor.x) + this.widthX * 0.5) + this.offset.x;
this.position.y = y + ((this.widthY * this.sprite.anchor.x) - this.widthY * 0.5) + this.offset.y;
- this.position.z = z - ((this.height * -this.sprite.anchor.y * 2) + this.height) + this.offset.z;
+ this.position.z = z - (Math.abs(this.sprite.height) * (1 - this.sprite.anchor.y)) + (Math.abs(this.sprite.width * 0.5)) + this.offset.z;
this.prev.x = this.position.x;
this.prev.y = this.position.y;
@@ -726,6 +727,8 @@ Phaser.Plugin.Isometric.Body.prototype = {
this.center.setTo(this.position.x + this.halfWidthX, this.position.y + this.halfWidthY, this.position.z + this.halfHeight);
+ this.sprite._isoPositionChanged = true;
+
},
/**
@@ -1090,395 +1093,6 @@ Phaser.Plugin.Isometric.Body.renderBodyInfo = function (debug, body) {
Phaser.Plugin.Isometric.Body.prototype.constructor = Phaser.Plugin.Isometric.Body;
-/**
- * Octree Constructor
- *
- * @class Phaser.Plugin.Isometric.Octree
- * @classdesc A Octree implementation. The original code was a conversion of the Java code posted to GameDevTuts.
- * However I've tweaked it massively to add node indexing, removed lots of temp. var creation and significantly increased performance as a result.
- * Original version at https://github.com/timohausmann/quadtree-js/
- * @constructor
- * @param {number} x - The bottom-back coordinate of the octree.
- * @param {number} y - The bottom-back coordinate of the octree.
- * @param {number} z - The bottom-back coordinate of the octree.
- * @param {number} widthX - The width X (breadth) of the octree.
- * @param {number} widthY - The width Y (depth) of the octree.
- * @param {number} height - The height (Z) of the octree.
- * @param {number} [maxObjects=10] - The maximum number of objects per node.
- * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
- * @param {number} [level=0] - Which level is this?
- */
-Phaser.Plugin.Isometric.Octree = function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
-
- /**
- * @property {number} maxObjects - The maximum number of objects per node.
- * @default
- */
- this.maxObjects = 10;
-
- /**
- * @property {number} maxLevels - The maximum number of levels to break down to.
- * @default
- */
- this.maxLevels = 4;
-
- /**
- * @property {number} level - The current level.
- */
- this.level = 0;
-
- /**
- * @property {object} bounds - Object that contains the octree bounds.
- */
- this.bounds = {};
-
- /**
- * @property {array} objects - Array of octree children.
- */
- this.objects = [];
-
- /**
- * @property {array} nodes - Array of associated child nodes.
- */
- this.nodes = [];
-
- /**
- * @property {array} _empty - Internal empty array.
- * @private
- */
- this._empty = [];
-
- this.reset(x, y, z, widthX, widthY, height, maxObjects, maxLevels, level);
-
-};
-
-Phaser.Plugin.Isometric.Octree.prototype = {
-
- /**
- * Resets the QuadTree.
- *
- * @method Phaser.Plugin.Isometric.Octree#reset
- * @param {number} x - The bottom-back coordinate of the octree.
- * @param {number} y - The bottom-back coordinate of the octree.
- * @param {number} z - The bottom-back coordinate of the octree.
- * @param {number} widthX - The width X (breadth) of the octree.
- * @param {number} widthY - The width Y (depth) of the octree.
- * @param {number} height - The height (Z) of the octree.
- * @param {number} [maxObjects=10] - The maximum number of objects per node.
- * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
- * @param {number} [level=0] - Which level is this?
- */
- reset: function (x, y, z, widthX, widthY, height, maxObjects, maxLevels, level) {
-
- this.maxObjects = maxObjects || 10;
- this.maxLevels = maxLevels || 4;
- this.level = level || 0;
-
- this.bounds = {
- x: Math.round(x),
- y: Math.round(y),
- z: Math.round(z),
- widthX: widthX,
- widthY: widthY,
- height: height,
- subWidthX: Math.floor(widthX * 0.5),
- subWidthY: Math.floor(widthY * 0.5),
- subHeight: Math.floor(height * 0.5),
- frontX: Math.round(x) + Math.floor(widthX * 0.5),
- frontY: Math.round(y) + Math.floor(widthY * 0.5),
- top: Math.round(z) + Math.floor(height * 0.5)
- };
-
- this.objects.length = 0;
- this.nodes.length = 0;
-
- },
-
- /**
- * Populates this octree with the children of the given Group. In order to be added the child must exist and have a body property.
- *
- * @method Phaser.Plugin.Isometric.Octree#populate
- * @param {Phaser.Group} group - The Group to add to the octree.
- */
- populate: function (group) {
-
- group.forEach(this.populateHandler, this, true);
-
- },
-
- /**
- * Handler for the populate method.
- *
- * @method Phaser.Plugin.Isometric.Octree#populateHandler
- * @param {Phaser.Plugin.Isometric.IsoSprite|object} sprite - The Sprite to check.
- */
- populateHandler: function (sprite) {
-
- if (sprite.body && sprite.exists) {
- this.insert(sprite.body);
- }
-
- },
-
- /**
- * Split the node into 8 subnodes
- *
- * @method Phaser.Plugin.Isometric.Octree#split
- */
- split: function () {
-
- // bottom four octants
- // -x-y-z
- this.nodes[0] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x-y-z
- this.nodes[1] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // -x+y-z
- this.nodes[2] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x+y-z
- this.nodes[3] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.z, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
-
- // top four octants
- // -x-y+z
- this.nodes[4] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x-y+z
- this.nodes[5] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.y, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // -x+y+z
- this.nodes[6] = new Phaser.Plugin.Isometric.Octree(this.bounds.x, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- // +x+y+z
- this.nodes[7] = new Phaser.Plugin.Isometric.Octree(this.bounds.frontX, this.bounds.frontY, this.bounds.top, this.bounds.subWidthX, this.bounds.subWidthY, this.bounds.subHeight, this.maxLevels, (this.level + 1));
- },
-
- /**
- * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.
- *
- * @method Phaser.Plugin.Isometric.Octree#insert
- * @param {Phaser.Plugin.Isometric.Body|Phaser.Plugin.Isometric.Cube|object} body - The Body object to insert into the octree. Can be any object so long as it exposes x, y, z, frontX, frontY and top properties.
- */
- insert: function (body) {
-
- var i = 0;
- var index;
-
- // if we have subnodes ...
- if (this.nodes[0] !== null) {
- index = this.getIndex(body);
-
- if (index !== -1) {
- this.nodes[index].insert(body);
- return;
- }
- }
-
- this.objects.push(body);
-
- if (this.objects.length > this.maxObjects && this.level < this.maxLevels) {
- // Split if we don't already have subnodes
- if (this.nodes[0] === null) {
- this.split();
- }
-
- // Add objects to subnodes
- while (i < this.objects.length) {
- index = this.getIndex(this.objects[i]);
-
- if (index !== -1) {
- // this is expensive - see what we can do about it
- this.nodes[index].insert(this.objects.splice(i, 1)[0]);
- } else {
- i++;
- }
- }
- }
-
- },
-
- /**
- * Determine which node the object belongs to.
- *
- * @method Phaser.Plugin.Isometric.Octree#getIndex
- * @param {Phaser.Plugin.Isometric.Cube|object} cube - The bounds in which to check.
- * @return {number} index - Index of the subnode (0-7), or -1 if cube cannot completely fit within a subnode and is part of the parent node.
- */
- getIndex: function (cube) {
-
- // default is that cube doesn't fit, i.e. it straddles the internal octants
- var index = -1;
-
- if (cube.x < this.bounds.frontX && cube.frontX < this.bounds.frontX) {
- if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into -x-y-z octant
- index = 0;
- } else if (cube.z > this.bounds.top) {
- // cube fits into -x-y+z octant
- index = 4;
- }
- } else if (cube.y > this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into -x+y-z octant
- index = 2;
- } else if (cube.z > this.bounds.top) {
- // cube fits into -x+y+z octant
- index = 6;
- }
- }
- } else if (cube.x > this.bounds.frontX) {
- if (cube.y < this.bounds.frontY && cube.frontY < this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into +x-y-z octant
- index = 1;
- } else if (cube.z > this.bounds.top) {
- // cube fits into +x-y+z octant
- index = 5;
- }
- } else if (cube.y > this.bounds.frontY) {
- if (cube.z < this.bounds.top && cube.top < this.bounds.top) {
- // cube fits into +x+y-z octant
- index = 3;
- } else if (cube.z > this.bounds.top) {
- // cube fits into +x+y+z octant
- index = 7;
- }
- }
- }
-
-
- return index;
-
- },
-
- /**
- * Return all objects that could collide with the given IsoSprite or Cube.
- *
- * @method Phaser.Plugin.Isometric.Octree#retrieve
- * @param {Phaser.Plugin.Isometric.IsoSprite|Phaser.Plugin.Isometric.Cube} source - The source object to check the Octree against. Either a IsoSprite or Cube.
- * @return {array} - Array with all detected objects.
- */
- retrieve: function (source) {
-
- var returnObjects, index;
-
- if (source instanceof Phaser.Plugin.Isometric.Cube) {
- returnObjects = this.objects;
-
- index = this.getIndex(source);
- } else {
- if (!source.body) {
- return this._empty;
- }
-
- returnObjects = this.objects;
-
- index = this.getIndex(source.body);
- }
-
- if (this.nodes[0]) {
- // If cube fits into a subnode ..
- if (index !== -1) {
- returnObjects = returnObjects.concat(this.nodes[index].retrieve(source));
- } else {
- // If cube does not fit into a subnode, check it against all subnodes (unrolled for speed)
- returnObjects = returnObjects.concat(this.nodes[0].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[1].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[2].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[3].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[4].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[5].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[6].retrieve(source));
- returnObjects = returnObjects.concat(this.nodes[7].retrieve(source));
- }
- }
-
- return returnObjects;
-
- },
-
- /**
- * Clear the octree.
- * @method Phaser.Plugin.Isometric.Octree#clear
- */
- clear: function () {
-
- this.objects.length = 0;
-
- var i = this.nodes.length;
-
- while (i--) {
- this.nodes[i].clear();
- this.nodes.splice(i, 1);
- }
-
- this.nodes.length = 0;
- }
-
-};
-
-Phaser.Plugin.Isometric.Octree.prototype.constructor = Phaser.Plugin.Isometric.Octree;
-
-/**
- * Visually renders an Octree to the display.
- *
- * @method Phaser.Utils.Debug#octree
- * @param {Phaser.Plugin.Isometric.Octree} octree - The octree to render.
- * @param {string} color - The color of the lines in the quadtree.
- */
-Phaser.Utils.Debug.prototype.octree = function (octree, color) {
-
- color = color || 'rgba(255,0,0,0.3)';
-
- this.start();
-
- var bounds = octree.bounds,
- i, points;
-
- if (octree.nodes.length === 0) {
-
- this.context.strokeStyle = color;
-
- var cube = new Phaser.Plugin.Isometric.Cube(bounds.x, bounds.y, bounds.z, bounds.widthX, bounds.widthY, bounds.height);
- var corners = cube.getCorners();
-
- points = corners.slice(0, corners.length);
- points = points.map(function (p) {
- return this.game.iso.project(p);
- });
-
- this.context.moveTo(points[0].x, points[0].y);
- this.context.beginPath();
- this.context.strokeStyle = color;
-
- this.context.lineTo(points[1].x, points[1].y);
- this.context.lineTo(points[3].x, points[3].y);
- this.context.lineTo(points[2].x, points[2].y);
- this.context.lineTo(points[6].x, points[6].y);
- this.context.lineTo(points[4].x, points[4].y);
- this.context.lineTo(points[5].x, points[5].y);
- this.context.lineTo(points[1].x, points[1].y);
- this.context.lineTo(points[0].x, points[0].y);
- this.context.lineTo(points[4].x, points[4].y);
- this.context.moveTo(points[0].x, points[0].y);
- this.context.lineTo(points[2].x, points[2].y);
- this.context.moveTo(points[3].x, points[3].y);
- this.context.lineTo(points[7].x, points[7].y);
- this.context.lineTo(points[6].x, points[6].y);
- this.context.moveTo(points[7].x, points[7].y);
- this.context.lineTo(points[5].x, points[5].y);
- this.context.stroke();
- this.context.closePath();
-
- for (i = 0; i < octree.objects.length; i++) {
- this.body(octree.objects[i].sprite, 'rgb(0,255,0)', false);
- }
- } else {
- for (i = 0; i < octree.nodes.length; i++) {
- this.octree(octree.nodes[i]);
- }
- }
-
- this.stop();
-
-};
-
Phaser.Utils.Debug.prototype.body = (function (_super) {
return function (sprite, color, filled) {