UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

416 lines (371 loc) 11.4 kB
/** * @author Richard Davey <rich@phaser.io> * @copyright 2013-2025 Phaser Studio Inc. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ var body1; var body2; var body1Pushable; var body2Pushable; var body1MassImpact; var body2MassImpact; var body1FullImpact; var body2FullImpact; var body1MovingUp; var body1MovingDown; var body1Stationary; var body2MovingUp; var body2MovingDown; var body2Stationary; var body1OnTop; var body2OnTop; var overlap; /** * Sets all of the local processing values and calculates the velocity exchanges. * * Then runs `BlockCheck` and returns the value from it. * * This method is called by `Phaser.Physics.Arcade.SeparateY` and should not be * called directly. * * @function Phaser.Physics.Arcade.ProcessY.Set * @ignore * @since 3.50.0 * * @param {Phaser.Physics.Arcade.Body} b1 - The first Body to separate. * @param {Phaser.Physics.Arcade.Body} b2 - The second Body to separate. * @param {number} ov - The overlap value. * * @return {number} The BlockCheck result. 0 = not blocked. 1 = Body 1 blocked. 2 = Body 2 blocked. */ var Set = function (b1, b2, ov) { body1 = b1; body2 = b2; var v1 = body1.velocity.y; var v2 = body2.velocity.y; body1Pushable = body1.pushable; body1MovingUp = body1._dy < 0; body1MovingDown = body1._dy > 0; body1Stationary = body1._dy === 0; body1OnTop = Math.abs(body1.bottom - body2.y) <= Math.abs(body2.bottom - body1.y); body1FullImpact = v2 - v1 * body1.bounce.y; body2Pushable = body2.pushable; body2MovingUp = body2._dy < 0; body2MovingDown = body2._dy > 0; body2Stationary = body2._dy === 0; body2OnTop = !body1OnTop; body2FullImpact = v1 - v2 * body2.bounce.y; // negative delta = up, positive delta = down (inc. gravity) overlap = Math.abs(ov); return BlockCheck(); }; /** * Blocked Direction checks, because it doesn't matter if an object can be pushed * or not, blocked is blocked. * * @function Phaser.Physics.Arcade.ProcessY.BlockCheck * @ignore * @since 3.50.0 * * @return {number} The BlockCheck result. 0 = not blocked. 1 = Body 1 blocked. 2 = Body 2 blocked. */ var BlockCheck = function () { // Body1 is moving down and Body2 is blocked from going down any further if (body1MovingDown && body1OnTop && body2.blocked.down) { body1.processY(-overlap, body1FullImpact, false, true); return 1; } // Body1 is moving up and Body2 is blocked from going up any further if (body1MovingUp && body2OnTop && body2.blocked.up) { body1.processY(overlap, body1FullImpact, true); return 1; } // Body2 is moving down and Body1 is blocked from going down any further if (body2MovingDown && body2OnTop && body1.blocked.down) { body2.processY(-overlap, body2FullImpact, false, true); return 2; } // Body2 is moving up and Body1 is blocked from going up any further if (body2MovingUp && body1OnTop && body1.blocked.up) { body2.processY(overlap, body2FullImpact, true); return 2; } return 0; }; /** * The main check function. Runs through one of the four possible tests and returns the results. * * @function Phaser.Physics.Arcade.ProcessY.Check * @ignore * @since 3.50.0 * * @return {boolean} `true` if a check passed, otherwise `false`. */ var Check = function () { var v1 = body1.velocity.y; var v2 = body2.velocity.y; var nv1 = Math.sqrt((v2 * v2 * body2.mass) / body1.mass) * ((v2 > 0) ? 1 : -1); var nv2 = Math.sqrt((v1 * v1 * body1.mass) / body2.mass) * ((v1 > 0) ? 1 : -1); var avg = (nv1 + nv2) * 0.5; nv1 -= avg; nv2 -= avg; body1MassImpact = avg + nv1 * body1.bounce.y; body2MassImpact = avg + nv2 * body2.bounce.y; // Body1 hits Body2 on the bottom side if (body1MovingUp && body2OnTop) { return Run(0); } // Body2 hits Body1 on the bottom side if (body2MovingUp && body1OnTop) { return Run(1); } // Body1 hits Body2 on the top side if (body1MovingDown && body1OnTop) { return Run(2); } // Body2 hits Body1 on the top side if (body2MovingDown && body2OnTop) { return Run(3); } return false; }; /** * The main check function. Runs through one of the four possible tests and returns the results. * * @function Phaser.Physics.Arcade.ProcessY.Run * @ignore * @since 3.50.0 * * @param {number} side - The side to test. As passed in by the `Check` function. * * @return {boolean} Always returns `true`. */ var Run = function (side) { if (body1Pushable && body2Pushable) { // Both pushable, or both moving at the same time, so equal rebound overlap *= 0.5; if (side === 0 || side === 3) { // body1MovingUp && body2OnTop // body2MovingDown && body2OnTop body1.processY(overlap, body1MassImpact); body2.processY(-overlap, body2MassImpact); } else { // body2MovingUp && body1OnTop // body1MovingDown && body1OnTop body1.processY(-overlap, body1MassImpact); body2.processY(overlap, body2MassImpact); } } else if (body1Pushable && !body2Pushable) { // Body1 pushable, Body2 not if (side === 0 || side === 3) { // body1MovingUp && body2OnTop // body2MovingDown && body2OnTop body1.processY(overlap, body1FullImpact, true); } else { // body2MovingUp && body1OnTop // body1MovingDown && body1OnTop body1.processY(-overlap, body1FullImpact, false, true); } } else if (!body1Pushable && body2Pushable) { // Body2 pushable, Body1 not if (side === 0 || side === 3) { // body1MovingUp && body2OnTop // body2MovingDown && body2OnTop body2.processY(-overlap, body2FullImpact, false, true); } else { // body2MovingUp && body1OnTop // body1MovingDown && body1OnTop body2.processY(overlap, body2FullImpact, true); } } else { // Neither body is pushable, so base it on movement var halfOverlap = overlap * 0.5; if (side === 0) { // body1MovingUp && body2OnTop if (body2Stationary) { body1.processY(overlap, 0, true); body2.processY(0, null, false, true); } else if (body2MovingDown) { body1.processY(halfOverlap, 0, true); body2.processY(-halfOverlap, 0, false, true); } else { // Body2 moving same direction as Body1 body1.processY(halfOverlap, body2.velocity.y, true); body2.processY(-halfOverlap, null, false, true); } } else if (side === 1) { // body2MovingUp && body1OnTop if (body1Stationary) { body1.processY(0, null, false, true); body2.processY(overlap, 0, true); } else if (body1MovingDown) { body1.processY(-halfOverlap, 0, false, true); body2.processY(halfOverlap, 0, true); } else { // Body1 moving same direction as Body2 body1.processY(-halfOverlap, null, false, true); body2.processY(halfOverlap, body1.velocity.y, true); } } else if (side === 2) { // body1MovingDown && body1OnTop if (body2Stationary) { body1.processY(-overlap, 0, false, true); body2.processY(0, null, true); } else if (body2MovingUp) { body1.processY(-halfOverlap, 0, false, true); body2.processY(halfOverlap, 0, true); } else { // Body2 moving same direction as Body1 body1.processY(-halfOverlap, body2.velocity.y, false, true); body2.processY(halfOverlap, null, true); } } else if (side === 3) { // body2MovingDown && body2OnTop if (body1Stationary) { body1.processY(0, null, true); body2.processY(-overlap, 0, false, true); } else if (body1MovingUp) { body1.processY(halfOverlap, 0, true); body2.processY(-halfOverlap, 0, false, true); } else { // Body1 moving same direction as Body2 body1.processY(halfOverlap, body2.velocity.y, true); body2.processY(-halfOverlap, null, false, true); } } } return true; }; /** * This function is run when Body1 is Immovable and Body2 is not. * * @function Phaser.Physics.Arcade.ProcessY.RunImmovableBody1 * @ignore * @since 3.50.0 * * @param {number} blockedState - The block state value. */ var RunImmovableBody1 = function (blockedState) { if (blockedState === 1) { // But Body2 cannot go anywhere either, so we cancel out velocity // Separation happened in the block check body2.velocity.y = 0; } else if (body1OnTop) { body2.processY(overlap, body2FullImpact, true); } else { body2.processY(-overlap, body2FullImpact, false, true); } // This is special case code that handles things like horizontally moving platforms you can ride if (body1.moves) { var body1Distance = body1.directControl ? (body1.x - body1.autoFrame.x) : (body1.x - body1.prev.x); body2.x += body1Distance * body1.friction.x; body2._dx = body2.x - body2.prev.x; } }; /** * This function is run when Body2 is Immovable and Body1 is not. * * @function Phaser.Physics.Arcade.ProcessY.RunImmovableBody2 * @ignore * @since 3.50.0 * * @param {number} blockedState - The block state value. */ var RunImmovableBody2 = function (blockedState) { if (blockedState === 2) { // But Body1 cannot go anywhere either, so we cancel out velocity // Separation happened in the block check body1.velocity.y = 0; } else if (body2OnTop) { body1.processY(overlap, body1FullImpact, true); } else { body1.processY(-overlap, body1FullImpact, false, true); } // This is special case code that handles things like horizontally moving platforms you can ride if (body2.moves) { var body2Distance = body2.directControl ? (body2.x - body2.autoFrame.x) : (body2.x - body2.prev.x); body1.x += body2Distance * body2.friction.x; body1._dx = body1.x - body1.prev.x; } }; /** * @namespace Phaser.Physics.Arcade.ProcessY * @ignore */ module.exports = { BlockCheck: BlockCheck, Check: Check, Set: Set, Run: Run, RunImmovableBody1: RunImmovableBody1, RunImmovableBody2: RunImmovableBody2 };