Skip to content

Commit bd9898d

Browse files
committed
New merged separate function that now uses processCallback the way it was always meant to be used.
1 parent e7c2b6a commit bd9898d

2 files changed

Lines changed: 212 additions & 52 deletions

File tree

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ That is fine too. While Pull Requests are the best thing in the world for us, th
6464

6565
- Follow conventions already in the code, and listen to jshint. Our config is set-up for a reason.
6666

67-
Thanks to Chad for creating the original Contributing file which we adapted for our use.
67+
Thanks to Chad for creating the original Pixi.js Contributing file which we adapted for Phaser.
6868

6969
[0]: https://github.com/photonstorm/phaser/issues
7070
[1]: http://jsfiddle.net

src/physics/arcade/ArcadePhysics.js

Lines changed: 211 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -431,15 +431,17 @@ Phaser.Physics.Arcade.prototype = {
431431
},
432432

433433
/**
434-
* Checks for collision between two game objects. The objects can be Sprites, Groups, Emitters or Tilemap Layers.
435-
* You can perform Sprite vs. Sprite, Sprite vs. Group, Group vs. Group, Sprite vs. Tilemap Layer or Group vs. Tilemap Layer collisions.
436-
* The objects are also automatically separated.
434+
* Checks for collision between two game objects. You can perform Sprite vs. Sprite, Sprite vs. Group, Group vs. Group, Sprite vs. Tilemap Layer or Group vs. Tilemap Layer collisions.
435+
* The objects are also automatically separated. If you don't require separation then use ArcadePhysics.overlap instead.
436+
* An optional processCallback can be provided. If given this function will be called when two sprites are found to be colliding. It is called before any separation takes place,
437+
* giving you the chance to perform additional checks. If the function returns true then the collision and separation is carried out. If it returns false it is skipped.
438+
* The collideCallback is an optional function that is only called if two sprites collide. If a processCallback has been set then it needs to return true for collideCallback to be called.
437439
*
438440
* @method Phaser.Physics.Arcade#collide
439441
* @param {Phaser.Sprite|Phaser.Group|Phaser.Particles.Emitter|Phaser.Tilemap} object1 - The first object to check. Can be an instance of Phaser.Sprite, Phaser.Group, Phaser.Particles.Emitter, or Phaser.Tilemap
440442
* @param {Phaser.Sprite|Phaser.Group|Phaser.Particles.Emitter|Phaser.Tilemap} object2 - The second object to check. Can be an instance of Phaser.Sprite, Phaser.Group, Phaser.Particles.Emitter or Phaser.Tilemap
441-
* @param {function} [collideCallback=null] - An optional callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you specified them.
442-
* @param {function} [processCallback=null] - A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then collideCallback will only be called if processCallback returns true.
443+
* @param {function} [collideCallback=null] - An optional callback function that is called if the objects collide. The two objects will be passed to this function in the same order in which you specified them.
444+
* @param {function} [processCallback=null] - A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then collision will only happen if processCallback returns true. The two objects will be passed to this function in the same order in which you specified them.
443445
* @param {object} [callbackContext] - The context in which to run the callbacks.
444446
* @returns {boolean} True if a collision occured otherwise false.
445447
*/
@@ -612,32 +614,14 @@ Phaser.Physics.Arcade.prototype = {
612614
*/
613615
collideSpriteVsSprite: function (sprite1, sprite2, collideCallback, processCallback, callbackContext) {
614616

615-
this.separate(sprite1.body, sprite2.body);
616-
617-
if (this._result)
617+
if (this.separate(sprite1.body, sprite2.body, processCallback, callbackContext))
618618
{
619-
// They collided, is there a custom process callback?
620-
if (processCallback)
619+
if (collideCallback)
621620
{
622-
if (processCallback.call(callbackContext, sprite1, sprite2))
623-
{
624-
this._total++;
625-
626-
if (collideCallback)
627-
{
628-
collideCallback.call(callbackContext, sprite1, sprite2);
629-
}
630-
}
621+
collideCallback.call(callbackContext, sprite1, sprite2);
631622
}
632-
else
633-
{
634-
this._total++;
635623

636-
if (collideCallback)
637-
{
638-
collideCallback.call(callbackContext, sprite1, sprite2);
639-
}
640-
}
624+
this._total++;
641625
}
642626

643627
},
@@ -661,23 +645,16 @@ Phaser.Physics.Arcade.prototype = {
661645
for (var i = 0, len = this._potentials.length; i < len; i++)
662646
{
663647
// We have our potential suspects, are they in this group?
664-
if (this._potentials[i].sprite.group == group)
648+
if (this._potentials[i].sprite.group === group)
665649
{
666-
this.separate(sprite.body, this._potentials[i]);
667-
668-
if (this._result && processCallback)
650+
if (this.separate(sprite1.body, this._potentials[i], processCallback, callbackContext))
669651
{
670-
this._result = processCallback.call(callbackContext, sprite, this._potentials[i].sprite);
671-
}
672-
673-
if (this._result)
674-
{
675-
this._total++;
676-
677652
if (collideCallback)
678653
{
679-
collideCallback.call(callbackContext, sprite, this._potentials[i].sprite);
654+
collideCallback.call(callbackContext, sprite1, sprite2);
680655
}
656+
657+
this._total++;
681658
}
682659
}
683660
}
@@ -719,19 +696,206 @@ Phaser.Physics.Arcade.prototype = {
719696
* @method Phaser.Physics.Arcade#separate
720697
* @param {Phaser.Physics.Arcade.Body} body1 - The Body object to separate.
721698
* @param {Phaser.Physics.Arcade.Body} body2 - The Body object to separate.
722-
* @returns {boolean} Returns true if the bodies were separated, otherwise false.
699+
* @param {function} [processCallback=null] - A callback function that lets you perform additional checks against the two objects if they overlap. If this function is set then the sprites will only be collided if it returns true.
700+
* @param {object} [callbackContext] - The context in which to run the process callback.
701+
* @returns {boolean} Returns true if the bodies collided, otherwise false.
723702
*/
724-
separate: function (body1, body2) {
703+
separate: function (body1, body2, processCallback, callbackContext) {
725704

726-
if (body1 !== body2)
705+
// Can't separate two immovable bodies and the same body cannot collide with itself
706+
if (body1 === body2 || (body1.immovable && body2.immovable) || Phaser.Rectangle.intersects(body1, body2) === false)
727707
{
728-
this._result = (this.separateX(body1, body2) || this.separateY(body1, body2));
708+
return false;
729709
}
730-
else
710+
711+
// They overlap. Is there a custom process callback? If it returns true then we can carry on, otherwise we should abort.
712+
if (processCallback && processCallback.call(callbackContext, body1.sprite, body2.sprite) === false)
731713
{
732-
this._result = false;
714+
return false;
733715
}
734716

717+
// We got this far, so the bodies overlap and our process was good, which means we can separate ...
718+
this._overlap = 0;
719+
720+
this._maxOverlap = body1.deltaAbsX() + body2.deltaAbsX() + this.OVERLAP_BIAS;
721+
722+
if (body1.deltaX() === 0 && body2.deltaX() === 0)
723+
{
724+
// They overlap but neither of them are moving
725+
body1.embedded = true;
726+
body2.embedded = true;
727+
}
728+
else if (body1.deltaX() > body2.deltaX())
729+
{
730+
// Body1 is moving right and/or Body2 is moving left
731+
this._overlap = body1.x + body1.width - body2.x;
732+
733+
if ((this._overlap > this._maxOverlap) || body1.allowCollision.right === false || body2.allowCollision.left === false)
734+
{
735+
this._overlap = 0;
736+
}
737+
else
738+
{
739+
body1.touching.right = true;
740+
body2.touching.left = true;
741+
}
742+
}
743+
else if (body1.deltaX() < body2.deltaX())
744+
{
745+
// Body1 is moving left and/or Body2 is moving right
746+
this._overlap = body1.x - body2.width - body2.x;
747+
748+
if ((-this._overlap > this._maxOverlap) || body1.allowCollision.left === false || body2.allowCollision.right === false)
749+
{
750+
this._overlap = 0;
751+
}
752+
else
753+
{
754+
body1.touching.left = true;
755+
body2.touching.right = true;
756+
}
757+
}
758+
759+
// Then adjust their positions and velocities accordingly (if there was any overlap)
760+
if (this._overlap !== 0)
761+
{
762+
body1.overlapX = this._overlap;
763+
body2.overlapX = this._overlap;
764+
765+
if (!body1.customSeparateX && !body2.customSeparateX)
766+
{
767+
this._velocity1 = body1.velocity.x;
768+
this._velocity2 = body2.velocity.x;
769+
770+
if (!body1.immovable && !body2.immovable)
771+
{
772+
this._overlap *= 0.5;
773+
body1.overlapX = this._overlap;
774+
body2.overlapX = this._overlap;
775+
776+
body1.x = body1.x - this._overlap;
777+
body2.x += this._overlap;
778+
779+
this._newVelocity1 = Math.sqrt((this._velocity2 * this._velocity2 * body2.mass) / body1.mass) * ((this._velocity2 > 0) ? 1 : -1);
780+
this._newVelocity2 = Math.sqrt((this._velocity1 * this._velocity1 * body1.mass) / body2.mass) * ((this._velocity1 > 0) ? 1 : -1);
781+
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
782+
this._newVelocity1 -= this._average;
783+
this._newVelocity2 -= this._average;
784+
785+
body1.velocity.x = this._average + this._newVelocity1 * body1.bounce.x;
786+
body2.velocity.x = this._average + this._newVelocity2 * body2.bounce.x;
787+
}
788+
else if (!body1.immovable)
789+
{
790+
body1.x = body1.x - this._overlap;
791+
body1.velocity.x = this._velocity2 - this._velocity1 * body1.bounce.x;
792+
}
793+
else if (!body2.immovable)
794+
{
795+
body2.x += this._overlap;
796+
body2.velocity.x = this._velocity1 - this._velocity2 * body2.bounce.x;
797+
}
798+
}
799+
}
800+
801+
// Now for the vertical
802+
this._overlap = 0;
803+
804+
this._maxOverlap = body1.deltaAbsY() + body2.deltaAbsY() + this.OVERLAP_BIAS;
805+
806+
if (body1.deltaY() === 0 && body2.deltaY() === 0)
807+
{
808+
// They overlap but neither of them are moving
809+
body1.embedded = true;
810+
body2.embedded = true;
811+
}
812+
else if (body1.deltaY() > body2.deltaY())
813+
{
814+
// Body1 is moving down and/or Body2 is moving up
815+
this._overlap = body1.y + body1.height - body2.y;
816+
817+
if ((this._overlap > this._maxOverlap) || body1.allowCollision.down === false || body2.allowCollision.up === false)
818+
{
819+
this._overlap = 0;
820+
}
821+
else
822+
{
823+
body1.touching.down = true;
824+
body2.touching.up = true;
825+
}
826+
}
827+
else if (body1.deltaY() < body2.deltaY())
828+
{
829+
// Body1 is moving up and/or Body2 is moving down
830+
this._overlap = body1.y - body2.height - body2.y;
831+
832+
if ((-this._overlap > this._maxOverlap) || body1.allowCollision.up === false || body2.allowCollision.down === false)
833+
{
834+
this._overlap = 0;
835+
}
836+
else
837+
{
838+
body1.touching.up = true;
839+
body2.touching.down = true;
840+
}
841+
}
842+
843+
// Then adjust their positions and velocities accordingly (if there was any overlap)
844+
if (this._overlap !== 0)
845+
{
846+
body1.overlapY = this._overlap;
847+
body2.overlapY = this._overlap;
848+
849+
if (!body1.customSeparateY && !body2.customSeparateY)
850+
{
851+
this._velocity1 = body1.velocity.y;
852+
this._velocity2 = body2.velocity.y;
853+
854+
if (!body1.immovable && !body2.immovable)
855+
{
856+
this._overlap *= 0.5;
857+
body1.overlapY = this._overlap;
858+
body2.overlapY = this._overlap;
859+
860+
body1.y = body1.y - this._overlap;
861+
body2.y += this._overlap;
862+
863+
this._newVelocity1 = Math.sqrt((this._velocity2 * this._velocity2 * body2.mass) / body1.mass) * ((this._velocity2 > 0) ? 1 : -1);
864+
this._newVelocity2 = Math.sqrt((this._velocity1 * this._velocity1 * body1.mass) / body2.mass) * ((this._velocity1 > 0) ? 1 : -1);
865+
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
866+
this._newVelocity1 -= this._average;
867+
this._newVelocity2 -= this._average;
868+
869+
body1.velocity.y = this._average + this._newVelocity1 * body1.bounce.y;
870+
body2.velocity.y = this._average + this._newVelocity2 * body2.bounce.y;
871+
}
872+
else if (!body1.immovable)
873+
{
874+
body1.y -= this._overlap;
875+
body1.velocity.y = this._velocity2 - this._velocity1 * body1.bounce.y;
876+
877+
// This is special case code that handles things like horizontal moving platforms you can ride
878+
if (body2.moves)
879+
{
880+
body1.x += body2.x - body2.preX;
881+
}
882+
}
883+
else if (!body2.immovable)
884+
{
885+
body2.y += this._overlap;
886+
body2.velocity.y = this._velocity1 - this._velocity2 * body2.bounce.y;
887+
888+
// This is special case code that handles things like horizontal moving platforms you can ride
889+
if (body1.moves)
890+
{
891+
body2.x += body1.x - body1.preX;
892+
}
893+
}
894+
}
895+
}
896+
897+
return true;
898+
735899
},
736900

737901
/**
@@ -740,7 +904,6 @@ Phaser.Physics.Arcade.prototype = {
740904
* @param {Phaser.Physics.Arcade.Body} body1 - The Body object to separate.
741905
* @param {Phaser.Physics.Arcade.Body} body2 - The Body object to separate.
742906
* @returns {boolean} Returns true if the bodies were separated, otherwise false.
743-
*/
744907
separateX: function (body1, body2) {
745908
746909
// Can't separate two immovable bodies
@@ -833,8 +996,6 @@ Phaser.Physics.Arcade.prototype = {
833996
body2.x += this._overlap;
834997
body2.velocity.x = this._velocity1 - this._velocity2 * body2.bounce.x;
835998
}
836-
// body1.updateHulls();
837-
// body2.updateHulls();
838999
8391000
return true;
8401001
}
@@ -843,14 +1004,14 @@ Phaser.Physics.Arcade.prototype = {
8431004
return false;
8441005
8451006
},
1007+
*/
8461008

8471009
/**
8481010
* The core separation function to separate two physics bodies on the y axis.
8491011
* @method Phaser.Physics.Arcade#separateY
8501012
* @param {Phaser.Physics.Arcade.Body} body1 - The Body object to separate.
8511013
* @param {Phaser.Physics.Arcade.Body} body2 - The Body object to separate.
8521014
* @returns {boolean} Returns true if the bodies were separated, otherwise false.
853-
*/
8541015
separateY: function (body1, body2) {
8551016
8561017
// Can't separate two immovable or non-existing bodys
@@ -955,8 +1116,6 @@ Phaser.Physics.Arcade.prototype = {
9551116
body2.x += body1.x - body1.preX;
9561117
}
9571118
}
958-
// body1.updateHulls();
959-
// body2.updateHulls();
9601119
9611120
return true;
9621121
}
@@ -966,6 +1125,7 @@ Phaser.Physics.Arcade.prototype = {
9661125
return false;
9671126
9681127
},
1128+
*/
9691129

9701130
/**
9711131
* The core separation function to separate a physics body and an array of tiles.

0 commit comments

Comments
 (0)