Skip to content

Commit d160df3

Browse files
committed
Removed late Set, optimized step process and added overlapTiles and collideTile methods.
1 parent 73617da commit d160df3

1 file changed

Lines changed: 145 additions & 79 deletions

File tree

src/physics/arcade/World.js

Lines changed: 145 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -95,28 +95,6 @@ var World = new Class({
9595
*/
9696
this.pendingDestroy = new Set();
9797

98-
/**
99-
* Dynamic Bodies that need a second `update` call to resynchronize their Game Objects.
100-
* This set is filled only when the `_late` flag is on, and is processed and cleared during `postUpdate`.
101-
*
102-
* @name Phaser.Physics.Arcade.World#late
103-
* @type {Phaser.Structs.Set.<Phaser.Physics.Arcade.Body>}
104-
* @private
105-
* @since 3.16.0
106-
*/
107-
this.late = new Set();
108-
109-
/**
110-
* A flag allowing the `late` set to be filled, as appropriate.
111-
* This is on (true) only between `update` and `postUpdate` and false at other times.
112-
*
113-
* @name Phaser.Physics.Arcade.World#_late
114-
* @type {boolean}
115-
* @private
116-
* @since 3.16.0
117-
*/
118-
this._late = false;
119-
12098
/**
12199
* This simulation's collision processors.
122100
*
@@ -651,7 +629,6 @@ var World = new Class({
651629
{
652630
this.tree.remove(body);
653631
this.bodies.delete(body);
654-
this.late.delete(body);
655632
}
656633
else if (body.physicsType === CONST.STATIC_BODY)
657634
{
@@ -935,12 +912,25 @@ var World = new Class({
935912
return;
936913
}
937914

915+
// Update all active bodies
916+
var body;
917+
var bodies = this.bodies.entries;
918+
919+
for (var i = 0; i < bodies.length; i++)
920+
{
921+
body = bodies[i];
922+
923+
if (body.enable)
924+
{
925+
body.preUpdate();
926+
}
927+
}
928+
938929
var stepsThisFrame = 0;
939930
var fixedDelta = this._frameTime;
940931
var msPerFrame = this._frameTimeMS * this.timeScale;
941932

942933
this._elapsed += delta;
943-
this._late = false;
944934

945935
while (this._elapsed >= msPerFrame)
946936
{
@@ -952,7 +942,6 @@ var World = new Class({
952942
}
953943

954944
this.stepsLastFrame = stepsThisFrame;
955-
this._late = true;
956945
},
957946

958947
/**
@@ -1000,18 +989,6 @@ var World = new Class({
1000989
collider.update();
1001990
}
1002991
}
1003-
1004-
len = bodies.length;
1005-
1006-
for (i = 0; i < len; i++)
1007-
{
1008-
body = bodies[i];
1009-
1010-
if (body.enable)
1011-
{
1012-
body.postUpdate();
1013-
}
1014-
}
1015992
},
1016993

1017994
/**
@@ -1023,38 +1000,23 @@ var World = new Class({
10231000
postUpdate: function ()
10241001
{
10251002
var i;
1026-
var bodies;
10271003
var body;
1028-
var len;
1004+
var bodies = this.bodies.entries;
1005+
var len = bodies.length;
10291006

10301007
var dynamic = this.bodies;
10311008
var staticBodies = this.staticBodies;
1032-
var pending = this.pendingDestroy;
1033-
var late = this.late;
10341009

1035-
if (late.size > 0)
1010+
for (i = 0; i < len; i++)
10361011
{
1037-
bodies = late.entries;
1038-
len = bodies.length;
1012+
body = bodies[i];
10391013

1040-
for (i = 0; i < len; i++)
1014+
if (body.enable)
10411015
{
1042-
body = bodies[i];
1043-
1044-
if (body.enable)
1045-
{
1046-
body.postUpdate();
1047-
}
1016+
body.postUpdate();
10481017
}
1049-
1050-
late.clear();
10511018
}
10521019

1053-
this._late = false;
1054-
1055-
bodies = dynamic.entries;
1056-
len = bodies.length;
1057-
10581020
if (this.drawDebug)
10591021
{
10601022
var graphics = this.debugGraphic;
@@ -1085,6 +1047,8 @@ var World = new Class({
10851047
}
10861048
}
10871049

1050+
var pending = this.pendingDestroy;
1051+
10881052
if (pending.size > 0)
10891053
{
10901054
var dynamicTree = this.tree;
@@ -1101,7 +1065,6 @@ var World = new Class({
11011065
{
11021066
dynamicTree.remove(body);
11031067
dynamic.delete(body);
1104-
late.delete(body);
11051068
}
11061069
else if (body.physicsType === CONST.STATIC_BODY)
11071070
{
@@ -1400,18 +1363,9 @@ var World = new Class({
14001363
this.emit(Events.OVERLAP, body1.gameObject, body2.gameObject, body1, body2);
14011364
}
14021365
}
1403-
else
1366+
else if (body1.onCollide || body2.onCollide)
14041367
{
1405-
if (this._late)
1406-
{
1407-
this.late.set(body1);
1408-
this.late.set(body2);
1409-
}
1410-
1411-
if (body1.onCollide || body2.onCollide)
1412-
{
1413-
this.emit(Events.COLLIDE, body1.gameObject, body2.gameObject, body1, body2);
1414-
}
1368+
this.emit(Events.COLLIDE, body1.gameObject, body2.gameObject, body1, body2);
14151369
}
14161370
}
14171371

@@ -1612,8 +1566,8 @@ var World = new Class({
16121566
}
16131567

16141568
// sync changes back to the bodies
1615-
body1.postUpdate();
1616-
body2.postUpdate();
1569+
// body1.postUpdate();
1570+
// body2.postUpdate();
16171571

16181572
return true;
16191573
},
@@ -2073,6 +2027,81 @@ var World = new Class({
20732027
return didCollide;
20742028
},
20752029

2030+
/**
2031+
* This advanced method is specifically for testing for collision between a single Sprite and an array of Tile objects.
2032+
*
2033+
* You should generally use the `collide` method instead, with a Sprite vs. a Tilemap Layer, as that will perform
2034+
* tile filtering and culling for you, as well as handle the interesting face collision automatically.
2035+
*
2036+
* This method is offered for those who would like to check for collision with specific Tiles in a layer, without
2037+
* having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic collisions
2038+
* on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method,
2039+
* you should filter them before passing them to this method.
2040+
*
2041+
* Important: Use of this method skips the `interesting faces` system that Tilemap Layers use. This means if you have
2042+
* say a row or column of tiles, and you jump into, or walk over them, it's possible to get stuck on the edges of the
2043+
* tiles as the interesting face calculations are skipped. However, for quick-fire small collision set tests on
2044+
* dynamic maps, this method can prove very useful.
2045+
*
2046+
* @method Phaser.Physics.Arcade.World#collideTiles
2047+
* @fires Phaser.Physics.Arcade.Events#TILE_COLLIDE
2048+
* @since 3.16.3
2049+
*
2050+
* @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision.
2051+
* @param {Phaser.Tilemaps.Tile[]} tiles - An array of Tiles to check for collision against.
2052+
* @param {ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide.
2053+
* @param {ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`.
2054+
* @param {any} [callbackContext] - The context in which to run the callbacks.
2055+
*
2056+
* @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated.
2057+
*/
2058+
collideTiles: function (sprite, tiles, collideCallback, processCallback, callbackContext)
2059+
{
2060+
if (!sprite.body.enable || tiles.length === 0)
2061+
{
2062+
return false;
2063+
}
2064+
else
2065+
{
2066+
return this.collideSpriteVsTilesHandler(sprite, tiles, collideCallback, processCallback, callbackContext, false, false);
2067+
}
2068+
},
2069+
2070+
/**
2071+
* This advanced method is specifically for testing for overlaps between a single Sprite and an array of Tile objects.
2072+
*
2073+
* You should generally use the `overlap` method instead, with a Sprite vs. a Tilemap Layer, as that will perform
2074+
* tile filtering and culling for you, as well as handle the interesting face collision automatically.
2075+
*
2076+
* This method is offered for those who would like to check for overlaps with specific Tiles in a layer, without
2077+
* having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic overlap
2078+
* tests on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method,
2079+
* you should filter them before passing them to this method.
2080+
*
2081+
* @method Phaser.Physics.Arcade.World#overlapTiles
2082+
* @fires Phaser.Physics.Arcade.Events#TILE_OVERLAP
2083+
* @since 3.16.3
2084+
*
2085+
* @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision.
2086+
* @param {Phaser.Tilemaps.Tile[]} tiles - An array of Tiles to check for collision against.
2087+
* @param {ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects overlap.
2088+
* @param {ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`.
2089+
* @param {any} [callbackContext] - The context in which to run the callbacks.
2090+
*
2091+
* @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated.
2092+
*/
2093+
overlapTiles: function (sprite, tiles, collideCallback, processCallback, callbackContext)
2094+
{
2095+
if (!sprite.body.enable || tiles.length === 0)
2096+
{
2097+
return false;
2098+
}
2099+
else
2100+
{
2101+
return this.collideSpriteVsTilesHandler(sprite, tiles, collideCallback, processCallback, callbackContext, true, false);
2102+
}
2103+
},
2104+
20762105
/**
20772106
* Internal handler for Sprite vs. Tilemap collisions.
20782107
* Please use Phaser.Physics.Arcade.World#collide instead.
@@ -2131,13 +2160,47 @@ var World = new Class({
21312160
{
21322161
return false;
21332162
}
2163+
else
2164+
{
2165+
return this.collideSpriteVsTilesHandler(sprite, mapData, collideCallback, processCallback, callbackContext, overlapOnly, true);
2166+
}
2167+
},
2168+
2169+
/**
2170+
* Internal handler for Sprite vs. Tilemap collisions.
2171+
* Please use Phaser.Physics.Arcade.World#collide instead.
2172+
*
2173+
* @method Phaser.Physics.Arcade.World#collideSpriteVsTilesHandler
2174+
* @fires Phaser.Physics.Arcade.Events#TILE_COLLIDE
2175+
* @fires Phaser.Physics.Arcade.Events#TILE_OVERLAP
2176+
* @private
2177+
* @since 3.16.3
2178+
*
2179+
* @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision.
2180+
* @param {(Phaser.Tilemaps.DynamicTilemapLayer|Phaser.Tilemaps.StaticTilemapLayer)} tilemapLayer - The second object to check for collision.
2181+
* @param {ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide.
2182+
* @param {ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`.
2183+
* @param {any} [callbackContext] - The context in which to run the callbacks.
2184+
* @param {boolean} [overlapOnly] - Whether this is a collision or overlap check.
2185+
* @param {boolean} [isLayer] - Is this check coming from a TilemapLayer or an array of tiles?
2186+
*
2187+
* @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated.
2188+
*/
2189+
collideSpriteVsTilesHandler: function (sprite, tiles, collideCallback, processCallback, callbackContext, overlapOnly, isLayer)
2190+
{
2191+
var body = sprite.body;
21342192

21352193
var tile;
21362194
var tileWorldRect = { left: 0, right: 0, top: 0, bottom: 0 };
2195+
var tilemapLayer;
2196+
var collision = false;
21372197

2138-
for (var i = 0; i < mapData.length; i++)
2198+
for (var i = 0; i < tiles.length; i++)
21392199
{
2140-
tile = mapData[i];
2200+
tile = tiles[i];
2201+
2202+
tilemapLayer = tile.tilemapLayer;
2203+
21412204
tileWorldRect.left = tilemapLayer.tileToWorldX(tile.x);
21422205
tileWorldRect.top = tilemapLayer.tileToWorldY(tile.y);
21432206

@@ -2154,28 +2217,32 @@ var World = new Class({
21542217
if (TileIntersectsBody(tileWorldRect, body)
21552218
&& (!processCallback || processCallback.call(callbackContext, sprite, tile))
21562219
&& ProcessTileCallbacks(tile, sprite)
2157-
&& (overlapOnly || SeparateTile(i, body, tile, tileWorldRect, tilemapLayer, this.TILE_BIAS)))
2220+
&& (overlapOnly || SeparateTile(i, body, tile, tileWorldRect, tilemapLayer, this.TILE_BIAS, isLayer)))
21582221
{
21592222
this._total++;
21602223

2224+
collision = true;
2225+
21612226
if (collideCallback)
21622227
{
21632228
collideCallback.call(callbackContext, sprite, tile);
21642229
}
21652230

21662231
if (overlapOnly && body.onOverlap)
21672232
{
2168-
this.emit(Events.TILE_OVERLAP, body.gameObject, tile, body);
2233+
this.emit(Events.TILE_OVERLAP, sprite, tile, body);
21692234
}
21702235
else if (body.onCollide)
21712236
{
2172-
this.emit(Events.TILE_COLLIDE, body.gameObject, tile, body);
2237+
this.emit(Events.TILE_COLLIDE, sprite, tile, body);
21732238
}
21742239

21752240
// sync changes back to the body
2176-
body.postUpdate();
2241+
// body.postUpdate();
21772242
}
21782243
}
2244+
2245+
return collision;
21792246
},
21802247

21812248
/**
@@ -2288,7 +2355,6 @@ var World = new Class({
22882355
this.staticTree.clear();
22892356
this.bodies.clear();
22902357
this.staticBodies.clear();
2291-
this.late.clear();
22922358
this.colliders.destroy();
22932359

22942360
this.removeAllListeners();

0 commit comments

Comments
 (0)