diff --git a/src/body/Body.js b/src/body/Body.js index 8e135f20..2a95014e 100644 --- a/src/body/Body.js +++ b/src/body/Body.js @@ -456,15 +456,26 @@ var Axes = require('../geometry/Axes'); }; /** - * Sets the position of the body instantly. Velocity, angle, force etc. are unchanged. + * Sets the position of the body instantly. By default velocity, angle, force etc. are unchanged. + * If `updateVelocity` is `true` then velocity is inferred from the change in position. * @method setPosition * @param {body} body * @param {vector} position + * @param {boolean} [updateVelocity=false] */ - Body.setPosition = function(body, position) { + Body.setPosition = function(body, position, updateVelocity) { var delta = Vector.sub(position, body.position); + + if (updateVelocity) { + body.positionPrev.x = body.position.x; + body.positionPrev.y = body.position.y; + body.velocity.x = delta.x; + body.velocity.y = delta.y; + body.speed = Vector.magnitude(delta); + } else { body.positionPrev.x += delta.x; body.positionPrev.y += delta.y; + } for (var i = 0; i < body.parts.length; i++) { var part = body.parts[i]; @@ -476,14 +487,23 @@ var Axes = require('../geometry/Axes'); }; /** - * Sets the angle of the body instantly. Angular velocity, position, force etc. are unchanged. + * Sets the angle of the body instantly. By default angular velocity, position, force etc. are unchanged. + * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle. * @method setAngle * @param {body} body * @param {number} angle + * @param {boolean} [updateVelocity=false] */ - Body.setAngle = function(body, angle) { + Body.setAngle = function(body, angle, updateVelocity) { var delta = angle - body.angle; + + if (updateVelocity) { + body.anglePrev = body.angle; + body.angularVelocity = delta; + body.angularSpeed = Math.abs(delta); + } else { body.anglePrev += delta; + } for (var i = 0; i < body.parts.length; i++) { var part = body.parts[i]; @@ -504,13 +524,49 @@ var Axes = require('../geometry/Axes'); * @param {vector} velocity */ Body.setVelocity = function(body, velocity) { - body.positionPrev.x = body.position.x - velocity.x; - body.positionPrev.y = body.position.y - velocity.y; - body.velocity.x = velocity.x; - body.velocity.y = velocity.y; + var timeScale = body.deltaTime / Common._timeUnit; + body.positionPrev.x = body.position.x - velocity.x * timeScale; + body.positionPrev.y = body.position.y - velocity.y * timeScale; + body.velocity.x = velocity.x * timeScale; + body.velocity.y = velocity.y * timeScale; body.speed = Vector.magnitude(body.velocity); }; + /** + * Gets the linear velocity of the body. Use this instead of the internal `body.velocity`. + * @method getVelocity + * @param {body} body + * @return {vector} velocity + */ + Body.getVelocity = function(body) { + var timeScale = Common._timeUnit / body.deltaTime; + + return { + x: (body.position.x - body.positionPrev.x) * timeScale, + y: (body.position.y - body.positionPrev.y) * timeScale + }; + }; + + /** + * Gets the linear speed the body. Use this instead of the internal `body.speed`. + * @method getSpeed + * @param {body} body + * @return {number} speed + */ + Body.getSpeed = function(body) { + return Vector.magnitude(Body.getVelocity(body)); + }; + + /** + * Sets the linear speed of the body. Use this instead of the internal `body.speed`. + * @method setSpeed + * @param {body} body + * @param {number} speed + */ + Body.setSpeed = function(body, speed) { + Body.setVelocity(body, Vector.mult(Vector.normalise(Body.getVelocity(body)), speed)); + }; + /** * Sets the angular velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`. * @method setAngularVelocity @@ -518,31 +574,66 @@ var Axes = require('../geometry/Axes'); * @param {number} velocity */ Body.setAngularVelocity = function(body, velocity) { - body.anglePrev = body.angle - velocity; - body.angularVelocity = velocity; + var timeScale = body.deltaTime / Common._timeUnit; + body.anglePrev = body.angle - velocity * timeScale; + body.angularVelocity = velocity * timeScale; body.angularSpeed = Math.abs(body.angularVelocity); }; /** - * Moves a body by a given vector relative to its current position, without imparting any velocity. + * Gets the angular velocity of the body. Use this instead of the internal `body.angularVelocity`. + * @method getAngularVelocity + * @param {body} body + * @return {number} angular velocity + */ + Body.getAngularVelocity = function(body) { + return (body.angle - body.anglePrev) * Common._timeUnit / body.deltaTime; + }; + + /** + * Gets the angular speed of the body. Use this instead of the internal `body.angularSpeed`. + * @method getAngularSpeed + * @param {body} body + * @return {number} angular speed + */ + Body.getAngularSpeed = function(body) { + return Math.abs(Body.getAngularVelocity(body)); + }; + + /** + * Sets the angular speed of the body. Use this instead of the internal `body.angularSpeed`. + * @method setAngularSpeed + * @param {body} body + * @param {number} speed + */ + Body.setAngularSpeed = function(body, speed) { + Body.setAngularVelocity(body, Common.sign(Body.getAngularVelocity(body)) * speed); + }; + + /** + * Moves a body by a given vector relative to its current position, without imparting any velocity by default. + * If `updateVelocity` is `true` then velocity is inferred from the change in position. * @method translate * @param {body} body * @param {vector} translation + * @param {boolean} [updateVelocity=false] */ - Body.translate = function(body, translation) { - Body.setPosition(body, Vector.add(body.position, translation)); + Body.translate = function(body, translation, updateVelocity) { + Body.setPosition(body, Vector.add(body.position, translation), updateVelocity); }; /** - * Rotates a body by a given angle relative to its current angle, without imparting any angular velocity. + * Rotates a body by a given angle relative to its current angle, without imparting any angular velocity by default. + * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle. * @method rotate * @param {body} body * @param {number} rotation * @param {vector} [point] + * @param {boolean} [updateVelocity=false] */ - Body.rotate = function(body, rotation, point) { + Body.rotate = function(body, rotation, point, updateVelocity) { if (!point) { - Body.setAngle(body, body.angle + rotation); + Body.setAngle(body, body.angle + rotation, updateVelocity); } else { var cos = Math.cos(rotation), sin = Math.sin(rotation), @@ -552,9 +643,9 @@ var Axes = require('../geometry/Axes'); Body.setPosition(body, { x: point.x + (dx * cos - dy * sin), y: point.y + (dx * sin + dy * cos) - }); + }, updateVelocity); - Body.setAngle(body, body.angle + rotation); + Body.setAngle(body, body.angle + rotation, updateVelocity); } }; @@ -863,7 +954,7 @@ var Axes = require('../geometry/Axes'); */ /** - * A `Number` that _measures_ the current speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.velocity`). + * Internal only. Use `Body.getSpeed` and `Body.setSpeed` instead. * * @readOnly * @property speed @@ -872,7 +963,7 @@ var Axes = require('../geometry/Axes'); */ /** - * A `Number` that _measures_ the current angular speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.angularVelocity`). + * Internal only. Use `Body.getAngularSpeed` and `Body.setAngularSpeed` instead. * * @readOnly * @property angularSpeed @@ -881,8 +972,7 @@ var Axes = require('../geometry/Axes'); */ /** - * A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only. - * If you need to modify a body's velocity directly, you should either apply a force or simply change the body's `position` (as the engine uses position-Verlet integration). + * Internal only. Use `Body.getVelocity` and `Body.setVelocity` instead. * * @readOnly * @property velocity @@ -891,8 +981,7 @@ var Axes = require('../geometry/Axes'); */ /** - * A `Number` that _measures_ the current angular velocity of the body after the last `Body.update`. It is read-only. - * If you need to modify a body's angular velocity directly, you should apply a torque or simply change the body's `angle` (as the engine uses position-Verlet integration). + * Internal only. Use `Body.getAngularVelocity` and `Body.setAngularVelocity` instead. * * @readOnly * @property angularVelocity