Skip to content

Commit 6b1cdc8

Browse files
authored
Merge pull request phaserjs#4858 from samme/feature/closest-furthest-targets
Add `targets` argument to ArcadePhysics#closest() and ArcadePhysics#furthest()
2 parents 9596f7c + e572921 commit 6b1cdc8

1 file changed

Lines changed: 64 additions & 29 deletions

File tree

src/physics/arcade/ArcadePhysics.js

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var World = require('./World');
2323
* It also holds some useful methods for moving and rotating Arcade Physics Bodies.
2424
*
2525
* You can access it from within a Scene using `this.physics`.
26-
*
26+
*
2727
* Arcade Physics uses the Projection Method of collision resolution and separation. While it's fast and suitable
2828
* for 'arcade' style games it lacks stability when multiple objects are in close proximity or resting upon each other.
2929
* The separation that stops two objects penetrating may create a new penetration against a different object. If you
@@ -186,7 +186,7 @@ var ArcadePhysics = new Class({
186186
* If two Groups or arrays are passed, each member of one will be tested against each member of the other.
187187
*
188188
* If **only** one Group is passed (as `object1`), each member of the Group will be collided against the other members.
189-
*
189+
*
190190
* If **only** one Array is passed, the array is iterated and every element in it is tested against the others.
191191
*
192192
* Two callbacks can be provided. The `collideCallback` is invoked if a collision occurs and the two colliding
@@ -221,15 +221,15 @@ var ArcadePhysics = new Class({
221221

222222
/**
223223
* This advanced method is specifically for testing for collision between a single Sprite and an array of Tile objects.
224-
*
224+
*
225225
* You should generally use the `collide` method instead, with a Sprite vs. a Tilemap Layer, as that will perform
226226
* tile filtering and culling for you, as well as handle the interesting face collision automatically.
227-
*
227+
*
228228
* This method is offered for those who would like to check for collision with specific Tiles in a layer, without
229229
* having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic collisions
230230
* on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method,
231231
* you should filter them before passing them to this method.
232-
*
232+
*
233233
* Important: Use of this method skips the `interesting faces` system that Tilemap Layers use. This means if you have
234234
* 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
235235
* tiles as the interesting face calculations are skipped. However, for quick-fire small collision set tests on
@@ -254,10 +254,10 @@ var ArcadePhysics = new Class({
254254

255255
/**
256256
* This advanced method is specifically for testing for overlaps between a single Sprite and an array of Tile objects.
257-
*
257+
*
258258
* You should generally use the `overlap` method instead, with a Sprite vs. a Tilemap Layer, as that will perform
259259
* tile filtering and culling for you, as well as handle the interesting face collision automatically.
260-
*
260+
*
261261
* This method is offered for those who would like to check for overlaps with specific Tiles in a layer, without
262262
* having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic overlap
263263
* tests on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method,
@@ -367,75 +367,110 @@ var ArcadePhysics = new Class({
367367
},
368368

369369
/**
370-
* Finds the Dynamic Body closest to a source point or object.
371-
*
372-
* If two or more bodies are the exact same distance from the source point, only the first body
370+
* Finds the Body or Game Object closest to a source point or object.
371+
*
372+
* If a `targets` argument is passed, this method finds the closest of those.
373+
* The targets can be Arcade Physics Game Objects, Dynamic Bodies, or Static Bodies.
374+
*
375+
* If no `targets` argument is passed, this method finds the closest Dynamic Body.
376+
*
377+
* If two or more targets are the exact same distance from the source point, only the first target
373378
* is returned.
374379
*
375380
* @method Phaser.Physics.Arcade.ArcadePhysics#closest
376381
* @since 3.0.0
377382
*
378383
* @param {any} source - Any object with public `x` and `y` properties, such as a Game Object or Geometry object.
384+
* @param {(Phaser.Physics.Arcade.Body[]|Phaser.Physics.Arcade.StaticBody[]|Phaser.GameObjects.GameObject[])} [targets] - The targets.
379385
*
380-
* @return {Phaser.Physics.Arcade.Body} The closest Dynamic Body to the given source point.
386+
* @return {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody|Phaser.GameObjects.GameObject)} The target closest to the given source point.
381387
*/
382-
closest: function (source)
388+
closest: function (source, targets)
383389
{
384-
var bodies = this.world.bodies;
390+
if (!targets)
391+
{
392+
targets = this.world.bodies.entries;
393+
}
385394

386395
var min = Number.MAX_VALUE;
387396
var closest = null;
388397
var x = source.x;
389398
var y = source.y;
399+
var len = targets.length;
390400

391-
bodies.iterate(function (target)
401+
for (var i = 0; i < len; i++)
392402
{
393-
var distance = DistanceSquared(x, y, target.x, target.y);
403+
var target = targets[i];
404+
var body = target.body || target;
405+
406+
if (source === target || source === body || source === body.gameObject || source === body.center)
407+
{
408+
continue;
409+
}
410+
411+
var distance = DistanceSquared(x, y, body.center.x, body.center.y);
394412

395413
if (distance < min)
396414
{
397415
closest = target;
398416
min = distance;
399417
}
400-
401-
});
418+
}
402419

403420
return closest;
404421
},
405422

406423
/**
407-
* Finds the Dynamic Body farthest from a source point or object.
408-
*
409-
* If two or more bodies are the exact same distance from the source point, only the first body
424+
* Finds the Body or Game Object farthest from a source point or object.
425+
*
426+
* If a `targets` argument is passed, this method finds the farthest of those.
427+
* The targets can be Arcade Physics Game Objects, Dynamic Bodies, or Static Bodies.
428+
*
429+
* If no `targets` argument is passed, this method finds the farthest Dynamic Body.
430+
*
431+
* If two or more targets are the exact same distance from the source point, only the first target
410432
* is returned.
411433
*
412434
* @method Phaser.Physics.Arcade.ArcadePhysics#furthest
413435
* @since 3.0.0
414436
*
415437
* @param {any} source - Any object with public `x` and `y` properties, such as a Game Object or Geometry object.
438+
* @param {(Phaser.Physics.Arcade.Body[]|Phaser.Physics.Arcade.StaticBody[]|Phaser.GameObjects.GameObject[])} [targets] - The targets.
416439
*
417-
* @return {Phaser.Physics.Arcade.Body} The Dynamic Body furthest away from the given source point.
440+
* @return {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody|Phaser.GameObjects.GameObject)} The target farthest from the given source point.
418441
*/
419-
furthest: function (source)
442+
furthest: function (source, targets)
420443
{
421-
var bodies = this.world.bodies;
444+
if (!targets)
445+
{
446+
targets = this.world.bodies.entries;
447+
}
422448

423449
var max = -1;
424450
var farthest = null;
425451
var x = source.x;
426452
var y = source.y;
453+
var len = targets.length;
427454

428-
bodies.iterate(function (target)
455+
for (var i = 0; i < len; i++)
429456
{
430-
var distance = DistanceSquared(x, y, target.x, target.y);
457+
var target = targets[i];
458+
var body = target.body || target;
459+
460+
if (source === target || source === body || source === body.gameObject || source === body.center)
461+
{
462+
continue;
463+
}
464+
465+
var distance = DistanceSquared(x, y, body.center.x, body.center.y);
431466

432467
if (distance > max)
433468
{
434469
farthest = target;
435470
max = distance;
436471
}
437472

438-
});
473+
}
439474

440475
return farthest;
441476
},
@@ -545,10 +580,10 @@ var ArcadePhysics = new Class({
545580
/**
546581
* This method will search the given rectangular area and return an array of all physics bodies that
547582
* overlap with it. It can return either Dynamic, Static bodies or a mixture of both.
548-
*
583+
*
549584
* A body only has to intersect with the search area to be considered, it doesn't have to be fully
550585
* contained within it.
551-
*
586+
*
552587
* If Arcade Physics is set to use the RTree (which it is by default) then the search for is extremely fast,
553588
* otherwise the search is O(N) for Dynamic Bodies.
554589
*
@@ -568,7 +603,7 @@ var ArcadePhysics = new Class({
568603
{
569604
return OverlapRect(this.world, x, y, width, height, includeDynamic, includeStatic);
570605
},
571-
606+
572607
/**
573608
* The Scene that owns this plugin is shutting down.
574609
* We need to kill and reset all internal properties as well as stop listening to Scene events.

0 commit comments

Comments
 (0)