diff --git a/README.md b/README.md index 30359761c..32808ed09 100644 --- a/README.md +++ b/README.md @@ -56,10 +56,15 @@ Significant API changes: * Tilemap.createFromObjects can now turn a bunch of Tiled objects into Sprites in one single call, and copies across all properties as well. * Tween.onStartCallback and onCompleteCallback have been removed to avoid confusion. You should use the onStart, onLoop and onComplete events instead. * Button.forceOut default value has changed from true to false, so Buttons will revert to an Up state (if set) when pressed and released. -* Body.drag has been removed. Please use the new Body.friction value instead (which is a number value, not a Point object) * The way the collision process callback works has changed significantly and now works as originally intended. * The World level quadtree is no longer created, they are now built and ripped down each time you collide a Group, this helps collision accuracy. * Bodies are no longer added to a world quadtree, so have had all of their quadtree properties removed such as skipQuadtree, quadTreeIndex, etc. +* Body.drag has been removed. Please use the new Body.friction value instead (which is a number value, not a Point object) +* Body.embedded and Body.wasTouching have been removed as they are no longer required. +* Body.customSeparateX/Y have been removed as you should now use Body.customSeparateCallback. +* Body.maxVelocity defaults have been removed from 10,000 to 2000. +* Body.friction is new and has a default value of 0.1 - you may need to set this to zero depending on the type of game you're making. +* Body.customSeparateCallback allows you to set your own callback when two Bodies need to separate rather than using the built-in method. New features: @@ -87,12 +92,14 @@ New features: * Groups now have an 'alive' property, which can be useful when iterating through child groups with functions like forEachAlive. * Added a new Project Template "Full Screen Mobile" which you can find in the resources folder. Contains html / css / layout needed for a deployed Phaser game. * Body.speed - the current speed of the body. +* Body.angle - the current angle the Body is facing based on its velocity. This is not the same as the Sprite angle that may own the body. * Body.friction - This now replaces Body.drag and provides for a much smoother friction experience. * Body.minBounceVelocity - If a Body has bounce set, this threshold controls if it should rebound or not. Use it to stop 'jittering' on bounds/tiles with super-low velocities. * QuadTree.populate - you can pass it a Group and it'll automatically insert all of the children ready for inspection. * Input.setMoveCallback allows you to set a callback that will be fired each time the activePointer receives a DOM move event. * Math.distancePow(x1,y1,x2,y2,power) returns the distance between two coordinates at the given power. * Physics.collideArray(obj, array) for when you want to collide an object against a number of sprites that aren't all in the same Group. +* Physics.overlapArray(obj, array) for when you want to overlap test an object against a number of sprites that aren't all in the same Group. * Math.reverseAngle - reverses an angle (in radians). * Math.normalizeAngle - normalises an angle, now in radians only. * Math.normalizeLatitude - Normalizes a latitude to the [-90,90] range. diff --git a/examples/tilemaps/sci fly.js b/examples/tilemaps/sci fly.js index e16ea2f48..359bcb0c8 100644 --- a/examples/tilemaps/sci fly.js +++ b/examples/tilemaps/sci fly.js @@ -3,8 +3,8 @@ var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: p function preload() { - game.load.tilemap('level3', 'assets/maps/cybernoid.json', null, Phaser.Tilemap.TILED_JSON); - game.load.image('tiles', 'assets/maps/cybernoid.png', 16, 16); + game.load.tilemap('level3', 'assets/tilemaps/maps/cybernoid.json', null, Phaser.Tilemap.TILED_JSON); + game.load.image('tiles', 'assets/tilemaps/tiles/cybernoid.png', 16, 16); game.load.image('phaser', 'assets/sprites/phaser-ship.png'); game.load.image('chunk', 'assets/sprites/chunk.png'); @@ -29,13 +29,12 @@ function create() { // Basically this sets EVERY SINGLE tile to fully collide on all faces map.setCollisionByExclusion([7, 32, 35, 36, 47]); - // layer.debug = true; + layer.debug = true; layer.resizeWorld(); sprite = game.add.sprite(450, 80, 'phaser'); sprite.anchor.setTo(0.5, 0.5); - sprite.angle = 5; game.camera.follow(sprite); // game.camera.deadzone = new Phaser.Rectangle(160, 160, layer.renderWidth-320, layer.renderHeight-320); @@ -47,7 +46,7 @@ function create() { emitter.makeParticles('chunk'); emitter.minRotation = 0; emitter.maxRotation = 0; - emitter.gravity = 5; + emitter.gravity = 150; emitter.bounce.setTo(0.5, 0.5); game.input.onDown.add(particleBurst, this); diff --git a/examples/wip/2ball.js b/examples/wip/2ball.js index 3b0f884cf..1b75ffa29 100644 --- a/examples/wip/2ball.js +++ b/examples/wip/2ball.js @@ -28,7 +28,7 @@ function create() { var bg = game.add.sprite(0, 0, bmd); bg.body.moves = false; - test7(); + test4(); } @@ -36,7 +36,7 @@ function test7() { game.physics.gravity.y = 200; - sprite = game.add.sprite(300, 300, 'gameboy', 0); + sprite = game.add.sprite(0, 300, 'gameboy', 0); sprite.name = 'red'; sprite.body.collideWorldBounds = true; sprite.body.bounce.setTo(0.8, 0.8); @@ -119,7 +119,7 @@ function stop5() { function test4() { - game.physics.gravity.y = 50; + game.physics.gravity.y = 150; sprite = game.add.sprite(300, 0, 'gameboy', 0); sprite.name = 'red'; @@ -242,15 +242,15 @@ function update() { // game.physics.collide(group, group); - // if (sprite3) - // { - // game.physics.collideArray(sprite, [sprite2, sprite3]); - // game.physics.collide(sprite2, sprite3); - // } - // else - // { - // game.physics.collide(sprite, sprite2); - // } + if (sprite3) + { + game.physics.collideArray(sprite, [sprite2, sprite3]); + game.physics.collide(sprite2, sprite3); + } + else + { + game.physics.collide(sprite, sprite2); + } if (sprite) diff --git a/examples/wip/multiball.js b/examples/wip/multiball.js index d311ff278..84aff62b5 100644 --- a/examples/wip/multiball.js +++ b/examples/wip/multiball.js @@ -23,10 +23,11 @@ function create() { bg.body.moves = false; game.physics.gravity.y = 250; + // game.physics.gravity.x = 250; sprites = game.add.group(); - for (var i = 0; i < 40; i++) + for (var i = 0; i < 20; i++) { var s = sprites.create(game.rnd.integerInRange(100, 700), game.rnd.integerInRange(32, 200), 'ball'); s.body.velocity.x = game.rnd.integerInRange(-400, 400); diff --git a/examples/wip/sci-fly2.js b/examples/wip/sci-fly2.js index e16ea2f48..a30dc004c 100644 --- a/examples/wip/sci-fly2.js +++ b/examples/wip/sci-fly2.js @@ -3,8 +3,8 @@ var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: p function preload() { - game.load.tilemap('level3', 'assets/maps/cybernoid.json', null, Phaser.Tilemap.TILED_JSON); - game.load.image('tiles', 'assets/maps/cybernoid.png', 16, 16); + game.load.tilemap('level3', 'assets/tilemaps/maps/cybernoid.json', null, Phaser.Tilemap.TILED_JSON); + game.load.image('tiles', 'assets/tilemaps/tiles/cybernoid.png', 16, 16); game.load.image('phaser', 'assets/sprites/phaser-ship.png'); game.load.image('chunk', 'assets/sprites/chunk.png'); @@ -29,7 +29,7 @@ function create() { // Basically this sets EVERY SINGLE tile to fully collide on all faces map.setCollisionByExclusion([7, 32, 35, 36, 47]); - // layer.debug = true; + layer.debug = true; layer.resizeWorld(); @@ -47,7 +47,7 @@ function create() { emitter.makeParticles('chunk'); emitter.minRotation = 0; emitter.maxRotation = 0; - emitter.gravity = 5; + emitter.gravity = 150; emitter.bounce.setTo(0.5, 0.5); game.input.onDown.add(particleBurst, this); diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index 357ed5403..a88bcec05 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -32,12 +32,7 @@ Phaser.Physics.Arcade = function (game) { /** * @property {Phaser.Rectangle} bounds - The bounds inside of which the physics world exists. Defaults to match the world bounds. */ - this.bounds = new Phaser.Rectangle(0, 0, game.world.width, game.world.height); - - /** - * @property {number} OVERLAP_BIAS - A value added to the delta values during collision checks. - */ - this.OVERLAP_BIAS = 4; + // this.bounds = new Phaser.Rectangle(0, 0, game.world.width, game.world.height); /** * @property {Phaser.QuadTree} quadTree - The world QuadTree. @@ -60,55 +55,55 @@ Phaser.Physics.Arcade = function (game) { * @property {Phaser.Rectangle} _bounds1 - Internal cache var. * @private */ - this._bounds1 = new Phaser.Rectangle(); + // this._bounds1 = new Phaser.Rectangle(); /** * @property {Phaser.Rectangle} _bounds2 - Internal cache var. * @private */ - this._bounds2 = new Phaser.Rectangle(); + // this._bounds2 = new Phaser.Rectangle(); /** * @property {number} _overlap - Internal cache var. * @private */ - this._overlap = 0; + // this._overlap = 0; /** * @property {number} _maxOverlap - Internal cache var. * @private */ - this._maxOverlap = 0; + // this._maxOverlap = 0; /** * @property {number} _velocity1 - Internal cache var. * @private */ - this._velocity1 = 0; + // this._velocity1 = 0; /** * @property {number} _velocity2 - Internal cache var. * @private */ - this._velocity2 = 0; + // this._velocity2 = 0; /** * @property {number} _newVelocity1 - Internal cache var. * @private */ - this._newVelocity1 = 0; + // this._newVelocity1 = 0; /** * @property {number} _newVelocity2 - Internal cache var. * @private */ - this._newVelocity2 = 0; + // this._newVelocity2 = 0; /** * @property {number} _average - Internal cache var. * @private */ - this._average = 0; + // this._average = 0; /** * @property {Array} _mapData - Internal cache var. @@ -263,45 +258,39 @@ Phaser.Physics.Arcade.prototype = { this._result = false; this._total = 0; - // Only test valid objects - if (object1 && object2 && object1.exists && object2.exists) + this.collideHandler(object1, object2, overlapCallback, processCallback, callbackContext, true); + + return (this._total > 0); + + }, + + /** + * Checks for overlaps between a game object and a array of game objects. You can perform Sprite vs. Sprite, Sprite vs. Group, Group vs. Group, Sprite vs. Tilemap Layer or Group vs. Tilemap Layer checks. + * Unlike collide the objects are NOT automatically separated or have any physics applied, they merely test for overlap results. + * An optional processCallback can be provided. If given this function will be called when two sprites are found to be overlapping, + * giving you the chance to perform additional checks. If the function returns true then the overlap takes place. If it returns false it is skipped. + * 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 overlapCallback to be called. + * + * @method Phaser.Physics.Arcade#overlapArray + * @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. + * @param {array|array|array|array} objectArray - An array of objects to check. Can contain instances of Phaser.Sprite, Phaser.Group, Phaser.Particles.Emitter or Phaser.Tilemap. + * @param {function} [overlapCallback=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. + * @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. + * @param {object} [callbackContext] - The context in which to run the callbacks. + * @returns {boolean} True if a collision occured otherwise false. + */ + overlapArray: function (object1, objectArray, overlapCallback, processCallback, callbackContext) { + + overlapCallback = overlapCallback || null; + processCallback = processCallback || null; + callbackContext = callbackContext || overlapCallback; + + this._result = false; + this._total = 0; + + for (var i = 0, len = objectArray.length; i < len; i++) { - // SPRITES - if (object1.type == Phaser.SPRITE || object1.type == Phaser.TILESPRITE) - { - if (object2.type == Phaser.SPRITE || object2.type == Phaser.TILESPRITE) - { - this.collideSpriteVsSprite(object1, object2, overlapCallback, processCallback, callbackContext, true); - } - else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER) - { - this.collideSpriteVsGroup(object1, object2, overlapCallback, processCallback, callbackContext, true); - } - } - // GROUPS - else if (object1.type == Phaser.GROUP) - { - if (object2.type == Phaser.SPRITE || object2.type == Phaser.TILESPRITE) - { - this.collideSpriteVsGroup(object2, object1, overlapCallback, processCallback, callbackContext, true); - } - else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER) - { - this.collideGroupVsGroup(object1, object2, overlapCallback, processCallback, callbackContext, true); - } - } - // EMITTER - else if (object1.type == Phaser.EMITTER) - { - if (object2.type == Phaser.SPRITE || object2.type == Phaser.TILESPRITE) - { - this.collideSpriteVsGroup(object2, object1, overlapCallback, processCallback, callbackContext, true); - } - else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER) - { - this.collideGroupVsGroup(object1, object2, overlapCallback, processCallback, callbackContext, true); - } - } + this.collideHandler(object1, objectArray[i], overlapCallback, processCallback, callbackContext, true); } return (this._total > 0); @@ -333,7 +322,7 @@ Phaser.Physics.Arcade.prototype = { this._result = false; this._total = 0; - this.collideHandler(object1, object2, collideCallback, processCallback, callbackContext); + this.collideHandler(object1, object2, collideCallback, processCallback, callbackContext, false); return (this._total > 0); @@ -365,7 +354,7 @@ Phaser.Physics.Arcade.prototype = { for (var i = 0, len = objectArray.length; i < len; i++) { - this.collideHandler(object1, objectArray[i], collideCallback, processCallback, callbackContext); + this.collideHandler(object1, objectArray[i], collideCallback, processCallback, callbackContext, false); } return (this._total > 0); @@ -379,16 +368,17 @@ Phaser.Physics.Arcade.prototype = { * @private * @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. * @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. Can also be an array of objects to check. - * @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. - * @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. - * @param {object} [callbackContext] - The context in which to run the callbacks. + * @param {function} collideCallback - 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. + * @param {function} processCallback - 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. + * @param {object} callbackContext - The context in which to run the callbacks. + * @param {boolean} overlapOnly - Just run an overlap or a full collision. */ - collideHandler: function (object1, object2, collideCallback, processCallback, callbackContext) { + collideHandler: function (object1, object2, collideCallback, processCallback, callbackContext, overlapOnly) { // Only collide valid objects if (typeof object2 === 'undefined' && object1.type === Phaser.GROUP) { - this.collideGroupVsSelf(object1, collideCallback, processCallback, callbackContext, false); + this.collideGroupVsSelf(object1, collideCallback, processCallback, callbackContext, overlapOnly); return; } @@ -399,11 +389,11 @@ Phaser.Physics.Arcade.prototype = { { if (object2.type == Phaser.SPRITE || object2.type == Phaser.TILESPRITE) { - this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext, false); + this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER) { - this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext, false); + this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.type == Phaser.TILEMAPLAYER) { @@ -415,11 +405,11 @@ Phaser.Physics.Arcade.prototype = { { if (object2.type == Phaser.SPRITE || object2.type == Phaser.TILESPRITE) { - this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext, false); + this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER) { - this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext, false); + this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.type == Phaser.TILEMAPLAYER) { @@ -443,11 +433,11 @@ Phaser.Physics.Arcade.prototype = { { if (object2.type == Phaser.SPRITE || object2.type == Phaser.TILESPRITE) { - this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext, false); + this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER) { - this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext, false); + this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); } else if (object2.type == Phaser.TILEMAPLAYER) { @@ -688,11 +678,7 @@ Phaser.Physics.Arcade.prototype = { { if (body1.overlap(body2)) { - // console.log('-----------------------------------------------------------------------------'); - // console.log(body1.sprite.name, 'overlaps', body2.sprite.name, 'x', body1.overlapX, 'y', body1.overlapY); - - body1.separate(body2); - return true; + return body1.separate(body2); } } diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index 0b8602700..a3ea2630c 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -125,16 +125,10 @@ Phaser.Physics.Arcade.Body = function (sprite) { this.acceleration = new Phaser.Point(); /** - * @property {number} speed - The speed the Body is traveling. + * @property {number} speed - The speed in pixels per second sq. of the Body. */ this.speed = 0; - /** - * @property {number} minDelta - When a body bounces (off a wall or another body) if the resulting delta is less than minDelta, the velocity is cancelled. - * @default - */ - this.minDelta = 0.09; - /** * @property {number} angle - The angle of the Body in radians. */ @@ -143,9 +137,7 @@ Phaser.Physics.Arcade.Body = function (sprite) { /** * @property {number} minBounceVelocity - The minimum bounce velocity (could just be the bounce value?). */ - // this.minBounceVelocity = 0.2; - - this._debug = 0; + this.minBounceVelocity = 0.5; /** * @property {Phaser.Point} gravity - The gravity applied to the motion of the Body. This works in addition to any gravity set on the world. @@ -167,7 +159,7 @@ Phaser.Physics.Arcade.Body = function (sprite) { * @property {Phaser.Point} maxVelocity - The maximum velocity that the Body can reach. * @default */ - this.maxVelocity = new Phaser.Point(10000, 10000); + this.maxVelocity = new Phaser.Point(2000, 2000); /** * @property {number} angularVelocity - The angular velocity of the Body. @@ -213,12 +205,6 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this.touching = { none: true, up: false, down: false, left: false, right: false }; - /** - * This object is populated with previous touching values from the bodies previous collision. - * @property {object} wasTouching - An object containing previous touching results. - */ - this.wasTouching = { none: true, up: false, down: false, left: false, right: false }; - /** * @property {number} facing - A const reference to the direction the Body is traveling or facing. * @default @@ -256,20 +242,16 @@ Phaser.Physics.Arcade.Body = function (sprite) { this.allowGravity = true; /** - * This flag allows you to disable the custom x separation that takes place by Physics.Arcade.separate. - * Used in combination with your own collision processHandler you can create whatever type of collision response you need. - * @property {boolean} customSeparateX - Use a custom separation system or the built-in one? + * @property {function} customSeparateCallback - If set this callback will be used for Body separation instead of the built-in one. Callback should return true if separated, otherwise false. * @default */ - this.customSeparateX = false; + this.customSeparateCallback = null; /** - * This flag allows you to disable the custom y separation that takes place by Physics.Arcade.separate. - * Used in combination with your own collision processHandler you can create whatever type of collision response you need. - * @property {boolean} customSeparateY - Use a custom separation system or the built-in one? + * @property {object} customSeparateContext - The context in which the customSeparateCallback is called. * @default */ - this.customSeparateY = false; + this.customSeparateContext = null; /** * When this body collides with another, the amount of overlap is stored here. @@ -284,17 +266,11 @@ Phaser.Physics.Arcade.Body = function (sprite) { this.overlapY = 0; /** - * @property {number} friction - The amount of friction this body experiences during motion. Friction reduces velocity until the body comes to a stand-still. + * @property {number} friction - The amount of friction this body experiences during motion. * @default */ this.friction = 0.1; - /** - * If a body is overlapping with another body, but neither of them are moving (maybe they spawned on-top of each other?) this is set to true. - * @property {boolean} embedded - Body embed value. - */ - this.embedded = false; - /** * A Body can be set to collide against the World bounds automatically and rebound back into the World if this is set to true. Otherwise it will leave the World. * @property {boolean} collideWorldBounds - Should the Body collide with the World bounds? @@ -308,6 +284,9 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this.blocked = { up: false, down: false, left: false, right: false }; + /** + * @property {Phaser.Point} blockedPoint - A Point object holding the blocked penetration distance. + */ this.blockedPoint = new Phaser.Point(0, 0); /** @@ -334,10 +313,26 @@ Phaser.Physics.Arcade.Body = function (sprite) { */ this._sy = sprite.scale.y; + /** + * @property {number} _newVelocity1 - Internal cache var. + * @private + */ this._newVelocity1 = 0; + + /** + * @property {number} _newVelocity2 - Internal cache var. + * @private + */ this._newVelocity2 = 0; + + /** + * @property {number} _average - Internal cache var. + * @private + */ this._average = 0; + this._debug = 0; + }; Phaser.Physics.Arcade.Body.prototype = { @@ -378,39 +373,42 @@ Phaser.Physics.Arcade.Body.prototype = { this.preY = (this.sprite.world.y - (this.sprite.anchor.y * this.height)) + this.offset.y; this.preRotation = this.sprite.angle; - this.x = this.preX; - this.y = this.preY; - this.rotation = this.preRotation; - this.blocked.up = false; this.blocked.down = false; this.blocked.left = false; this.blocked.right = false; - // this.embedded = false; + this.x = this.preX; + this.y = this.preY; + this.rotation = this.preRotation; + + this.speed = Math.sqrt(this.velocity.x * this.velocity.x + this.velocity.y * this.velocity.y); + this.angle = Math.atan2(this.velocity.y, this.velocity.x); this._debug++; - if (this.collideWorldBounds) - { - this.checkWorldBounds(true); - } - if (this.moves) { - this.speed = Math.sqrt(this.velocity.x * this.velocity.x + this.velocity.y * this.velocity.y); - this.angle = Math.atan2(this.velocity.y, this.velocity.x); + if (this.collideWorldBounds) + { + this.checkWorldBounds(); + } this.game.physics.updateMotion(this); + + this.applyMotion(); + } - this.checkVelocity(); - - this.applyFriction(); - - this.limitVelocity(); - - console.log(this._debug, 'motion', this.motionVelocity.x, 'x', this.x, 'prex', this.preX); + if (this.deltaX() != 0) + { + this.touching.left = false; + this.touching.right = false; + } + if (this.deltaY() != 0) + { + this.touching.up = false; + this.touching.down = false; } }, @@ -421,7 +419,7 @@ Phaser.Physics.Arcade.Body.prototype = { * @method Phaser.Physics.Arcade#checkWorldBounds * @protected */ - ORIGINALcheckWorldBounds: function () { + checkWorldBounds: function () { this.blockedPoint.setTo(0, 0); @@ -457,413 +455,13 @@ Phaser.Physics.Arcade.Body.prototype = { }, - /** - * Internal method used to check the Body against the World Bounds and move it back into the bounds again. - * Doesn't cause a delta value. - * - * @method Phaser.Physics.Arcade#checkWorldBounds - * @protected - */ - checkWorldBounds: function () { - - if (this.x <= this.game.world.bounds.x) - { - this.x += (this.game.world.bounds.x - this.x); - // this.preX += (this.game.world.bounds.x - this.x); - this.blocked.left = true; - // console.log(this._debug, 'cwl', this.overlapX, this.x, this.game.world.bounds.x); - } - else if (this.right >= this.game.world.bounds.right) - { - this.x -= this.right - this.game.world.bounds.right; - // this.preX -= this.right - this.game.world.bounds.right; - this.blocked.right = true; - // console.log(this._debug, 'cwr', this.overlapX, this.x, this.game.world.bounds.x); - } - - if (this.y <= this.game.world.bounds.y) - { - this.y += this.game.world.bounds.y - this.y; - // this.preY += this.game.world.bounds.y - this.y; - this.blocked.up = true; - // console.log(this._debug, 'cwu', this.overlapY, this.y, this.height, this.bottom, this.game.world.bounds.bottom); - } - else if (this.bottom >= this.game.world.bounds.bottom) - { - this.y -= this.bottom - this.game.world.bounds.bottom; - // this.preY -= this.bottom - this.game.world.bounds.bottom; - this.blocked.down = true; - // console.log(this._debug, 'cwd', this.overlapY, this.y, this.height, this.bottom, this.game.world.bounds.bottom); - } - - }, - - /** - * Internal method. - * - * @method Phaser.Physics.Arcade#applyFriction - * @protected - */ - applyFriction: function () { - - if (this.friction > 0 && this.acceleration.isZero()) - { - if (this.speed > this.friction) - { - this.speed -= this.friction; - } - else - { - this.speed = 0; - } - - this.velocity.x = Math.cos(this.angle) * this.speed; - this.velocity.y = Math.sin(this.angle) * this.speed; - } - - }, - - /* - worldBounce: function () { - - // overlapX/Y values at this point will be penetration into the bounds and DELTA WILL BE ZERO - if (this.blocked.left) - { - this.velocity.x *= -this.bounce.x; - - this._dx = this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); - - if (this._dx > this.minBounceVelocity) - // if (Math.abs(this.velocity.x) > this.minVelocity.x) - { - this.x += this._dx; - this.velocity.x += this.motionVelocity.x; - // console.log(this._debug, 'blocked left', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x); - } - else - { - // Kill it dead :) - this.preX = this.x; // because we don't want any delta from a separation - this.velocity.x = 0; - this.motionVelocity.x = 0; - // console.log(this._debug, 'blocked left KILL', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x); - } - } - else if (this.blocked.right) - { - // Separate - this.x -= this.blockedPoint.x; - // this.x -= this.overlapX; - - this.velocity.x *= -this.bounce.x; - - this._dx = this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); - - if (this._dx < -this.minBounceVelocity) - { - this.x += this._dx; - this.velocity.x += this.motionVelocity.x; - // console.log(this._debug, 'blocked right', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x); - } - else - { - // Kill it dead :) - this.preX = this.x; // because we don't want any delta from a separation - this.velocity.x = 0; - this.motionVelocity.x = 0; - // console.log(this._debug, 'blocked right KILL', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x); - } - } - else - { - this.x += this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); - this.velocity.x += this.motionVelocity.x; - } - - // overlapX/Y values at this point will be penetration into the bounds and DELTA WILL BE ZERO - if (this.blocked.up) - { - // Separate - // this.y += this.overlapY; - this.y += this.blockedPoint.y; - - this.velocity.y *= -this.bounce.y; - - this._dy = this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); - - if (this._dy > this.minBounceVelocity) - // if (Math.abs(this.velocity.y) > this.minVelocity.y) - { - this.y += this._dy; - this.velocity.y += this.motionVelocity.y; - } - else - { - // Kill it dead :) - this.preY = this.y; // because we don't want any delta from a separation - this.velocity.y = 0; - this.motionVelocity.y = 0; - // console.log(this._debug, 'void1', this.velocity.y, 'delta', this.deltaY()); - } - } - else if (this.blocked.down) - { - // Separate - // this.y -= this.overlapY; - this.y -= this.blockedPoint.y; - - this.velocity.y *= -this.bounce.y; - - this._dy = this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); - - if (this._dy < -this.minBounceVelocity) - // if (Math.abs(this.velocity.y) > this.minVelocity.y) - { - this.y += this._dy; - this.velocity.y += this.motionVelocity.y; - // console.log(this._debug, 'rb', this._dy, 'delta', this.deltaY(), 'newy', this.y); - } - else - { - // Kill it dead :) - this.preY = this.y; // because we don't want any delta from a separation - this.velocity.y = 0; - this.motionVelocity.y = 0; - // console.log(this._debug, 'void1', this.velocity.y, 'delta', this.deltaY()); - } - } - else - { - this.y += this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); - this.velocity.y += this.motionVelocity.y; - } - - - }, - */ - - getReboundVelocityX: function () { - - var angle = this.game.math.reverseAngle(this.angle); - var vx = 0; - - if (this.bounce.x > 0) - { - vx = (Math.cos(angle) * this.speed) * this.bounce.x; - } - - return vx; - - }, - - getReboundVelocityY: function () { - - var angle = this.game.math.reverseAngle(this.angle); - var vy = 0; - - if (this.bounce.y > 0) - { - vy = (Math.sin(angle) * this.speed) * this.bounce.y; - } - - return vy; - - }, - - checkVelocity: function () { - - var gx = this.gravity.x + this.game.physics.gravity.x; - var gy = this.gravity.y + this.game.physics.gravity.y; - - var vx = this.getReboundVelocityX(); - var vy = this.getReboundVelocityY(); - - if (gx < 0 && this.blocked.left) - { - // Left pulling gravity - // vx = this.getReboundVelocityX(); - - if (Math.abs(vx) < this.minVelocity.x) - { - this.velocity.x = 0; - } - else - { - this.velocity.x = vx; - } - } - else if (gx > 0 && this.blocked.right) - { - // Right pulling gravity - // vx = this.getReboundVelocityX(); - - if (Math.abs(vx) < this.minVelocity.x) - { - this.velocity.x = 0; - } - else - { - this.velocity.x = vx; - } - } - else if (gx === 0) - { - // No horizontal gravity, but could still need to rebound? - if (Math.abs(vx) < this.minVelocity.x) - { - this.velocity.x = 0; - } - } - - if (gy < 0 && this.blocked.up) - { - // Up pulling gravity - // vy = this.getReboundVelocityY(); - - if (Math.abs(vy) < this.minVelocity.y) - { - this.velocity.y = 0; - } - else - { - this.velocity.y = vy; - } - } - else if (gy > 0 && this.blocked.down) - { - // Down pulling gravity - // vy = this.getReboundVelocityY(); - - if (Math.abs(vy) < this.minVelocity.y) - { - this.velocity.y = 0; - } - else - { - this.velocity.y = vy; - } - } - else if (gy === 0) - { - // No vertical gravity, but could still need to rebound? - if (Math.abs(vy) < this.minVelocity.y) - { - this.velocity.y = 0; - } - } - - }, - - limitVelocity: function (dx, dy) { - - if (this.velocity.x > this.maxVelocity.x) - { - this.velocity.x = this.maxVelocity.x; - } - else if (this.velocity.x < -this.maxVelocity.x) - { - this.velocity.x = -this.maxVelocity.x; - } - - if (this.velocity.y > this.maxVelocity.y) - { - this.velocity.y = this.maxVelocity.y; - } - else if (this.velocity.y < -this.maxVelocity.y) - { - this.velocity.y = -this.maxVelocity.y; - } - - /* - var gx = this.gravity.x + this.game.physics.gravity.x; - var gy = this.gravity.y + this.game.physics.gravity.y; - var stopX = false; - var stopY = false; - - - - - if (dx) - { - if (gx < 0 && this.blocked.left && Math.abs(dx) < this.minDelta) - { - // Left pulling gravity - console.log('gx killed 1', dx, gx); - stopX = true; - } - else if (gx > 0 && this.blocked.right && Math.abs(dx) < this.minDelta) - { - // Right pulling gravity - console.log('gx killed 2', dx, gx); - stopX = true; - } - else if (gx === 0 && this.velocity.x !== 0 && Math.abs(this.velocity.x) < this.minVelocity.x) - { - console.log('gx killed 3', this.velocity.x); - stopX = true; - } - - if (stopX) - { - // this.preX = this.x; - this.velocity.x = 0; - } - } - - if (dy) - { - if (gy > 0 && this.blocked.down && Math.abs(dy) < this.minDelta) - { - // Downward gravity - console.log('gy killed 1', dy, gy); - stopY = true; - } - else if (gy < 0 && this.blocked.up && Math.abs(dy) < this.minDelta) - { - // Upward gravity - console.log('gy killed 2', dy, gy); - stopY = true; - } - else if (gy === 0 && this.velocity.y !== 0 && Math.abs(this.velocity.y) < this.minVelocity.y) - { - console.log('gy killed 3', this.velocity.y); - stopY = true; - } - - if (stopY) - { - // this.preY = this.y; - this.velocity.y = 0; - } - } - - if (!stopX && !stopY) - { - return 0; - } - else if (stopX && !stopY) - { - return 1; - } - else if (!stopX && stopY) - { - return 2; - } - else - { - return 3; - } - */ - - }, - /** * Internal method. * * @method Phaser.Physics.Arcade#applyMotion * @protected */ - ORIGINALapplyMotion: function () { + applyMotion: function () { if (this.friction > 0 && this.acceleration.isZero()) { @@ -880,13 +478,8 @@ Phaser.Physics.Arcade.Body.prototype = { this.velocity.y = Math.sin(this.angle) * this.speed; } - if (this.blocked.isZero()) - { - return; - } - // overlapX/Y values at this point will be penetration into the bounds and DELTA WILL BE ZERO - if (this.blocked.left) + if (this.blocked.left && this.blockedPoint.x > 0) { // Separate // this.x += this.overlapX; @@ -914,7 +507,7 @@ Phaser.Physics.Arcade.Body.prototype = { // console.log(this._debug, 'blocked left KILL', this._dx, 'overlap', this.overlapX, 'delta', this.deltaX(), 'newy', this.x); } } - else if (this.blocked.right) + else if (this.blocked.right && this.blockedPoint.x > 0) { // Separate this.x -= this.blockedPoint.x; @@ -946,7 +539,7 @@ Phaser.Physics.Arcade.Body.prototype = { } // overlapX/Y values at this point will be penetration into the bounds and DELTA WILL BE ZERO - if (this.blocked.up) + if (this.blocked.up && this.blockedPoint.y > 0) { // Separate // this.y += this.overlapY; @@ -971,7 +564,7 @@ Phaser.Physics.Arcade.Body.prototype = { // console.log(this._debug, 'void1', this.velocity.y, 'delta', this.deltaY()); } } - else if (this.blocked.down) + else if (this.blocked.down && this.blockedPoint.y > 0) { // Separate // this.y -= this.overlapY; @@ -1067,18 +660,13 @@ Phaser.Physics.Arcade.Body.prototype = { this.touching.left = false; this.touching.right = false; } - else if (Math.abs(this.overlapX) < Math.abs(this.overlapY)) + else { // Horizontal penetration (as y is larger than x) this.overlapY = 0; this.touching.up = false; this.touching.down = false; } - else - { - // They are identical, so let's revert to checking the delta? - console.log('They are identical, so let\'s revert to checking the delta?'); - } } // overlapX/Y now contains either zero or a positive value containing the overlapping area @@ -1086,58 +674,7 @@ Phaser.Physics.Arcade.Body.prototype = { }, - // Ensure Body is within world limits - worldLimit: function () { - - if (!this.collideWorldBounds) - { - return; - } - - this.checkWorldBounds(); - - if (this.blocked.left && this.blockedPoint.x > 0) - { - this.x += this.blockedPoint.x; - this.preX += this.blockedPoint.x; - } - else if (this.blocked.right && this.blockedPoint.x > 0) - { - this.x -= this.blockedPoint.x; - this.preX -= this.blockedPoint.x; - } - - if (this.blocked.up && this.blockedPoint.y > 0) - { - this.y += this.blockedPoint.y; - this.preY += this.blockedPoint.y; - } - else if (this.blocked.down && this.blockedPoint.y > 0) - { - this.y -= this.blockedPoint.y; - this.preY -= this.blockedPoint.y; - } - - }, - - separateX: function (x, body, nv1, nv2, avg) { - - if (this.immovable || (x < 0 && this.blocked.right) || (x > 0 && this.blocked.left)) - { - body.x -= x; - body.velocity.x = this.velocity.x - body.velocity.x * body.bounce.x; - body.worldLimit(); - } - - // else if (x > 0) - // { - // // right - // } - - - }, - - // The left-hand face of this Body was hit + // The left-hand face of this Body was hit (so it gets moved to the right) // overlapX will be a positive value hitLeft: function (x, body, nv1, nv2, avg) { @@ -1146,7 +683,6 @@ Phaser.Physics.Arcade.Body.prototype = { { // console.log(this.sprite.name, 'hitLeft', 'immovable'); body.x -= x; - if (!body.immovable) body.velocity.x = this.velocity.x - body.velocity.x * body.bounce.x; } else @@ -1157,6 +693,12 @@ Phaser.Physics.Arcade.Body.prototype = { // We take the full separation as what hit is isn't moveable this.x += x; this.velocity.x = body.velocity.x - this.velocity.x * this.bounce.x; + + // Rebound check + if (Math.abs(this.velocity.x) < this.minVelocity.x) + { + this.velocity.x = 0; + } } else { @@ -1167,12 +709,25 @@ Phaser.Physics.Arcade.Body.prototype = { body.x -= x; this.velocity.x = avg + nv1 * this.bounce.x; body.velocity.x = avg + nv2 * body.bounce.x; + + // Rebound check + if (Math.abs(this.velocity.x) < this.minVelocity.x) + { + this.velocity.x = 0; + } } } + // Bounds check + if (this.checkWorldBounds && this.right >= this.game.world.bounds.right) + { + this.blocked.right = true; + this.x -= this.right - this.game.world.bounds.right; + } + }, - // The right-hand face of this Body was hit + // The right-hand face of this Body was hit (so will be moved to the left) // overlapX will be a negative value hitRight: function (x, body, nv1, nv2, avg) { @@ -1191,6 +746,12 @@ Phaser.Physics.Arcade.Body.prototype = { // We take the full separation as what hit is isn't moveable this.x += x; this.velocity.x = body.velocity.x - this.velocity.x * this.bounce.x; + + // Rebound check + if (Math.abs(this.velocity.x) < this.minVelocity.x) + { + this.velocity.x = 0; + } } else { @@ -1201,12 +762,25 @@ Phaser.Physics.Arcade.Body.prototype = { body.x -= x; this.velocity.x = avg + nv1 * this.bounce.x; body.velocity.x = avg + nv2 * body.bounce.x; + + // Rebound check + if (Math.abs(this.velocity.x) < this.minVelocity.x) + { + this.velocity.x = 0; + } } } + // Bounds check + if (this.checkWorldBounds && this.x <= this.game.world.bounds.x) + { + this.blocked.left = true; + this.x += this.game.world.bounds.x - this.x; + } + }, - // The top face of this Body was hit + // The top face of this Body was hit (so it will get pushed down) // overlapY will be a positive value hitUp: function (y, body, nv1, nv2, avg) { @@ -1225,6 +799,12 @@ Phaser.Physics.Arcade.Body.prototype = { // We take the full separation as what hit is isn't moveable this.y += y; this.velocity.y = body.velocity.y - this.velocity.y * this.bounce.y; + + // Rebound check + if (Math.abs(this.velocity.y) < this.minVelocity.y) + { + this.velocity.y = 0; + } } else { @@ -1235,12 +815,25 @@ Phaser.Physics.Arcade.Body.prototype = { body.y -= y; this.velocity.y = avg + nv1 * this.bounce.y; body.velocity.y = avg + nv2 * body.bounce.y; + + // Rebound check + if (Math.abs(this.velocity.y) < this.minVelocity.y) + { + this.velocity.y = 0; + } } } + // Bounds check + if (this.checkWorldBounds && this.bottom >= this.game.world.bounds.bottom) + { + this.blocked.down = true; + this.y -= this.bottom - this.game.world.bounds.bottom; + } + }, - // The bottom face of this Body was hit + // The bottom face of this Body was hit (so it will be pushed up) // overlapY will be a negative value hitDown: function (y, body, nv1, nv2, avg) { @@ -1259,6 +852,12 @@ Phaser.Physics.Arcade.Body.prototype = { // We take the full separation as what hit is isn't moveable this.y += y; this.velocity.y = body.velocity.y - this.velocity.y * this.bounce.y; + + // Rebound check + if (Math.abs(this.velocity.y) < this.minVelocity.y) + { + this.velocity.y = 0; + } } else { @@ -1269,14 +868,30 @@ Phaser.Physics.Arcade.Body.prototype = { body.y -= y; this.velocity.y = avg + nv1 * this.bounce.y; body.velocity.y = avg + nv2 * body.bounce.y; + + // Rebound check + if (Math.abs(this.velocity.y) < this.minVelocity.y) + { + this.velocity.y = 0; + } } } + // Bounds check + if (this.checkWorldBounds && this.y <= this.game.world.bounds.y) + { + this.blocked.up = true; + this.y += this.game.world.bounds.y - this.y; + } + }, separate: function (body) { - // We already know the overlap in this.overlapX/Y + if (this.customSeparateCallback) + { + return this.customSeparateCallback.call(this.customSeparateContext, this, this.overlapX, this.overlapY); + } if (this.overlapX !== 0) { @@ -1313,49 +928,11 @@ Phaser.Physics.Arcade.Body.prototype = { this.hitUp(this.overlapY, body, this._newVelocity1, this._newVelocity2, this._average); } } - - if (this.velocity.x > this.maxVelocity.x) - { - this.velocity.x = this.maxVelocity.x; - } - else if (this.velocity.x < -this.maxVelocity.x) - { - this.velocity.x = -this.maxVelocity.x; - } - - if (this.velocity.y > this.maxVelocity.y) - { - this.velocity.y = this.maxVelocity.y; - } - else if (this.velocity.y < -this.maxVelocity.y) - { - this.velocity.y = -this.maxVelocity.y; - } - - // this.worldLimit(); - // body.worldLimit(); + + return true; }, - /* - // Rebound? - if (rebound && this.speed > 0) - { - var angle = this.game.math.reverseAngle(this.angle); - - if ((this.blocked.left || this.blocked.right) && this.bounce.x > 0) - { - this.velocity.x = (Math.cos(angle) * this.speed) * this.bounce.x; - } - - if ((this.blocked.up || this.blocked.down) && this.bounce.y > 0) - { - this.velocity.y = (Math.sin(angle) * this.speed) * this.bounce.y; - } - } - - */ - /** * Internal method. This is called directly before the sprites are sent to the renderer. * @@ -1366,59 +943,6 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.moves) { - // If there is no velocity, there's nothing to do here? But the hull may have been moved due to collision anyway :-/ - this._dx = this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); - this._dy = this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); - - this.x += this._dx; - this.velocity.x += this.motionVelocity.x; - - this.y += this._dy; - this.velocity.y += this.motionVelocity.y; - - /* - - var result = this.limitVelocity(this._dx, this._dy); - - if (result === 0) - { - // Nothing was stopped - this.x += this._dx; - this.velocity.x += this.motionVelocity.x; - - this.y += this._dy; - this.velocity.y += this.motionVelocity.y; - } - else if (result === 1) - { - // X was stopped - this.y += this._dy; - this.velocity.y += this.motionVelocity.y; - } - else if (result === 2) - { - // Y was stopped - this.x += this._dx; - this.velocity.x += this.motionVelocity.x; - } - else - { - // Both stopped - } - */ - - if (this.collideWorldBounds) - { - this.checkWorldBounds(false); - } - - // this.checkVelocity(); - - // this.limitVelocity(); - - console.log(this._debug, 'delta', this.deltaX(), 'dx', this._dx, 'motion', this.motionVelocity.x, 'vel', this.velocity.x); - -/* if (this.deltaX() < 0) { this.facing = Phaser.LEFT; @@ -1436,8 +960,6 @@ Phaser.Physics.Arcade.Body.prototype = { { this.facing = Phaser.DOWN; } -*/ - this.sprite.x += this.deltaX(); this.sprite.y += this.deltaY(); @@ -1626,59 +1148,3 @@ Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "right", { } }); - -/** -* @name Phaser.Physics.Arcade.Body#speed -* @property {number} speed - -*/ -Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "XXspeed", { - - /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. - * However it does affect the width property. - * @method right - * @return {number} - */ - get: function () { - // Add local cache - return Math.sqrt(this.velocity.x * this.velocity.x + this.velocity.y * this.velocity.y); - }, - - /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. - * However it does affect the width property. - * @method right - * @param {number} value - */ - set: function (value) { - } - -}); - -/** -* @name Phaser.Physics.Arcade.Body#angle -* @property {number} angle - -*/ -Object.defineProperty(Phaser.Physics.Arcade.Body.prototype, "XXangle", { - - /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. - * However it does affect the width property. - * @method right - * @return {number} - */ - get: function () { - // Add local cache - return Math.atan2(this.velocity.y, this.velocity.x); - }, - - /** - * The sum of the x and width properties. Changing the right property of a Rectangle object has no effect on the x, y and height properties. - * However it does affect the width property. - * @method right - * @param {number} value - */ - set: function (value) { - } - -});