From e3699aaea0a33e0e3b81801b54174f0d50e1d3e7 Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Wed, 10 Jan 2018 19:34:22 -0600 Subject: [PATCH 01/12] Remove unnecessary Arcade Body#tilePadding --- src/physics/arcade/Body.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index aa7c1ce59..abec94ca1 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -131,8 +131,6 @@ var Body = new Class({ this.blocked = { none: true, up: false, down: false, left: false, right: false }; - this.tilePadding = new Vector2(); - this.dirty = false; this.syncBounds = false; From 32788d6eb6dda43d5946b21434e30ec0a0c1b1b2 Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Wed, 10 Jan 2018 20:43:11 -0600 Subject: [PATCH 02/12] Stub arcade collide vs tilemap methods --- src/physics/arcade/World.js | 2 ++ src/physics/arcade/inc/CollideGroupVsTilemapLayer.js | 8 ++++++++ src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 src/physics/arcade/inc/CollideGroupVsTilemapLayer.js create mode 100644 src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js diff --git a/src/physics/arcade/World.js b/src/physics/arcade/World.js index f619ef2d2..3cee14984 100644 --- a/src/physics/arcade/World.js +++ b/src/physics/arcade/World.js @@ -387,6 +387,8 @@ var World = new Class({ collideHandler: require('./inc/CollideHandler'), collideSpriteVsSprite: require('./inc/CollideSpriteVsSprite'), collideSpriteVsGroup: require('./inc/CollideSpriteVsGroup'), + collideGroupVsTilemapLayer: require('./inc/CollideGroupVsTilemapLayer'), + collideSpriteVsTilemapLayer: require('./inc/CollideSpriteVsTilemapLayer'), // Utils accelerateTo: require('./utils/AccelerateTo'), diff --git a/src/physics/arcade/inc/CollideGroupVsTilemapLayer.js b/src/physics/arcade/inc/CollideGroupVsTilemapLayer.js new file mode 100644 index 000000000..315ad61f6 --- /dev/null +++ b/src/physics/arcade/inc/CollideGroupVsTilemapLayer.js @@ -0,0 +1,8 @@ +var CollideGroupVsTilemapLayer = function (group, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) +{ + // TODO + + return false; +}; + +module.exports = CollideGroupVsTilemapLayer; diff --git a/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js new file mode 100644 index 000000000..75368a8a2 --- /dev/null +++ b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js @@ -0,0 +1,5 @@ +var CollideSpriteVsTilemapLayer = function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) +{ +}; + +module.exports = CollideSpriteVsTilemapLayer; From fdc1af0cd2c6a281c3a569c86cddf469c9f5b5a5 Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Wed, 10 Jan 2018 20:45:28 -0600 Subject: [PATCH 03/12] Install isTilemap prop used by physics system for fast type checking --- .../tilemap/dynamiclayer/DynamicTilemapLayer.js | 7 +++++++ src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js b/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js index 4cdcec323..c3e2dea47 100644 --- a/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js +++ b/src/gameobjects/tilemap/dynamiclayer/DynamicTilemapLayer.js @@ -49,6 +49,13 @@ var DynamicTilemapLayer = new Class({ { GameObject.call(this, scene, 'DynamicTilemapLayer'); + /** + * Used internally by physics system to perform fast type checks. + * @property {boolean} isTilemap + * @readonly + */ + this.isTilemap = true; + /** * The Tilemap that this layer is a part of. * @property {Tilemap} map diff --git a/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js b/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js index 78bd26db4..917c103fd 100644 --- a/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js +++ b/src/gameobjects/tilemap/staticlayer/StaticTilemapLayer.js @@ -49,6 +49,13 @@ var StaticTilemapLayer = new Class({ { GameObject.call(this, scene, 'StaticTilemapLayer'); + /** + * Used internally by physics system to perform fast type checks. + * @property {boolean} isTilemap + * @readonly + */ + this.isTilemap = true; + /** * The Tilemap that this layer is a part of. * @property {Tilemap} map From 98ae8009e09b293e35cfc145bfd129f2da739d3f Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Wed, 10 Jan 2018 20:47:25 -0600 Subject: [PATCH 04/12] Arcade rect vs tilemap layer collision handling --- .../arcade/inc/CollideSpriteVsTilemapLayer.js | 43 +++++++++ .../inc/tilemap/ProcessTileCallbacks.js | 20 ++++ .../inc/tilemap/ProcessTileSeparationX.js | 32 +++++++ .../inc/tilemap/ProcessTileSeparationY.js | 32 +++++++ .../arcade/inc/tilemap/SeparateTile.js | 94 +++++++++++++++++++ src/physics/arcade/inc/tilemap/TileCheckX.js | 63 +++++++++++++ src/physics/arcade/inc/tilemap/TileCheckY.js | 63 +++++++++++++ .../arcade/inc/tilemap/TileIntersectsBody.js | 18 ++++ 8 files changed, 365 insertions(+) create mode 100644 src/physics/arcade/inc/tilemap/ProcessTileCallbacks.js create mode 100644 src/physics/arcade/inc/tilemap/ProcessTileSeparationX.js create mode 100644 src/physics/arcade/inc/tilemap/ProcessTileSeparationY.js create mode 100644 src/physics/arcade/inc/tilemap/SeparateTile.js create mode 100644 src/physics/arcade/inc/tilemap/TileCheckX.js create mode 100644 src/physics/arcade/inc/tilemap/TileCheckY.js create mode 100644 src/physics/arcade/inc/tilemap/TileIntersectsBody.js diff --git a/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js index 75368a8a2..6ed2c800a 100644 --- a/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js +++ b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js @@ -1,5 +1,48 @@ +var SeparateTile = require('./tilemap/SeparateTile'); +var TileIntersectsBody = require('./tilemap/TileIntersectsBody'); +var ProcessTileCallbacks = require('./tilemap/ProcessTileCallbacks'); + var CollideSpriteVsTilemapLayer = function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) { + if (!sprite.body.enable) + { + return false; + } + + var mapData = tilemapLayer.getTilesWithinWorldXY( + sprite.body.position.x, sprite.body.position.y, + sprite.body.width, sprite.body.height + ); + + if (mapData.length === 0) + { + return false; + } + + var tile; + var tileWorldRect = { left: 0, right: 0, top: 0, bottom: 0 }; + + for (var i = 0; i < mapData.length; i++) + { + tile = mapData[i]; + tileWorldRect.left = tilemapLayer.tileToWorldX(tile.x); + tileWorldRect.top = tilemapLayer.tileToWorldY(tile.y); + tileWorldRect.right = tileWorldRect.left + tile.width * tilemapLayer.scaleX; + tileWorldRect.bottom = tileWorldRect.top + tile.height * tilemapLayer.scaleY; + + if (TileIntersectsBody(tileWorldRect, sprite.body) + && (!processCallback || processCallback.call(callbackContext, sprite, tile)) + && ProcessTileCallbacks(tile) + && (overlapOnly || SeparateTile(i, sprite.body, tile, tileWorldRect, tilemapLayer))) + { + this._total++; + + if (collideCallback) + { + collideCallback.call(callbackContext, sprite, tile); + } + } + } }; module.exports = CollideSpriteVsTilemapLayer; diff --git a/src/physics/arcade/inc/tilemap/ProcessTileCallbacks.js b/src/physics/arcade/inc/tilemap/ProcessTileCallbacks.js new file mode 100644 index 000000000..7bd983bfa --- /dev/null +++ b/src/physics/arcade/inc/tilemap/ProcessTileCallbacks.js @@ -0,0 +1,20 @@ +var ProcessTileCallbacks = function (tile) +{ + return true; + + // TODO: port v2 + // // Tilemap & tile callbacks take priority + // // A local callback always takes priority over a layer level callback + // if (tile.collisionCallback && !tile.collisionCallback.call(tile.collisionCallbackContext, body.sprite, tile)) + // { + // // If it returns true then we can carry on, otherwise we should abort. + // return false; + // } + // else if (typeof tile.layer.callbacks !== 'undefined' && tile.layer.callbacks[tile.index] && !tile.layer.callbacks[tile.index].callback.call(tile.layer.callbacks[tile.index].callbackContext, body.sprite, tile)) + // { + // // If it returns true then we can carry on, otherwise we should abort. + // return false; + // } +}; + +module.exports = ProcessTileCallbacks; diff --git a/src/physics/arcade/inc/tilemap/ProcessTileSeparationX.js b/src/physics/arcade/inc/tilemap/ProcessTileSeparationX.js new file mode 100644 index 000000000..b7fc4a6c9 --- /dev/null +++ b/src/physics/arcade/inc/tilemap/ProcessTileSeparationX.js @@ -0,0 +1,32 @@ +/** +* Internal function to process the separation of a physics body from a tile. +* +* @private +* @method Phaser.Physics.Arcade#processTileSeparationX +* @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. +* @param {number} x - The x separation amount. +*/ +var ProcessTileSeparationX = function (body, x) +{ + if (x < 0) + { + body.blocked.left = true; + } + else if (x > 0) + { + body.blocked.right = true; + } + + body.position.x -= x; + + if (body.bounce.x === 0) + { + body.velocity.x = 0; + } + else + { + body.velocity.x = -body.velocity.x * body.bounce.x; + } +}; + +module.exports = ProcessTileSeparationX; diff --git a/src/physics/arcade/inc/tilemap/ProcessTileSeparationY.js b/src/physics/arcade/inc/tilemap/ProcessTileSeparationY.js new file mode 100644 index 000000000..05777c2b0 --- /dev/null +++ b/src/physics/arcade/inc/tilemap/ProcessTileSeparationY.js @@ -0,0 +1,32 @@ +/** +* Internal function to process the separation of a physics body from a tile. +* +* @private +* @method Phaser.Physics.Arcade#processTileSeparationY +* @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. +* @param {number} y - The y separation amount. +*/ +var ProcessTileSeparationY = function (body, y) +{ + if (y < 0) + { + body.blocked.up = true; + } + else if (y > 0) + { + body.blocked.down = true; + } + + body.position.y -= y; + + if (body.bounce.y === 0) + { + body.velocity.y = 0; + } + else + { + body.velocity.y = -body.velocity.y * body.bounce.y; + } +}; + +module.exports = ProcessTileSeparationY; diff --git a/src/physics/arcade/inc/tilemap/SeparateTile.js b/src/physics/arcade/inc/tilemap/SeparateTile.js new file mode 100644 index 000000000..7c7c4799d --- /dev/null +++ b/src/physics/arcade/inc/tilemap/SeparateTile.js @@ -0,0 +1,94 @@ +var TileCheckX = require('./TileCheckX'); +var TileCheckY = require('./TileCheckY'); +var TileIntersectsBody = require('./TileIntersectsBody'); + +/** + * The core separation function to separate a physics body and a tile. + * + * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. + * @param {Phaser.Tile} tile - The tile to collide against. + * @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against. + * @return {boolean} Returns true if the body was separated, otherwise false. + */ +var SeparateTile = function (i, body, tile, tileWorldRect, tilemapLayer) +{ + var tileLeft = tileWorldRect.left; + var tileTop = tileWorldRect.top; + var tileRight = tileWorldRect.right; + var tileBottom = tileWorldRect.bottom; + var faceHorizontal = tile.faceLeft || tile.faceRight; + var faceVertical = tile.faceTop || tile.faceBottom; + + // We don't need to go any further if this tile doesn't actually have any colliding faces. This + // could happen if the tile was meant to be collided with re: a callback, but otherwise isn't + // needed for separation. + if (!faceHorizontal && !faceVertical) + { + return false; + } + + var ox = 0; + var oy = 0; + var minX = 0; + var minY = 1; + + if (body.deltaAbsX() > body.deltaAbsY()) + { + // Moving faster horizontally, check X axis first + minX = -1; + } + else if (body.deltaAbsX() < body.deltaAbsY()) + { + // Moving faster vertically, check Y axis first + minY = -1; + } + + if (body.deltaX() !== 0 && body.deltaY() !== 0 && faceHorizontal && faceVertical) + { + // We only need do this if both axes have colliding faces AND we're moving in both + // directions + minX = Math.min(Math.abs(body.position.x - tileRight), Math.abs(body.right - tileLeft)); + minY = Math.min(Math.abs(body.position.y - tileBottom), Math.abs(body.bottom - tileTop)); + } + + if (minX < minY) + { + if (faceHorizontal) + { + ox = TileCheckX(body, tile, tilemapLayer); + + // That's horizontal done, check if we still intersects? If not then we can return now + if (ox !== 0 && !TileIntersectsBody(tileWorldRect, body)) + { + return true; + } + } + + if (faceVertical) + { + oy = TileCheckY(body, tile, tilemapLayer); + } + } + else + { + if (faceVertical) + { + oy = TileCheckY(body, tile, tilemapLayer); + + // That's vertical done, check if we still intersects? If not then we can return now + if (oy !== 0 && !TileIntersectsBody(tileWorldRect, body)) + { + return true; + } + } + + if (faceHorizontal) + { + ox = TileCheckX(body, tile, tilemapLayer); + } + } + + return (ox !== 0 || oy !== 0); +}; + +module.exports = SeparateTile; diff --git a/src/physics/arcade/inc/tilemap/TileCheckX.js b/src/physics/arcade/inc/tilemap/TileCheckX.js new file mode 100644 index 000000000..6ab65c52a --- /dev/null +++ b/src/physics/arcade/inc/tilemap/TileCheckX.js @@ -0,0 +1,63 @@ +var TILE_BIAS = 16; +var ProcessTileSeparationX = require('./ProcessTileSeparationX'); + +/** +* Check the body against the given tile on the X axis. +* +* @private +* @method Phaser.Physics.Arcade#tileCheckX +* @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. +* @param {Phaser.Tile} tile - The tile to check. +* @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against. +* @return {number} The amount of separation that occurred. +*/ +var TileCheckX = function (body, tile, tilemapLayer) +{ + var ox = 0; + var tileLeft = tilemapLayer.tileToWorldX(tile.x); + var tileWidth = tile.width * tilemapLayer.scaleX; + var tileRight = tileLeft + tileWidth; + + if (body.deltaX() < 0 && !body.blocked.left && tile.collideRight && body.checkCollision.left) + { + // Body is moving LEFT + if (tile.faceRight && body.x < tileRight) + { + ox = body.x - tileRight; + + if (ox < -TILE_BIAS) + { + ox = 0; + } + } + } + else if (body.deltaX() > 0 && !body.blocked.right && tile.collideLeft && body.checkCollision.right) + { + // Body is moving RIGHT + if (tile.faceLeft && body.right > tileLeft) + { + ox = body.right - tileLeft; + + if (ox > TILE_BIAS) + { + ox = 0; + } + } + } + + if (ox !== 0) + { + if (body.customSeparateX) + { + body.overlapX = ox; + } + else + { + ProcessTileSeparationX(body, ox); + } + } + + return ox; +}; + +module.exports = TileCheckX; diff --git a/src/physics/arcade/inc/tilemap/TileCheckY.js b/src/physics/arcade/inc/tilemap/TileCheckY.js new file mode 100644 index 000000000..a431ff086 --- /dev/null +++ b/src/physics/arcade/inc/tilemap/TileCheckY.js @@ -0,0 +1,63 @@ +var TILE_BIAS = 16; +var ProcessTileSeparationY = require('./ProcessTileSeparationY'); + +/** +* Check the body against the given tile on the Y axis. +* +* @private +* @method Phaser.Physics.Arcade#tileCheckY +* @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. +* @param {Phaser.Tile} tile - The tile to check. +* @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against. +* @return {number} The amount of separation that occurred. +*/ +var TileCheckY = function (body, tile, tilemapLayer) +{ + var oy = 0; + var tileTop = tilemapLayer.tileToWorldX(tile.y); + var tileHeight = tile.height * tilemapLayer.scaleY; + var tileBottom = tileTop + tileHeight; + + if (body.deltaY() < 0 && !body.blocked.up && tile.collideDown && body.checkCollision.up) + { + // Body is moving UP + if (tile.faceBottom && body.y < tileBottom) + { + oy = body.y - tileBottom; + + if (oy < -TILE_BIAS) + { + oy = 0; + } + } + } + else if (body.deltaY() > 0 && !body.blocked.down && tile.collideUp && body.checkCollision.down) + { + // Body is moving DOWN + if (tile.faceTop && body.bottom > tileTop) + { + oy = body.bottom - tileTop; + + if (oy > TILE_BIAS) + { + oy = 0; + } + } + } + + if (oy !== 0) + { + if (body.customSeparateY) + { + body.overlapY = oy; + } + else + { + ProcessTileSeparationY(body, oy); + } + } + + return oy; +}; + +module.exports = TileCheckY; diff --git a/src/physics/arcade/inc/tilemap/TileIntersectsBody.js b/src/physics/arcade/inc/tilemap/TileIntersectsBody.js new file mode 100644 index 000000000..9c3cdda7c --- /dev/null +++ b/src/physics/arcade/inc/tilemap/TileIntersectsBody.js @@ -0,0 +1,18 @@ +var TileIntersectsBody = function (tileWorldRect, body) +{ + if (body.isCircle) + { + return false; + } + else + { + return !( + body.right <= tileWorldRect.left || + body.bottom <= tileWorldRect.top || + body.position.x >= tileWorldRect.right || + body.position.y >= tileWorldRect.bottom + ); + } +}; + +module.exports = TileIntersectsBody; From 718859b02e7becb03e1205e1a06b5c517eda9c78 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Thu, 11 Jan 2018 13:59:06 +0000 Subject: [PATCH 05/12] Moved the depth sorting functions into the DisplayList class, as it's really the one responsible for it, not System. --- src/actions/GridAlign.js | 3 ++- src/gameobjects/GameObject.js | 4 +-- src/gameobjects/components/Depth.js | 2 +- src/gameobjects/components/Transform.js | 2 +- src/scene/local/Systems.js | 26 ++++-------------- src/scene/plugins/DisplayList.js | 35 +++++++++++++++++++++++++ 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/actions/GridAlign.js b/src/actions/GridAlign.js index 7412027e9..041c62897 100644 --- a/src/actions/GridAlign.js +++ b/src/actions/GridAlign.js @@ -1,9 +1,10 @@ var AlignIn = require('../display/align/in/QuickSet'); var CONST = require('../display/align/const'); var GetValue = require('../utils/object/GetValue'); +var NOOP = require('../utils/NOOP'); var Zone = require('../gameobjects/zone/Zone'); -var tempZone = new Zone({ sys: { sortChildrenFlag: false }}, 0, 0, 1, 1); +var tempZone = new Zone({ sys: { queueDepthSort: NOOP }}, 0, 0, 1, 1); /** * [description] diff --git a/src/gameobjects/GameObject.js b/src/gameobjects/GameObject.js index faeddef62..53ce79e76 100644 --- a/src/gameobjects/GameObject.js +++ b/src/gameobjects/GameObject.js @@ -121,7 +121,7 @@ var GameObject = new Class({ this.body = null; // Tell the Scene to re-sort the children - this.scene.sys.sortChildrenFlag = true; + this.scene.sys.queueDepthSort(); }, /** @@ -294,7 +294,7 @@ var GameObject = new Class({ } // Tell the Scene to re-sort the children - this.scene.sys.sortChildrenFlag = true; + this.scene.sys.queueDepthSort(); this.active = false; this.visible = false; diff --git a/src/gameobjects/components/Depth.js b/src/gameobjects/components/Depth.js index 358332ba4..ec96ba5af 100644 --- a/src/gameobjects/components/Depth.js +++ b/src/gameobjects/components/Depth.js @@ -14,7 +14,7 @@ var Depth = { set: function (value) { - this.scene.sys.sortChildrenFlag = true; + this.scene.sys.queueDepthSort(); this._depth = value; } diff --git a/src/gameobjects/components/Transform.js b/src/gameobjects/components/Transform.js index 8013e68a5..9b8216a6a 100644 --- a/src/gameobjects/components/Transform.js +++ b/src/gameobjects/components/Transform.js @@ -180,7 +180,7 @@ var Transform = { set: function (value) { - this.scene.sys.sortChildrenFlag = true; + this.scene.sys.queueDepthSort(); this._depth = value; } diff --git a/src/scene/local/Systems.js b/src/scene/local/Systems.js index d40596bf7..a34b1c57a 100644 --- a/src/scene/local/Systems.js +++ b/src/scene/local/Systems.js @@ -29,8 +29,6 @@ var Systems = new Class({ this.config = config; this.settings = Settings.create(config); - this.sortChildrenFlag = false; - // Set by the GlobalSceneManager this.canvas; this.context; @@ -157,37 +155,23 @@ var Systems = new Class({ return; } - // inlined to avoid branching - if (this.sortChildrenFlag) - { - StableSort.inplace(this.displayList.list, this.sortZ); + var displayList = this.displayList; - this.sortChildrenFlag = false; - } + displayList.process(); - this.cameras.render(renderer, this.displayList, interpolation); + this.cameras.render(renderer, displayList, interpolation); }, // Force a sort of the display list on the next render queueDepthSort: function () { - this.sortChildrenFlag = true; + this.displayList.queueDepthSort(); }, // Immediately sorts the display list if the flag is set depthSort: function () { - if (this.sortChildrenFlag) - { - StableSort.inplace(this.displayList.list, this.sortZ); - - this.sortChildrenFlag = false; - } - }, - - sortZ: function (childA, childB) - { - return childA._depth - childB._depth; + this.displayList.depthSort(); }, // A paused Scene still renders, it just doesn't run ANY of its update handlers or systems diff --git a/src/scene/plugins/DisplayList.js b/src/scene/plugins/DisplayList.js index aa387cc23..b06264d13 100644 --- a/src/scene/plugins/DisplayList.js +++ b/src/scene/plugins/DisplayList.js @@ -1,4 +1,5 @@ var Class = require('../../utils/Class'); +var StableSort = require('../../utils/array/StableSort'); var DisplayList = new Class({ @@ -13,9 +14,43 @@ var DisplayList = new Class({ // The equivalent of the old `Sprite.children` array. this.list = []; + this.sortChildrenFlag = false; + this.position = 0; }, + process: function () + { + if (this.sortChildrenFlag) + { + StableSort.inplace(this.list, this.sortZ); + + this.sortChildrenFlag = false; + } + }, + + sortZ: function (childA, childB) + { + return childA._depth - childB._depth; + }, + + // Force a sort of the display list on the next call to process + queueDepthSort: function () + { + this.sortChildrenFlag = true; + }, + + // Immediately sorts the display list if the flag is set + depthSort: function () + { + if (this.sortChildrenFlag) + { + StableSort.inplace(this.list, this.sortZ); + + this.sortChildrenFlag = false; + } + }, + add: function (child) { // Is child already in this display list? From 5241798ab34ea0b1a8ae7ab7f65b280464f73e7b Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Thu, 11 Jan 2018 08:32:07 -0600 Subject: [PATCH 06/12] Pass TILE_BIAS from arcade world into tile colliding functions --- src/physics/arcade/World.js | 2 ++ .../arcade/inc/CollideSpriteVsTilemapLayer.js | 12 +++++++----- src/physics/arcade/inc/tilemap/SeparateTile.js | 10 +++++----- src/physics/arcade/inc/tilemap/TileCheckX.js | 7 +++---- src/physics/arcade/inc/tilemap/TileCheckY.js | 7 +++---- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/physics/arcade/World.js b/src/physics/arcade/World.js index 3cee14984..e6259718f 100644 --- a/src/physics/arcade/World.js +++ b/src/physics/arcade/World.js @@ -48,6 +48,8 @@ var World = new Class({ this.OVERLAP_BIAS = GetValue(config, 'overlapBias', 4); + this.TILE_BIAS = GetValue(config, 'tileBias', 16); + this.forceX = GetValue(config, 'forceX', false); this.isPaused = GetValue(config, 'isPaused', false); diff --git a/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js index 6ed2c800a..3d379c422 100644 --- a/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js +++ b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js @@ -4,14 +4,16 @@ var ProcessTileCallbacks = require('./tilemap/ProcessTileCallbacks'); var CollideSpriteVsTilemapLayer = function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) { - if (!sprite.body.enable) + var body = sprite.body; + + if (!body.enable) { return false; } var mapData = tilemapLayer.getTilesWithinWorldXY( - sprite.body.position.x, sprite.body.position.y, - sprite.body.width, sprite.body.height + body.position.x, body.position.y, + body.width, body.height ); if (mapData.length === 0) @@ -30,10 +32,10 @@ var CollideSpriteVsTilemapLayer = function (sprite, tilemapLayer, collideCallbac tileWorldRect.right = tileWorldRect.left + tile.width * tilemapLayer.scaleX; tileWorldRect.bottom = tileWorldRect.top + tile.height * tilemapLayer.scaleY; - if (TileIntersectsBody(tileWorldRect, sprite.body) + if (TileIntersectsBody(tileWorldRect, body) && (!processCallback || processCallback.call(callbackContext, sprite, tile)) && ProcessTileCallbacks(tile) - && (overlapOnly || SeparateTile(i, sprite.body, tile, tileWorldRect, tilemapLayer))) + && (overlapOnly || SeparateTile(i, body, tile, tileWorldRect, tilemapLayer, this.TILE_BIAS))) { this._total++; diff --git a/src/physics/arcade/inc/tilemap/SeparateTile.js b/src/physics/arcade/inc/tilemap/SeparateTile.js index 7c7c4799d..2ea374933 100644 --- a/src/physics/arcade/inc/tilemap/SeparateTile.js +++ b/src/physics/arcade/inc/tilemap/SeparateTile.js @@ -10,7 +10,7 @@ var TileIntersectsBody = require('./TileIntersectsBody'); * @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against. * @return {boolean} Returns true if the body was separated, otherwise false. */ -var SeparateTile = function (i, body, tile, tileWorldRect, tilemapLayer) +var SeparateTile = function (i, body, tile, tileWorldRect, tilemapLayer, tileBias) { var tileLeft = tileWorldRect.left; var tileTop = tileWorldRect.top; @@ -55,7 +55,7 @@ var SeparateTile = function (i, body, tile, tileWorldRect, tilemapLayer) { if (faceHorizontal) { - ox = TileCheckX(body, tile, tilemapLayer); + ox = TileCheckX(body, tile, tilemapLayer, tileBias); // That's horizontal done, check if we still intersects? If not then we can return now if (ox !== 0 && !TileIntersectsBody(tileWorldRect, body)) @@ -66,14 +66,14 @@ var SeparateTile = function (i, body, tile, tileWorldRect, tilemapLayer) if (faceVertical) { - oy = TileCheckY(body, tile, tilemapLayer); + oy = TileCheckY(body, tile, tilemapLayer, tileBias); } } else { if (faceVertical) { - oy = TileCheckY(body, tile, tilemapLayer); + oy = TileCheckY(body, tile, tilemapLayer, tileBias); // That's vertical done, check if we still intersects? If not then we can return now if (oy !== 0 && !TileIntersectsBody(tileWorldRect, body)) @@ -84,7 +84,7 @@ var SeparateTile = function (i, body, tile, tileWorldRect, tilemapLayer) if (faceHorizontal) { - ox = TileCheckX(body, tile, tilemapLayer); + ox = TileCheckX(body, tile, tilemapLayer, tileBias); } } diff --git a/src/physics/arcade/inc/tilemap/TileCheckX.js b/src/physics/arcade/inc/tilemap/TileCheckX.js index 6ab65c52a..92258db5e 100644 --- a/src/physics/arcade/inc/tilemap/TileCheckX.js +++ b/src/physics/arcade/inc/tilemap/TileCheckX.js @@ -1,4 +1,3 @@ -var TILE_BIAS = 16; var ProcessTileSeparationX = require('./ProcessTileSeparationX'); /** @@ -11,7 +10,7 @@ var ProcessTileSeparationX = require('./ProcessTileSeparationX'); * @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against. * @return {number} The amount of separation that occurred. */ -var TileCheckX = function (body, tile, tilemapLayer) +var TileCheckX = function (body, tile, tilemapLayer, tileBias) { var ox = 0; var tileLeft = tilemapLayer.tileToWorldX(tile.x); @@ -25,7 +24,7 @@ var TileCheckX = function (body, tile, tilemapLayer) { ox = body.x - tileRight; - if (ox < -TILE_BIAS) + if (ox < -tileBias) { ox = 0; } @@ -38,7 +37,7 @@ var TileCheckX = function (body, tile, tilemapLayer) { ox = body.right - tileLeft; - if (ox > TILE_BIAS) + if (ox > tileBias) { ox = 0; } diff --git a/src/physics/arcade/inc/tilemap/TileCheckY.js b/src/physics/arcade/inc/tilemap/TileCheckY.js index a431ff086..282a20aca 100644 --- a/src/physics/arcade/inc/tilemap/TileCheckY.js +++ b/src/physics/arcade/inc/tilemap/TileCheckY.js @@ -1,4 +1,3 @@ -var TILE_BIAS = 16; var ProcessTileSeparationY = require('./ProcessTileSeparationY'); /** @@ -11,7 +10,7 @@ var ProcessTileSeparationY = require('./ProcessTileSeparationY'); * @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against. * @return {number} The amount of separation that occurred. */ -var TileCheckY = function (body, tile, tilemapLayer) +var TileCheckY = function (body, tile, tilemapLayer, tileBias) { var oy = 0; var tileTop = tilemapLayer.tileToWorldX(tile.y); @@ -25,7 +24,7 @@ var TileCheckY = function (body, tile, tilemapLayer) { oy = body.y - tileBottom; - if (oy < -TILE_BIAS) + if (oy < -tileBias) { oy = 0; } @@ -38,7 +37,7 @@ var TileCheckY = function (body, tile, tilemapLayer) { oy = body.bottom - tileTop; - if (oy > TILE_BIAS) + if (oy > tileBias) { oy = 0; } From e601f4060a7b571e973e7880bc01289e22fe60c0 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Thu, 11 Jan 2018 14:48:43 +0000 Subject: [PATCH 07/12] Exposed SoundManager via Scene Systems --- src/scene/local/InjectionMap.js | 1 + src/scene/local/Systems.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/scene/local/InjectionMap.js b/src/scene/local/InjectionMap.js index fb5bbece2..4cee37874 100644 --- a/src/scene/local/InjectionMap.js +++ b/src/scene/local/InjectionMap.js @@ -9,6 +9,7 @@ var InjectionMap = { anims: 'anims', cache: 'cache', registry: 'registry', + sound: 'sound', textures: 'textures', add: 'add', diff --git a/src/scene/local/Systems.js b/src/scene/local/Systems.js index a34b1c57a..a7e687217 100644 --- a/src/scene/local/Systems.js +++ b/src/scene/local/Systems.js @@ -40,6 +40,7 @@ var Systems = new Class({ this.anims; this.cache; this.registry; + this.sound; this.textures; // Reference to Scene specific managers (Factory, Tweens, Loader, Physics, etc) @@ -72,6 +73,7 @@ var Systems = new Class({ this.anims = game.anims; this.cache = game.cache; this.registry = game.registry; + this.sound = game.sound; this.textures = game.textures; this.plugins = new PluginManager(scene); From 00cebf8eae26f69210e80f0b9b24e675544e0f03 Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Thu, 11 Jan 2018 14:03:34 -0600 Subject: [PATCH 08/12] CollideGroupVsTilemapLayer implementation --- .../arcade/inc/CollideGroupVsTilemapLayer.js | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/physics/arcade/inc/CollideGroupVsTilemapLayer.js b/src/physics/arcade/inc/CollideGroupVsTilemapLayer.js index 315ad61f6..ac2812ee2 100644 --- a/src/physics/arcade/inc/CollideGroupVsTilemapLayer.js +++ b/src/physics/arcade/inc/CollideGroupVsTilemapLayer.js @@ -1,8 +1,25 @@ var CollideGroupVsTilemapLayer = function (group, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) { - // TODO + var children = group.getChildren(); - return false; + if (children.length === 0) + { + return false; + } + + var didCollide = false; + + for (var i = 0; i < children.length; i++) + { + if (children[i].body) + { + if (this.collideSpriteVsTilemapLayer(children[i], tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly)) { + didCollide = true; + } + } + } + + return didCollide; }; module.exports = CollideGroupVsTilemapLayer; From bab399a02e40cd9643a23060e0920124c3ff74db Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Thu, 11 Jan 2018 14:13:42 -0600 Subject: [PATCH 09/12] Made CollideHandler consistent by returning value from logic branches Each branch should return true/false based on whether a collision happened --- src/physics/arcade/inc/CollideHandler.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/physics/arcade/inc/CollideHandler.js b/src/physics/arcade/inc/CollideHandler.js index 084177c2a..83eea732e 100644 --- a/src/physics/arcade/inc/CollideHandler.js +++ b/src/physics/arcade/inc/CollideHandler.js @@ -9,7 +9,7 @@ var CollideHandler = function (object1, object2, collideCallback, processCallbac // If neither of the objects are set then bail out if (!object1 || !object2) { - return; + return false; } // A Body @@ -17,15 +17,15 @@ var CollideHandler = function (object1, object2, collideCallback, processCallbac { if (object2.body) { - this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.isParent) { - this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.isTilemap) { - this.collideSpriteVsTilemapLayer(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideSpriteVsTilemapLayer(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } } // GROUPS @@ -33,15 +33,15 @@ var CollideHandler = function (object1, object2, collideCallback, processCallbac { if (object2.body) { - this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.isParent) { - this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.isTilemap) { - this.collideGroupVsTilemapLayer(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideGroupVsTilemapLayer(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } } // TILEMAP LAYERS @@ -49,11 +49,11 @@ var CollideHandler = function (object1, object2, collideCallback, processCallbac { if (object2.body) { - this.collideSpriteVsTilemapLayer(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideSpriteVsTilemapLayer(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.isParent) { - this.collideGroupVsTilemapLayer(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); + return this.collideGroupVsTilemapLayer(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); } } }; From 16b672e291203ef2f67f363ade4f665b1c1938d4 Mon Sep 17 00:00:00 2001 From: Dan Flettre Date: Thu, 11 Jan 2018 18:14:45 -0600 Subject: [PATCH 10/12] set data to KeyCombo for KeyComboMatchEvent --- src/input/keyboard/combo/KeyComboMatchEvent.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/input/keyboard/combo/KeyComboMatchEvent.js b/src/input/keyboard/combo/KeyComboMatchEvent.js index 7928b3c11..a8661dce9 100644 --- a/src/input/keyboard/combo/KeyComboMatchEvent.js +++ b/src/input/keyboard/combo/KeyComboMatchEvent.js @@ -11,9 +11,7 @@ var KeyComboMatchEvent = new Class({ { Event.call(this, 'KEY_COMBO_MATCH_EVENT'); - this.target = keyCombo; - - this.data = keyboardEvent; + this.data = keyCombo; } }); From 242471beb949515f084e5a5f93a430203cf3acf5 Mon Sep 17 00:00:00 2001 From: yp Date: Fri, 12 Jan 2018 02:18:36 +0200 Subject: [PATCH 11/12] Renamed no longer existing Vector2/3 .sub and .len to .subtract and .length where still used --- src/camera/3d/Camera3D.js | 8 ++++---- src/curves/curve/inc/GetTangent.js | 2 +- src/curves/line/LineCurve.js | 4 ++-- src/curves/path/inc/EllipseTo.js | 2 +- src/math/Quaternion.js | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/camera/3d/Camera3D.js b/src/camera/3d/Camera3D.js index b085b77ff..2e08ec376 100644 --- a/src/camera/3d/Camera3D.js +++ b/src/camera/3d/Camera3D.js @@ -298,7 +298,7 @@ var Camera3D = new Class({ dir.set(x, y, z); } - dir.sub(this.position).normalize(); + dir.subtract(this.position).normalize(); // Calculate right vector tmpVec3.copy(dir).cross(up).normalize(); @@ -319,7 +319,7 @@ var Camera3D = new Class({ rotateAround: function (point, radians, axis) { - tmpVec3.copy(point).sub(this.position); + tmpVec3.copy(point).subtract(this.position); this.translate(tmpVec3); this.rotate(radians, axis); @@ -391,7 +391,7 @@ var Camera3D = new Class({ direction.unproject(viewport, mtx); - direction.sub(origin).normalize(); + direction.subtract(origin).normalize(); return this.ray; }, @@ -419,7 +419,7 @@ var Camera3D = new Class({ var dir = dirvec.set(this.direction).negate(); // Better view-aligned billboards might use this: - // var dir = tmp.set(camera.position).sub(p).normalize(); + // var dir = tmp.set(camera.position).subtract(p).normalize(); var right = rightvec.set(this.up).cross(dir).normalize(); var up = tmpVec3.set(dir).cross(right).normalize(); diff --git a/src/curves/curve/inc/GetTangent.js b/src/curves/curve/inc/GetTangent.js index 474c11c25..e4b46b741 100644 --- a/src/curves/curve/inc/GetTangent.js +++ b/src/curves/curve/inc/GetTangent.js @@ -39,7 +39,7 @@ var GetTangent = function (t, out) this.getPoint(t1, this._tmpVec2A); this.getPoint(t2, out); - return out.sub(this._tmpVec2A).normalize(); + return out.subtract(this._tmpVec2A).normalize(); }; module.exports = GetTangent; diff --git a/src/curves/line/LineCurve.js b/src/curves/line/LineCurve.js index 124f6a5a9..d162846b2 100644 --- a/src/curves/line/LineCurve.js +++ b/src/curves/line/LineCurve.js @@ -59,7 +59,7 @@ var LineCurve = new Class({ return out.copy(this.p1); } - out.copy(this.p1).sub(this.p0).scale(t).add(this.p0); + out.copy(this.p1).subtract(this.p0).scale(t).add(this.p0); return out; }, @@ -72,7 +72,7 @@ var LineCurve = new Class({ getTangent: function () { - var tangent = tmpVec2.copy(this.p1).sub(this.p0); + var tangent = tmpVec2.copy(this.p1).subtract(this.p0); return tangent.normalize(); }, diff --git a/src/curves/path/inc/EllipseTo.js b/src/curves/path/inc/EllipseTo.js index ab5017c0f..4b13e9327 100644 --- a/src/curves/path/inc/EllipseTo.js +++ b/src/curves/path/inc/EllipseTo.js @@ -26,7 +26,7 @@ var EllipseTo = function (xRadius, yRadius, startAngle, endAngle, clockwise, rot // Calculate where to center the ellipse var start = ellipse.getStartPoint(this._tmpVec2B); - end.sub(start); + end.subtract(start); ellipse.x = end.x; ellipse.y = end.y; diff --git a/src/math/Quaternion.js b/src/math/Quaternion.js index e8f3040bb..dd819e658 100644 --- a/src/math/Quaternion.js +++ b/src/math/Quaternion.js @@ -168,7 +168,7 @@ var Quaternion = new Class({ if (dot < -0.999999) { - if (tmpvec.copy(xUnitVec3).cross(a).len() < EPSILON) + if (tmpvec.copy(xUnitVec3).cross(a).length() < EPSILON) { tmpvec.copy(yUnitVec3).cross(a); } From d55dc0da2da670a87c53488a9b8703bf1e637089 Mon Sep 17 00:00:00 2001 From: Dan Flettre Date: Thu, 11 Jan 2018 18:29:20 -0600 Subject: [PATCH 12/12] update headings I noticed `CONTRIBUTING.md` headings were not properly formatted markdown. I believe GitHub recently changed their markdown spec recently to make headings more strict. This update fixes all the headings in this file --- .github/CONTRIBUTING.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 086a6c716..4309c9657 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,10 +1,10 @@ -#How to contribute +# How to contribute It's important to us that you feel you can contribute towards the evolution of Phaser. This can take many forms: from helping to fix bugs or improve the docs, to adding in new features to the source. This guide should help you in making that process as smooth as possible. Before contributing, please read the [code of conduct](https://github.com/photonstorm/phaser/blob/master/v2/CODE_OF_CONDUCT.md). -##Reporting issues +## Reporting issues [GitHub Issues][0] is the place to report bugs you may have found. When submitting a bug please do the following: @@ -19,12 +19,12 @@ Before contributing, please read the [code of conduct](https://github.com/photon **5. Share as much information as possible.** Include browser version affected, your OS, version of the library, steps to reproduce, etc. "X isn't working!!!1!" will probably just be closed. -##Pixi and Phaser +## Pixi and Phaser It's important to understand that internally Phaser 2 uses a heavily customized version of [Pixi.js v2](https://github.com/GoodBoyDigital/pixi.js/) for all rendering. It's possible you may find a bug that is generated on the Pixi level rather than Phaser. You're welcome to still report the issue of course, but if you get a reply saying we think it might be a Pixi issue, this is what we're talking about :) -##Support Forum +## Support Forum We have a very active [Phaser Support Forum][4]. If you need general support, or are struggling to understand how to do something or need your code checked over, then we would urge you to post it to our forum. There are a lot of friendly devs in there who can help, as well as the core Phaser and Pixi teams, so it's a great place to get support from. You're welcome to report bugs directly on GitHub, but for general support we'd always recommend using the forum first. @@ -47,17 +47,17 @@ make your changes and submit a Pull Request: - **Only commit relevant changes.** Don't include changes that are not directly relevant to the fix you are making. The more focused a PR is, the faster it will get attention and be merged. Extra files changing only whitespace or trash files will likely get your PR closed. -##Coding style preferences are not contributions +## Coding style preferences are not contributions If your PR is doing little more than changing the Phaser source code into a format / coding style that you prefer then we will automatically close it. All PRs must adhere to the coding style already set-out across the thousands of lines of code in Phaser. Your personal preferences for how things should "look" or be structured do not apply here, sorry. PRs should fix bugs, fix documentation or add features. No changes for the sake of change. -##I don't really like git / node.js, but I can fix this bug +## I don't really like git / node.js, but I can fix this bug That is fine too. While Pull Requests are the best thing in the world for us, they are not the only way to help. You're welcome to post fixes to our forum or even just email them to us. All we ask is that you still adhere to the guidelines presented here re: JSHint, etc. -##Code Style Guide +## Code Style Guide - Use 4 spaces for tabs, never tab characters.