@@ -220,13 +220,74 @@ Phaser.Physics.Ninja.prototype = {
220220 } ,
221221
222222 /**
223- * Called automatically by a Physics body, it updates all motion related values on the Body .
223+ * Clears all physics bodies from the given TilemapLayer that were created with `World.convertTilemap` .
224224 *
225- * @method Phaser.Physics.Ninja#updateMotion
226- * @param {Phaser.Physics.Ninja.Body } The Body object to be updated.
227- update: function () {
225+ * @method Phaser.Physics.Ninja#clearTilemapLayerBodies
226+ * @param {Phaser.Tilemap } map - The Tilemap to get the map data from.
227+ * @param {number|string|Phaser.TilemapLayer } [layer] - The layer to operate on. If not given will default to map.currentLayer.
228+ */
229+ clearTilemapLayerBodies : function ( map , layer ) {
230+
231+ layer = map . getLayer ( layer ) ;
232+
233+ var i = map . layers [ layer ] . bodies . length ;
234+
235+ while ( i -- )
236+ {
237+ map . layers [ layer ] . bodies [ i ] . destroy ( ) ;
238+ }
239+
240+ map . layers [ layer ] . bodies . length = [ ] ;
241+
228242 } ,
243+
244+ /**
245+ * Goes through all tiles in the given Tilemap and TilemapLayer and converts those set to collide into physics tiles.
246+ * Only call this *after* you have specified all of the tiles you wish to collide with calls like Tilemap.setCollisionBetween, etc.
247+ * Every time you call this method it will destroy any previously created bodies and remove them from the world.
248+ * Therefore understand it's a very expensive operation and not to be done in a core game update loop.
249+ *
250+ * In Ninja the Tiles have an ID from 0 to 33, where 0 is 'empty', 1 is a full tile, 2 is a 45-degree slope, etc. You can find the ID
251+ * list either at the very bottom of `Tile.js`, or in a handy visual reference in the `resources/Ninja Physics Debug Tiles` folder in the repository.
252+ * The slopeMap parameter is an array that controls how the indexes of the tiles in your tilemap data will map to the Ninja Tile IDs.
253+ * For example if you had 6 tiles in your tileset: Imagine the first 4 should be converted into fully solid Tiles and the other 2 are 45-degree slopes.
254+ * Your slopeMap array would look like this: `[ 1, 1, 1, 1, 2, 3 ]`.
255+ * Where each element of the array is a tile in your tilemap and the resulting Ninja Tile it should create.
256+ *
257+ * @method Phaser.Physics.Ninja#convertTilemap
258+ * @param {Phaser.Tilemap } map - The Tilemap to get the map data from.
259+ * @param {number|string|Phaser.TilemapLayer } [layer] - The layer to operate on. If not given will default to map.currentLayer.
260+ * @param {object } [slopeMap] - The tilemap index to Tile ID map.
261+ * @return {array } An array of the Phaser.Physics.Ninja.Tile objects that were created.
229262 */
263+ convertTilemap : function ( map , layer , slopeMap ) {
264+
265+ layer = map . getLayer ( layer ) ;
266+
267+ if ( typeof addToWorld === 'undefined' ) { addToWorld = true ; }
268+ if ( typeof optimize === 'undefined' ) { optimize = true ; }
269+
270+ // If the bodies array is already populated we need to nuke it
271+ this . clearTilemapLayerBodies ( map , layer ) ;
272+
273+ for ( var y = 0 , h = map . layers [ layer ] . height ; y < h ; y ++ )
274+ {
275+ for ( var x = 0 , w = map . layers [ layer ] . width ; x < w ; x ++ )
276+ {
277+ var tile = map . layers [ layer ] . data [ y ] [ x ] ;
278+
279+ if ( tile && slopeMap . hasOwnProperty ( tile . index ) )
280+ {
281+ var body = new Phaser . Physics . Ninja . Body ( this , null , 3 , slopeMap [ tile . index ] , 0 , tile . worldX + tile . centerX , tile . worldY + tile . centerY , tile . width , tile . height ) ;
282+
283+ map . layers [ layer ] . bodies . push ( body ) ;
284+ }
285+ }
286+ }
287+
288+ return map . layers [ layer ] . bodies ;
289+
290+ } ,
230291
231292 /**
232293 * Checks for overlaps between two game objects. The objects can be Sprites, Groups or Emitters.
@@ -567,8 +628,14 @@ Phaser.Physics.Ninja.prototype = {
567628* @param {number } [type=1] - The type of Ninja shape to create. 1 = AABB, 2 = Circle or 3 = Tile.
568629* @param {number } [id=1] - If this body is using a Tile shape, you can set the Tile id here, i.e. Phaser.Physics.Ninja.Tile.SLOPE_45DEGpn, Phaser.Physics.Ninja.Tile.CONVEXpp, etc.
569630* @param {number } [radius=16] - If this body is using a Circle shape this controls the radius.
631+ * @param {number } [x=0] - The x coordinate of this Body. This is only used if a sprite is not provided.
632+ * @param {number } [y=0] - The y coordinate of this Body. This is only used if a sprite is not provided.
633+ * @param {number } [width=0] - The width of this Body. This is only used if a sprite is not provided.
634+ * @param {number } [height=0] - The height of this Body. This is only used if a sprite is not provided.
570635*/
571- Phaser . Physics . Ninja . Body = function ( system , sprite , type , id , radius ) {
636+ Phaser . Physics . Ninja . Body = function ( system , sprite , type , id , radius , x , y , width , height ) {
637+
638+ sprite = sprite || null ;
572639
573640 if ( typeof type === 'undefined' ) { type = 1 ; }
574641 if ( typeof id === 'undefined' ) { id = 1 ; }
@@ -582,7 +649,7 @@ Phaser.Physics.Ninja.Body = function (system, sprite, type, id, radius) {
582649 /**
583650 * @property {Phaser.Game } game - Local reference to game.
584651 */
585- this . game = sprite . game ;
652+ this . game = system . game ;
586653
587654 /**
588655 * @property {number } type - The type of physics system this body belongs to.
@@ -663,6 +730,13 @@ Phaser.Physics.Ninja.Body = function (system, sprite, type, id, radius) {
663730 */
664731 this . collideWorldBounds = true ;
665732
733+ /**
734+ * Set the checkCollision properties to control which directions collision is processed for this Body.
735+ * For example checkCollision.up = false means it won't collide when the collision happened while moving up.
736+ * @property {object } checkCollision - An object containing allowed collision.
737+ */
738+ this . checkCollision = { none : false , any : true , up : true , down : true , left : true , right : true } ;
739+
666740 /**
667741 * This object is populated with boolean values when the Body collides with another.
668742 * touching.up = true means the collision happened to the top of this Body for example.
@@ -682,32 +756,37 @@ Phaser.Physics.Ninja.Body = function (system, sprite, type, id, radius) {
682756 */
683757 this . maxSpeed = 8 ;
684758
685- var sx = sprite . x ;
686- var sy = sprite . y ;
687-
688- if ( sprite . anchor . x === 0 )
759+ if ( sprite )
689760 {
690- sx += ( sprite . width * 0.5 ) ;
691- }
761+ x = sprite . x ;
762+ y = sprite . y ;
763+ width = sprite . width ;
764+ height = sprite . height ;
692765
693- if ( sprite . anchor . y === 0 )
694- {
695- sy += ( sprite . height * 0.5 ) ;
766+ if ( sprite . anchor . x === 0 )
767+ {
768+ x += ( sprite . width * 0.5 ) ;
769+ }
770+
771+ if ( sprite . anchor . y === 0 )
772+ {
773+ y += ( sprite . height * 0.5 ) ;
774+ }
696775 }
697776
698777 if ( type === 1 )
699778 {
700- this . aabb = new Phaser . Physics . Ninja . AABB ( this , sx , sy , sprite . width , sprite . height ) ;
779+ this . aabb = new Phaser . Physics . Ninja . AABB ( this , x , y , width , height ) ;
701780 this . shape = this . aabb ;
702781 }
703782 else if ( type === 2 )
704783 {
705- this . circle = new Phaser . Physics . Ninja . Circle ( this , sx , sy , radius ) ;
784+ this . circle = new Phaser . Physics . Ninja . Circle ( this , x , y , radius ) ;
706785 this . shape = this . circle ;
707786 }
708787 else if ( type === 3 )
709788 {
710- this . tile = new Phaser . Physics . Ninja . Tile ( this , sx , sy , sprite . width , sprite . height , id ) ;
789+ this . tile = new Phaser . Physics . Ninja . Tile ( this , x , y , width , height , id ) ;
711790 this . shape = this . tile ;
712791 }
713792
@@ -753,16 +832,19 @@ Phaser.Physics.Ninja.Body.prototype = {
753832 */
754833 postUpdate : function ( ) {
755834
756- if ( this . sprite . type === Phaser . TILESPRITE )
835+ if ( this . sprite )
757836 {
758- // TileSprites don't use their anchor property, so we need to adjust the coordinates
759- this . sprite . x = this . shape . pos . x - this . shape . xw ;
760- this . sprite . y = this . shape . pos . y - this . shape . yw ;
761- }
762- else
763- {
764- this . sprite . x = this . shape . pos . x ;
765- this . sprite . y = this . shape . pos . y ;
837+ if ( this . sprite . type === Phaser . TILESPRITE )
838+ {
839+ // TileSprites don't use their anchor property, so we need to adjust the coordinates
840+ this . sprite . x = this . shape . pos . x - this . shape . xw ;
841+ this . sprite . y = this . shape . pos . y - this . shape . yw ;
842+ }
843+ else
844+ {
845+ this . sprite . x = this . shape . pos . x ;
846+ this . sprite . y = this . shape . pos . y ;
847+ }
766848 }
767849
768850 if ( this . velocity . x < 0 )
@@ -907,6 +989,46 @@ Phaser.Physics.Ninja.Body.prototype = {
907989
908990 this . shape . oldpos . copyFrom ( this . shape . pos ) ;
909991
992+ } ,
993+
994+ /**
995+ * Returns the absolute delta x value.
996+ *
997+ * @method Phaser.Physics.Ninja.Body#deltaAbsX
998+ * @return {number } The absolute delta value.
999+ */
1000+ deltaAbsX : function ( ) {
1001+ return ( this . deltaX ( ) > 0 ? this . deltaX ( ) : - this . deltaX ( ) ) ;
1002+ } ,
1003+
1004+ /**
1005+ * Returns the absolute delta y value.
1006+ *
1007+ * @method Phaser.Physics.Ninja.Body#deltaAbsY
1008+ * @return {number } The absolute delta value.
1009+ */
1010+ deltaAbsY : function ( ) {
1011+ return ( this . deltaY ( ) > 0 ? this . deltaY ( ) : - this . deltaY ( ) ) ;
1012+ } ,
1013+
1014+ /**
1015+ * Returns the delta x value. The difference between Body.x now and in the previous step.
1016+ *
1017+ * @method Phaser.Physics.Ninja.Body#deltaX
1018+ * @return {number } The delta value. Positive if the motion was to the right, negative if to the left.
1019+ */
1020+ deltaX : function ( ) {
1021+ return this . shape . pos . x - this . shape . oldpos . x ;
1022+ } ,
1023+
1024+ /**
1025+ * Returns the delta y value. The difference between Body.y now and in the previous step.
1026+ *
1027+ * @method Phaser.Physics.Ninja.Body#deltaY
1028+ * @return {number } The delta value. Positive if the motion was downwards, negative if upwards.
1029+ */
1030+ deltaY : function ( ) {
1031+ return this . shape . pos . y - this . shape . oldpos . y ;
9101032 }
9111033
9121034} ;
@@ -977,7 +1099,7 @@ Object.defineProperty(Phaser.Physics.Ninja.Body.prototype, "height", {
9771099Object . defineProperty ( Phaser . Physics . Ninja . Body . prototype , "bottom" , {
9781100
9791101 get : function ( ) {
980- return this . shape . pos . y + this . shape . height ;
1102+ return this . shape . pos . y + this . shape . yw ;
9811103 }
9821104
9831105} ) ;
@@ -990,7 +1112,7 @@ Object.defineProperty(Phaser.Physics.Ninja.Body.prototype, "bottom", {
9901112Object . defineProperty ( Phaser . Physics . Ninja . Body . prototype , "right" , {
9911113
9921114 get : function ( ) {
993- return this . shape . pos . x + this . shape . width ;
1115+ return this . shape . pos . x + this . shape . xw ;
9941116 }
9951117
9961118} ) ;
@@ -2332,6 +2454,18 @@ Phaser.Physics.Ninja.Tile.prototype = {
23322454
23332455 } ,
23342456
2457+ /**
2458+ * Destroys this Tiles reference to Body and System.
2459+ *
2460+ * @method Phaser.Physics.Ninja.Tile#destroy
2461+ */
2462+ destroy : function ( ) {
2463+
2464+ this . body = null ;
2465+ this . system = null ;
2466+
2467+ } ,
2468+
23352469 /**
23362470 * This converts a tile from implicitly-defined (via id), to explicit (via properties).
23372471 * Don't call directly, instead of setType.
@@ -2868,6 +3002,18 @@ Phaser.Physics.Ninja.Circle = function (body, x, y, radius) {
28683002 */
28693003 this . radius = radius ;
28703004
3005+ /**
3006+ * @property {number } xw - Half the width.
3007+ * @readonly
3008+ */
3009+ this . xw = radius ;
3010+
3011+ /**
3012+ * @property {number } xw - Half the height.
3013+ * @readonly
3014+ */
3015+ this . yw = radius ;
3016+
28713017 /**
28723018 * @property {number } width - The width.
28733019 * @readonly
@@ -3024,31 +3170,31 @@ Phaser.Physics.Ninja.Circle.prototype = {
30243170 */
30253171 collideWorldBounds : function ( ) {
30263172
3027- var dx = this . system . bounds . x - ( this . pos . x - this . xw ) ;
3173+ var dx = this . system . bounds . x - ( this . pos . x - this . radius ) ;
30283174
30293175 if ( 0 < dx )
30303176 {
30313177 this . reportCollisionVsWorld ( dx , 0 , 1 , 0 , null ) ;
30323178 }
30333179 else
30343180 {
3035- dx = ( this . pos . x + this . xw ) - this . system . bounds . width ;
3181+ dx = ( this . pos . x + this . radius ) - this . system . bounds . width ;
30363182
30373183 if ( 0 < dx )
30383184 {
30393185 this . reportCollisionVsWorld ( - dx , 0 , - 1 , 0 , null ) ;
30403186 }
30413187 }
30423188
3043- var dy = this . system . bounds . y - ( this . pos . y - this . yw ) ;
3189+ var dy = this . system . bounds . y - ( this . pos . y - this . radius ) ;
30443190
30453191 if ( 0 < dy )
30463192 {
30473193 this . reportCollisionVsWorld ( 0 , dy , 0 , 1 , null ) ;
30483194 }
30493195 else
30503196 {
3051- dy = ( this . pos . y + this . yw ) - this . system . bounds . height ;
3197+ dy = ( this . pos . y + this . radius ) - this . system . bounds . height ;
30523198
30533199 if ( 0 < dy )
30543200 {
0 commit comments