mirror of
https://github.com/photonstorm/phaser
synced 2025-01-10 20:28:56 +00:00
Major Optimization for Tilemap Collision Indexing
This update optimizes an existing feature (Tilemap Collision Indexing). This optimization will apply to [nearly] everyone using procedural generation tilemaps, infinite tilemaps, multiplayer tilemaps, particularly large tilemaps (especially those dyanmic in nature) or who otherwise intend to index collisions before the tiles are loaded. Benchmarking: Using the standard approach, indexing collisions for a 500x450 tileset took 2530ms. By pre-building the collision index array in its entirety, I was able to reduce that to 259ms. However, this implementation reduces it to 8 ms. Larger tilemaps would be exponentially affected. There are some considerations to make here since there are better implementations, but it would require deprecating some existing code. The advantage would be that the standard approach itself would be optimized, (thus avoiding the sort of 2500+ms costs here), rather than fairly obscured as it is with this implementation.
This commit is contained in:
parent
106e32a4f5
commit
5cd60b3378
5 changed files with 50 additions and 25 deletions
|
@ -1660,16 +1660,18 @@ var Tilemap = new Class({
|
|||
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||
* update.
|
||||
* @param {Phaser.Tilemaps.LayerData} [layer] - [description]
|
||||
* @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to
|
||||
* false if no tiles have been placed for significant performance boost.
|
||||
*
|
||||
* @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid.
|
||||
*/
|
||||
setCollision: function (indexes, collides, recalculateFaces, layer)
|
||||
setCollision: function (indexes, collides, recalculateFaces, layer, updateLayer)
|
||||
{
|
||||
layer = this.getLayer(layer);
|
||||
|
||||
if (layer === null) { return this; }
|
||||
|
||||
TilemapComponents.SetCollision(indexes, collides, recalculateFaces, layer);
|
||||
TilemapComponents.SetCollision(indexes, collides, recalculateFaces, layer, updateLayer);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
|
|
@ -23,33 +23,39 @@ var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
|||
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||
* update.
|
||||
* @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon.
|
||||
* @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to
|
||||
* false if no tiles have been placed for significant performance boost.
|
||||
*/
|
||||
var SetCollision = function (indexes, collides, recalculateFaces, layer)
|
||||
var SetCollision = function (indexes, collides, recalculateFaces, layer, updateLayer)
|
||||
{
|
||||
if (collides === undefined) { collides = true; }
|
||||
if (recalculateFaces === undefined) { recalculateFaces = true; }
|
||||
if (!Array.isArray(indexes)) { indexes = [ indexes ]; }
|
||||
if (updateLayer === undefined) { updateLayer = true; }
|
||||
|
||||
// Update the array of colliding indexes
|
||||
for (var i = 0; i < indexes.length; i++)
|
||||
{
|
||||
SetLayerCollisionIndex(indexes[i], collides, layer);
|
||||
}
|
||||
|
||||
|
||||
// Update the tiles
|
||||
for (var ty = 0; ty < layer.height; ty++)
|
||||
if(updateLayer)
|
||||
{
|
||||
for (var tx = 0; tx < layer.width; tx++)
|
||||
for (var ty = 0; ty < layer.height; ty++)
|
||||
{
|
||||
var tile = layer.data[ty][tx];
|
||||
|
||||
if (tile && indexes.indexOf(tile.index) !== -1)
|
||||
for (var tx = 0; tx < layer.width; tx++)
|
||||
{
|
||||
SetTileCollision(tile, collides);
|
||||
var tile = layer.data[ty][tx];
|
||||
|
||||
if (tile && indexes.indexOf(tile.index) !== -1)
|
||||
{
|
||||
SetTileCollision(tile, collides);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (recalculateFaces) { CalculateFacesWithin(0, 0, layer.width, layer.height, layer); }
|
||||
};
|
||||
|
||||
|
|
|
@ -25,11 +25,14 @@ var SetLayerCollisionIndex = require('./SetLayerCollisionIndex');
|
|||
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||
* update.
|
||||
* @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon.
|
||||
* @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to
|
||||
* false if no tiles have been placed for significant performance boost.
|
||||
*/
|
||||
var SetCollisionBetween = function (start, stop, collides, recalculateFaces, layer)
|
||||
var SetCollisionBetween = function (start, stop, collides, recalculateFaces, layer, updateLayer)
|
||||
{
|
||||
if (collides === undefined) { collides = true; }
|
||||
if (recalculateFaces === undefined) { recalculateFaces = true; }
|
||||
if (updateLayer === undefined) { updateLayer = true; }
|
||||
|
||||
if (start > stop) { return; }
|
||||
|
||||
|
@ -40,21 +43,24 @@ var SetCollisionBetween = function (start, stop, collides, recalculateFaces, lay
|
|||
}
|
||||
|
||||
// Update the tiles
|
||||
for (var ty = 0; ty < layer.height; ty++)
|
||||
if(updateLayer)
|
||||
{
|
||||
for (var tx = 0; tx < layer.width; tx++)
|
||||
for (var ty = 0; ty < layer.height; ty++)
|
||||
{
|
||||
var tile = layer.data[ty][tx];
|
||||
if (tile)
|
||||
for (var tx = 0; tx < layer.width; tx++)
|
||||
{
|
||||
if (tile.index >= start && tile.index <= stop)
|
||||
var tile = layer.data[ty][tx];
|
||||
if (tile)
|
||||
{
|
||||
SetTileCollision(tile, collides);
|
||||
if (tile.index >= start && tile.index <= stop)
|
||||
{
|
||||
SetTileCollision(tile, collides);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (recalculateFaces) { CalculateFacesWithin(0, 0, layer.width, layer.height, layer); }
|
||||
};
|
||||
|
||||
|
|
|
@ -872,7 +872,9 @@ var DynamicTilemapLayer = new Class({
|
|||
* single numeric index or an array of indexes: [2, 3, 15, 20]. The `collides` parameter controls if
|
||||
* collision will be enabled (true) or disabled (false).
|
||||
*
|
||||
* @method Phaser.Tilemaps.DynamicTilemapLayer#setCollision
|
||||
* If no layer specified, the map's current layer is used.
|
||||
*
|
||||
* @method Phaser.Tilemaps.Tilemap#setCollision
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param {(integer|array)} indexes - Either a single tile index, or an array of tile indexes.
|
||||
|
@ -880,12 +882,19 @@ var DynamicTilemapLayer = new Class({
|
|||
* collision.
|
||||
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||
* update.
|
||||
* @param {Phaser.Tilemaps.LayerData} [layer] - [description]
|
||||
* @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to
|
||||
* false if no tiles have been placed for significant performance boost.
|
||||
*
|
||||
* @return {Phaser.Tilemaps.DynamicTilemapLayer} This Tilemap Layer object.
|
||||
* @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid.
|
||||
*/
|
||||
setCollision: function (indexes, collides, recalculateFaces)
|
||||
setCollision: function (indexes, collides, recalculateFaces, layer, updateLayer)
|
||||
{
|
||||
TilemapComponents.SetCollision(indexes, collides, recalculateFaces, this.layer);
|
||||
layer = this.getLayer(layer);
|
||||
|
||||
if (layer === null) { return this; }
|
||||
|
||||
TilemapComponents.SetCollision(indexes, collides, recalculateFaces, layer, updateLayer);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
|
|
@ -784,12 +784,14 @@ var StaticTilemapLayer = new Class({
|
|||
* collision.
|
||||
* @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the
|
||||
* update.
|
||||
* @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to
|
||||
* false if no tiles have been placed for significant performance boost.
|
||||
*
|
||||
* @return {Phaser.Tilemaps.StaticTilemapLayer} This Tilemap Layer object.
|
||||
*/
|
||||
setCollision: function (indexes, collides, recalculateFaces)
|
||||
setCollision: function (indexes, collides, recalculateFaces, updateLayer)
|
||||
{
|
||||
TilemapComponents.SetCollision(indexes, collides, recalculateFaces, this.layer);
|
||||
TilemapComponents.SetCollision(indexes, collides, recalculateFaces, this.layer, updateLayer);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue