From c3183dcea9a231fdf8fb7bbfc4846fadec45a37f Mon Sep 17 00:00:00 2001 From: photonstorm Date: Fri, 3 Jan 2014 04:50:31 +0000 Subject: [PATCH] Angular Physics re-implemented, most tests now working as expected. --- examples/physics/launcher.js | 19 +++-- examples/wip/physics-motion.js | 46 +++++++++--- src/physics/arcade/ArcadePhysics.js | 110 ++++++++++++---------------- src/physics/arcade/Body.js | 82 +++++++++++++++++---- src/utils/Debug.js | 7 +- 5 files changed, 164 insertions(+), 100 deletions(-) diff --git a/examples/physics/launcher.js b/examples/physics/launcher.js index 2f48e2e0..8616f37a 100644 --- a/examples/physics/launcher.js +++ b/examples/physics/launcher.js @@ -19,7 +19,7 @@ var launchVelocity = 0; function create() { // set global gravity - game.physics.gravity.setTo(0,8); + game.physics.gravity.y = 100; game.stage.backgroundColor = '#0072bc'; var graphics = game.add.graphics(0,0); @@ -42,7 +42,7 @@ function create() { ball.anchor.setTo(0.5, 0.5); ball.body.collideWorldBounds = true; ball.body.bounce.setTo(0.9, 0.9); - ball.body.drag.setTo(50, 50); + ball.body.drag.setTo(10, 0); // Enable input. ball.inputEnabled = true; @@ -66,10 +66,10 @@ function launch() { arrow.alpha = 0; analog.alpha = 0; - Xvector = (arrow.x - ball.x) * 4.1; - Yvector = (arrow.y - ball.y) * 4.1; + Xvector = (arrow.x - ball.x) * 3; + Yvector = (arrow.y - ball.y) * 3; ball.body.allowGravity = true; - ball.body.velocity.setTo(Xvector,Yvector); + ball.body.velocity.setTo(Xvector, Yvector); } @@ -85,7 +85,7 @@ function update() { arrow.alpha = 1; analog.alpha = 0.5; - analog.rotation = arrow.rotation - 3.14/2; + analog.rotation = arrow.rotation - 3.14 / 2; analog.height = game.physics.distanceToPointer(arrow); launchVelocity = analog.height; } @@ -95,7 +95,10 @@ function update() { function render() { game.debug.renderText("Drag the ball and release to launch", 32, 32); - game.debug.renderSpriteInfo(ball, 32, 64); - game.debug.renderText("Launch Velocity: " + parseInt(launchVelocity), 32, 250); + + game.debug.renderBodyInfo(ball, 32, 64); + + // game.debug.renderSpriteInfo(ball, 32, 64); + // game.debug.renderText("Launch Velocity: " + parseInt(launchVelocity), 32, 250); } diff --git a/examples/wip/physics-motion.js b/examples/wip/physics-motion.js index 8494df67..1701406f 100644 --- a/examples/wip/physics-motion.js +++ b/examples/wip/physics-motion.js @@ -4,6 +4,7 @@ var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: function preload() { game.load.image('chunk', 'assets/sprites/chunk.png'); + game.load.image('arrow', 'assets/sprites/asteroids_ship.png'); } @@ -12,25 +13,36 @@ var bmd; function create() { - game.stage.backgroundColor = '#2384e7'; + game.stage.backgroundColor = '#124184'; bmd = game.add.bitmapData(800, 600); bmd.fillStyle('#ffffff'); - game.add.sprite(0, 0, bmd); + var bg = game.add.sprite(0, 0, bmd); + bg.body.moves = false; - sprite = game.add.sprite(732, 0, 'chunk'); + game.physics.gravity.y = 100; + + // sprite = game.add.sprite(732, 0, 'chunk'); + + // sprite = game.add.sprite(32, 450, 'chunk'); + sprite = game.add.sprite(32, 450, 'arrow'); + sprite.anchor.setTo(0.5, 0.5); sprite.body.collideWorldBounds = true; - sprite.body.bounce.setTo(0.5, 0.5); + // sprite.body.bounce.setTo(0.5, 0.5); + sprite.body.bounce.setTo(0.8, 0.8); + //sprite.body.drag.setTo(0, -20); - sprite.body.drag.setTo(5, 0); + sprite.body.drag.setTo(10, 10); + // sprite.body.sleepMin.setTo(-50, -20); // sprite.body.sleepMax.setTo(50, 20); // sprite.body.sleepDuration = 1000; - sprite.body.sleepMin.setTo(0, -5); - sprite.body.sleepMax.setTo(0, 5); - sprite.body.sleepDuration = 1000; + sprite.body.sleepMin.setTo(-5, -5); + sprite.body.sleepMax.setTo(5, 5); + sprite.body.sleepDuration = 500; + // sprite.body.canSleep = false; game.input.onDown.add(launch, this); @@ -38,20 +50,32 @@ function create() { function launch() { - sprite.body.velocity.setTo(-100, 300); + // up and to the right + sprite.body.velocity.setTo(200, -300); - sprite.body.gravity.setTo(0, -100); + // sprite.body.velocity.setTo(-100, 300); + // sprite.body.gravity.setTo(0, -100); + + // sprite.body.gravity.setTo(0, -100); } function update() { + sprite.rotation = sprite.body.angle; + + // console.log(sprite.body.velocity.x); + + bmd.fillStyle('#ffffff'); bmd.fillRect(sprite.x, sprite.y, 2, 2); + // bmd.fillStyle('#ff0000'); + // bmd.fillRect(sprite.body.x, sprite.body.y, 2, 2); + } function render() { - game.debug.renderBodyInfo(sprite, 16, 16); + game.debug.renderBodyInfo(sprite, 16, 24); } diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index 25b06ac5..1640ea12 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -166,8 +166,7 @@ Phaser.Physics.Arcade.prototype = { * * @method Phaser.Physics.Arcade#updateMotion * @param {Phaser.Physics.Arcade.Body} The Body object to be updated. - */ - OLDupdateMotion: function (body) { + updateMotion: function (body) { // If you're wondering why the velocity is halved and applied twice, read this: http://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html @@ -208,6 +207,7 @@ Phaser.Physics.Arcade.prototype = { // body.velocity.y += this._velocityDelta; }, + */ /** * Called automatically by a Physics body, it updates all motion related values on the Body. @@ -221,8 +221,8 @@ Phaser.Physics.Arcade.prototype = { if (body.allowGravity) { - this._gravityX = (this.gravity.x + body.gravity.x) * this.game.time.physicsElapsed; - this._gravityY = (this.gravity.y + body.gravity.y) * this.game.time.physicsElapsed; + this._gravityX = (this.gravity.x + body.gravity.x); + this._gravityY = (this.gravity.y + body.gravity.y); } else { @@ -231,27 +231,46 @@ Phaser.Physics.Arcade.prototype = { } // Rotation - // this._velocityDelta = (this.computeVelocity(body, body.angularVelocity, body.angularAcceleration, body.angularDrag, body.maxAngular, 0) - body.angularVelocity) * 0.5; - // body.angularVelocity += this._velocityDelta; - // body.rotation += (body.angularVelocity * this.game.time.physicsElapsed); - // body.angularVelocity += this._velocityDelta; + if (body.allowRotation) + { + this._velocityDelta = body.angularAcceleration * this.game.time.physicsElapsed; + + if (body.angularDrag !== 0 && body.angularAcceleration === 0) + { + this._drag = body.angularDrag * this.game.time.physicsElapsed; + + if (body.angularVelocity > 0) + { + body.angularVelocity -= this._drag; + } + else if (body.angularVelocity < 0) + { + body.angularVelocity += this._drag; + } + } + + body.rotation += this.game.time.physicsElapsed * (body.angularVelocity + this._velocityDelta / 2); + body.angularVelocity += this._velocityDelta; + + if (body.angularVelocity > body.maxAngular) + { + body.angularVelocity = body.maxAngular; + } + else if (body.angularVelocity < -body.maxAngular) + { + body.angularVelocity = -body.maxAngular; + } + } // velocity = velocity + gravity*delta_time/2 // position = position + velocity*delta_time // velocity = velocity + gravity*delta_time/2 - - body.velocity.x += this._gravityX; - body.velocity.y += this._gravityY; - - body.motionVelocity.x = body.acceleration.x * this.game.time.physicsElapsed; - body.motionVelocity.y = body.acceleration.y * this.game.time.physicsElapsed; - // temp = acc*dt // pos = pos + dt*(vel + temp/2) // vel = vel + temp - // body.motionVelocity.x = (body.acceleration.x + this._gravityX) * this.game.time.physicsElapsed; - // body.motionVelocity.y = (body.acceleration.y + this._gravityY) * this.game.time.physicsElapsed; + body.motionVelocity.x = (body.acceleration.x + this._gravityX) * this.game.time.physicsElapsed; + body.motionVelocity.y = (body.acceleration.y + this._gravityY) * this.game.time.physicsElapsed; }, @@ -266,64 +285,30 @@ Phaser.Physics.Arcade.prototype = { * @param {number} [max=10000] - An absolute value cap for the velocity. * @param {number} gravity - The acceleration due to gravity. Gravity will not induce drag. * @return {number} The altered Velocity value. - */ computeVelocity: function (body, velocity, acceleration, drag, max, gravity) { max = max || 10000; - velocity += (acceleration + gravity) * this.game.time.physicsElapsed; - - if (acceleration === 0 && drag !== 0) - { - this._drag = drag; - - if (velocity - this._drag > 0) - { - velocity -= this._drag; - } - else if (velocity + this._drag < 0) - { - velocity += this._drag; - } - else - { - velocity = 0; - } - } - - return velocity; - - }, - - /** - * A tween-like function that takes a starting velocity and some other factors and returns an altered velocity. - * - * @method Phaser.Physics.Arcade#computeVelocity - * @param {Phaser.Physics.Arcade.Body} body - The Body object to be updated. - * @param {number} velocity - Any component of velocity (e.g. 20). - * @param {number} acceleration - Rate at which the velocity is changing. - * @param {number} drag - Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set. - * @param {number} [max=10000] - An absolute value cap for the velocity. - * @param {number} gravity - The acceleration due to gravity. Gravity will not induce drag. - * @return {number} The altered Velocity value. - */ - OLDcomputeVelocity: function (body, velocity, acceleration, drag, max, gravity) { - - max = max || 10000; - - velocity += (acceleration + gravity) * this.game.time.physicsElapsed; + // velocity = (acceleration + gravity) * this.game.time.physicsElapsed; + // velocity += (acceleration + gravity) * this.game.time.physicsElapsed; + velocity = (acceleration + gravity); if (acceleration === 0 && drag !== 0) { this._drag = drag * this.game.time.physicsElapsed; + // this._drag = drag; + // if (velocity - drag > 0) if (velocity - this._drag > 0) { - velocity -= this._drag; + // velocity += this._drag; + velocity -= drag; } - else if (velocity + this._drag < 0) + // else if (velocity - drag < 0) + else if (velocity - this._drag < 0) { - velocity += this._drag; + // velocity -= this._drag; + velocity -= drag; } else { @@ -343,6 +328,7 @@ Phaser.Physics.Arcade.prototype = { return velocity; }, + */ /** * Called automatically by the core game loop. diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index b1e6dff5..7dfe206d 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -308,13 +308,15 @@ Phaser.Physics.Arcade.Body = function (sprite) { * @default */ this.sleeping = false; - this.canSleep = false; + this.canSleep = true; this.sleepMin = new Phaser.Point(-20, -20); this.sleepMax = new Phaser.Point(20, 20); this.sleepDuration = 2000; // ms this._sleepTimer = 0; // ms this._drag = 0; this._debug = 0; + // this.friction = 0.99; + // this._debug = 0; /** * 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. @@ -415,10 +417,7 @@ Phaser.Physics.Arcade.Body.prototype = { { if (this._sleepTimer >= this.sleepDuration) { - console.log('sleeping true'); this.sleeping = true; - // this.preX = this.x; - // this.preY = this.y; } else { @@ -451,7 +450,43 @@ Phaser.Physics.Arcade.Body.prototype = { applyMotion: function () { - // Apply drag + // Apply drag - this should be proportionally applied, not linearly like below + if (this.drag.x !== 0 && this.acceleration.x === 0) + { + this._drag = this.drag.x * this.game.time.physicsElapsed; + + if (this.velocity.x > 0) + { + this.velocity.x -= this._drag; + } + else if (this.velocity.x < 0) + { + this.velocity.x += this._drag; + } + } + + if (this.drag.y !== 0 && this.acceleration.y === 0) + { + this._drag = this.drag.y * this.game.time.physicsElapsed; + + if (this.velocity.y > 0) + { + this.velocity.y -= this._drag; + } + else if (this.velocity.y < 0) + { + this.velocity.y += this._drag; + } + } + + this.x += this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); + this.velocity.x += this.motionVelocity.x; + + this.y += this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); + this.velocity.y += this.motionVelocity.y; + + + /* if (this.drag.x !== 0 && this.acceleration.x === 0) { this._drag = this.drag.x * this.game.time.physicsElapsed; @@ -459,19 +494,21 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.velocity.x - this._drag > 0) { this.velocity.x -= this._drag; + this.x += this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); + this.velocity.x += this.motionVelocity.x; } else if (this.velocity.x + this.drag.x < 0) { this.velocity.x += this._drag; + this.x += this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); + this.velocity.x += this.motionVelocity.x; } else { this.velocity.x = 0; + // this.preX = this.x; // this.motionVelocity.x = 0; } - - this.x += this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2); - this.velocity.x += this.motionVelocity.x; } else { @@ -486,25 +523,28 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.velocity.y - this._drag > 0) { this.velocity.y -= this._drag; + this.y += this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); + this.velocity.y += this.motionVelocity.y; } else if (this.velocity.y + this.drag.y < 0) { this.velocity.y += this._drag; + this.y += this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); + this.velocity.y += this.motionVelocity.y; } else { this.velocity.y = 0; + // this.preY = this.y; // this.motionVelocity.y = 0; } - - this.y += this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); - this.velocity.y += this.motionVelocity.y; } else { this.y += this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2); this.velocity.y += this.motionVelocity.y; } + */ if (this.velocity.x > this.maxVelocity.x) { @@ -518,6 +558,16 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.collideWorldBounds) { this.checkWorldBounds(); + + if (this.blocked.left || this.blocked.right) + { + // this.preX = this.x; + } + + if (this.blocked.up || this.blocked.down) + { + // this.preX = this.x; + } } }, @@ -556,7 +606,7 @@ Phaser.Physics.Arcade.Body.prototype = { if (this.collideWorldBounds) { - this.checkWorldBounds(); + // this.checkWorldBounds(); } this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight); @@ -587,14 +637,14 @@ Phaser.Physics.Arcade.Body.prototype = { this.blocked.left = true; this.x = this.game.world.bounds.x; this.velocity.x *= -this.bounce.x; - console.log(this._debug, 'hit left', vx,'to',this.velocity.x); + // console.log(this._debug, 'hit left', vx,'to',this.velocity.x); } else if (this.right > this.game.world.bounds.right) { this.blocked.right = true; this.x = this.game.world.bounds.right - this.width; this.velocity.x *= -this.bounce.x; - console.log(this._debug, 'hit right', vx,'to',this.velocity.x); + // console.log(this._debug, 'hit right', vx,'to',this.velocity.x); } if (this.y < this.game.world.bounds.y) @@ -602,14 +652,14 @@ Phaser.Physics.Arcade.Body.prototype = { this.blocked.up = true; this.y = this.game.world.bounds.y; this.velocity.y *= -this.bounce.y; - console.log(this._debug, 'hit top', vy,'to',this.velocity.y); + // console.log(this._debug, 'hit top', vy,'to',this.velocity.y); } else if (this.bottom > this.game.world.bounds.bottom) { this.blocked.down = true; this.y = this.game.world.bounds.bottom - this.height; this.velocity.y *= -this.bounce.y; - console.log(this._debug, 'hit bottom', vy,'to',this.velocity.y); + // console.log(this._debug, 'hit bottom', vy,'to',this.velocity.y); } }, diff --git a/src/utils/Debug.js b/src/utils/Debug.js index 30087e92..880bd293 100644 --- a/src/utils/Debug.js +++ b/src/utils/Debug.js @@ -454,15 +454,16 @@ Phaser.Utils.Debug.prototype = { this.start(x, y, color, 220); - this.splitline('Width: ' + sprite.width, 'Height: ' + sprite.height); - this.splitline('x: ' + sprite.body.x.toFixed(2), 'y: ' + sprite.body.y.toFixed(2)); + this.splitline('x: ' + sprite.body.x.toFixed(2), 'y: ' + sprite.body.y.toFixed(2), 'width: ' + sprite.width, 'height: ' + sprite.height); this.splitline('speed: ' + sprite.body.speed.toFixed(2), 'angle: ' + sprite.body.angle.toFixed(2)); - this.splitline('old x: ' + sprite.body.preX.toFixed(2), 'y: ' + sprite.body.preY.toFixed(2)); + //this.splitline('old x: ' + sprite.body.preX.toFixed(2), 'y: ' + sprite.body.preY.toFixed(2)); this.splitline('drag x: ' + sprite.body.drag.x, 'y: ' + sprite.body.drag.y); this.splitline('gravity x: ' + sprite.body.gravity.x, 'y: ' + sprite.body.gravity.y); + this.splitline('world gravity x: ' + this.game.physics.gravity.x, 'y: ' + this.game.physics.gravity.y); this.splitline('acceleration x: ' + sprite.body.acceleration.x.toFixed(2), 'y: ' + sprite.body.acceleration.y.toFixed(2)); this.splitline('velocity x: ' + sprite.body.velocity.x.toFixed(2), 'y: ' + sprite.body.velocity.y.toFixed(2)); this.splitline('motion x: ' + sprite.body.motionVelocity.x.toFixed(2), 'y: ' + sprite.body.motionVelocity.y.toFixed(2)); + this.splitline('bounce x: ' + sprite.body.bounce.x.toFixed(2), 'y: ' + sprite.body.bounce.y.toFixed(2)); this.splitline('sleeping: ' + sprite.body.sleeping, 'sleepTimer: ' + sprite.body._sleepTimer.toFixed(2)); this.splitline('sleepMin x: ' + sprite.body.sleepMin.x, 'y: ' + sprite.body.sleepMin.y); this.splitline('sleepMax x: ' + sprite.body.sleepMax.x, 'y: ' + sprite.body.sleepMax.y);