-
Notifications
You must be signed in to change notification settings - Fork 329
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added TopDownVehicle class, Body.prototype.getVelocityAtPoint
- Loading branch information
Showing
4 changed files
with
303 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Top down vehicle demo - p2.js physics engine</title> | ||
<script src="../build/p2.js"></script> | ||
<script src="../build/p2.renderer.js"></script> | ||
<link href="css/demo.css" rel="stylesheet"/> | ||
<meta name="description" content=""> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | ||
</head> | ||
<body> | ||
<script> | ||
|
||
// Create demo application | ||
var app = new p2.WebGLRenderer(function(){ | ||
|
||
// Create a World | ||
var world = new p2.World({ | ||
gravity : [0,0] | ||
}); | ||
this.setWorld(world); | ||
|
||
// Create a dynamic body for the chassis | ||
chassisBody = new p2.Body({ | ||
mass: 1 | ||
}); | ||
var boxShape = new p2.Rectangle(0.5,1); | ||
chassisBody.addShape(boxShape); | ||
world.addBody(chassisBody); | ||
|
||
// Create the vehicle | ||
vehicle = new p2.TopDownVehicle(chassisBody); | ||
|
||
// Add one front wheel and one back wheel - we don't actually need four :) | ||
frontWheel = vehicle.addWheel({ | ||
localPosition: [0, 0.5] // front | ||
}); | ||
frontWheel.setSideFriction(4); | ||
|
||
// Back wheel | ||
backWheel = vehicle.addWheel({ | ||
localPosition: [0, -0.5] // back | ||
}); | ||
backWheel.setSideFriction(3); // Less side friction on back wheel makes it easier to drift | ||
|
||
vehicle.addToWorld(world); | ||
|
||
// Key controls | ||
var keys = { | ||
'37': 0, // left | ||
'39': 0, // right | ||
'38': 0, // up | ||
'40': 0 // down | ||
}; | ||
var maxSteer = Math.PI / 5; | ||
this.on("keydown",function (evt){ | ||
keys[evt.keyCode] = 1; | ||
onInputChange(); | ||
}); | ||
this.on("keyup",function (evt){ | ||
keys[evt.keyCode] = 0; | ||
onInputChange(); | ||
}); | ||
function onInputChange(){ | ||
|
||
// Steer value zero means straight forward. Positive is left and negative right. | ||
frontWheel.steerValue = maxSteer * (keys[37] - keys[39]); | ||
|
||
// Engine force forward | ||
backWheel.engineForce = keys[38] * 7; | ||
|
||
backWheel.setBrakeForce(0); | ||
if(keys[40]){ | ||
if(backWheel.getSpeed() > 0.1){ | ||
// Moving forward - add some brake force to slow down | ||
backWheel.setBrakeForce(5); | ||
} else { | ||
// Moving backwards - reverse the engine force | ||
backWheel.setBrakeForce(0); | ||
backWheel.engineForce = -2; | ||
} | ||
} | ||
} | ||
|
||
}); | ||
|
||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
var vec2 = require('../math/vec2'); | ||
var Utils = require('../utils/Utils'); | ||
var Constraint = require('../constraints/Constraint'); | ||
var FrictionEquation = require('../equations/FrictionEquation'); | ||
var Body = require('../objects/Body'); | ||
|
||
module.exports = TopDownVehicle; | ||
|
||
/** | ||
* @class TopDownVehicle | ||
* @constructor | ||
* @param {Body} chassisBody A dynamic body, already added to the world. | ||
* @param {Object} [options] | ||
*/ | ||
function TopDownVehicle(chassisBody, options){ | ||
options = options || {}; | ||
|
||
/** | ||
* @property {Body} chassisBody | ||
*/ | ||
this.chassisBody = chassisBody; | ||
|
||
/** | ||
* @property {Array} wheels | ||
*/ | ||
this.wheels = []; | ||
|
||
// A dummy body to constrain the chassis to | ||
this.groundBody = new Body({ mass: 0 }); | ||
|
||
this.world = null; | ||
|
||
var that = this; | ||
this.preStepCallback = function(){ | ||
that.update(); | ||
}; | ||
} | ||
|
||
/** | ||
* @method addToWorld | ||
* @param {World} world | ||
*/ | ||
TopDownVehicle.prototype.addToWorld = function(world){ | ||
this.world = world; | ||
world.addBody(this.groundBody); | ||
world.on('preStep', this.preStepCallback); | ||
for (var i = 0; i < this.wheels.length; i++) { | ||
var wheel = this.wheels[i]; | ||
world.addConstraint(wheel); | ||
} | ||
}; | ||
|
||
/** | ||
* @method removeFromWorld | ||
* @param {World} world | ||
*/ | ||
TopDownVehicle.prototype.removeFromWorld = function(){ | ||
var world = this.world; | ||
world.removeBody(this.groundBody); | ||
world.off('preStep', this.preStepCallback); | ||
for (var i = 0; i < this.wheels.length; i++) { | ||
var wheel = this.wheels[i]; | ||
world.removeConstraint(wheel); | ||
} | ||
this.world = null; | ||
}; | ||
|
||
/** | ||
* @method addWheel | ||
* @param {object} [wheelOptions] | ||
* @return {WheelConstraint} | ||
*/ | ||
TopDownVehicle.prototype.addWheel = function(wheelOptions){ | ||
var wheel = new WheelConstraint(this,wheelOptions); | ||
this.wheels.push(wheel); | ||
return wheel; | ||
}; | ||
|
||
/** | ||
* @method update | ||
*/ | ||
TopDownVehicle.prototype.update = function(){ | ||
for (var i = 0; i < this.wheels.length; i++) { | ||
this.wheels[i].update(); | ||
} | ||
}; | ||
|
||
/** | ||
* @class WheelConstraint | ||
* @constructor | ||
* @extends {Constraint} | ||
* @param {Vehicle} vehicle | ||
* @param {object} [options] | ||
* @param {Array} [options.localForwardVector] The local wheel forward vector in local body space. Default is [0,1]. | ||
* @param {Array} [options.localPosition] The local position of the wheen in the chassis body. Default is [0,0] - the center of the body. | ||
* @param {Array} [options.sideFriction=5] The max friction force in the sideways direction. | ||
*/ | ||
function WheelConstraint(vehicle, options){ | ||
options = options || {}; | ||
|
||
this.vehicle = vehicle; | ||
|
||
this.forwardEquation = new FrictionEquation(vehicle.chassisBody, vehicle.groundBody); | ||
|
||
this.sideEquation = new FrictionEquation(vehicle.chassisBody, vehicle.groundBody); | ||
|
||
/** | ||
* @property {number} steerValue | ||
*/ | ||
this.steerValue = 0; | ||
|
||
/** | ||
* @property {number} engineForce | ||
*/ | ||
this.engineForce = 0; | ||
|
||
this.setSideFriction(options.sideFriction !== undefined ? options.sideFriction : 5); | ||
|
||
/** | ||
* @property {Array} localForwardVector | ||
*/ | ||
this.localForwardVector = vec2.fromValues(0, 1); | ||
if(options.localForwardVector){ | ||
vec2.copy(this.localForwardVector, options.localForwardVector); | ||
} | ||
|
||
/** | ||
* @property {Array} localPosition | ||
*/ | ||
this.localPosition = vec2.fromValues(0, 0); | ||
if(options.localPosition){ | ||
vec2.copy(this.localPosition, options.localPosition); | ||
} | ||
|
||
Constraint.apply(this, vehicle.chassisBody, vehicle.groundBody); | ||
|
||
this.equations.push( | ||
this.forwardEquation, | ||
this.sideEquation | ||
); | ||
|
||
this.setBrakeForce(0); | ||
} | ||
WheelConstraint.prototype = new Constraint(); | ||
|
||
/** | ||
* @method setForwardFriction | ||
*/ | ||
WheelConstraint.prototype.setBrakeForce = function(force){ | ||
this.forwardEquation.setSlipForce(force); | ||
}; | ||
|
||
/** | ||
* @method setSideFriction | ||
*/ | ||
WheelConstraint.prototype.setSideFriction = function(force){ | ||
this.sideEquation.setSlipForce(force); | ||
}; | ||
|
||
var worldVelocity = vec2.create(); | ||
var relativePoint = vec2.create(); | ||
|
||
/** | ||
* @method getSpeed | ||
*/ | ||
WheelConstraint.prototype.getSpeed = function(){ | ||
this.vehicle.chassisBody.vectorToWorldFrame(relativePoint, this.localForwardVector); | ||
this.vehicle.chassisBody.getVelocityAtPoint(worldVelocity, relativePoint); | ||
return vec2.dot(worldVelocity, relativePoint); | ||
}; | ||
|
||
var tmpVec = vec2.create(); | ||
|
||
/** | ||
* @method update | ||
*/ | ||
WheelConstraint.prototype.update = function(){ | ||
|
||
// Directional | ||
this.vehicle.chassisBody.vectorToWorldFrame(this.forwardEquation.t, this.localForwardVector); | ||
vec2.rotate(this.sideEquation.t, this.localForwardVector, Math.PI / 2); | ||
this.vehicle.chassisBody.vectorToWorldFrame(this.sideEquation.t, this.sideEquation.t); | ||
|
||
vec2.rotate(this.forwardEquation.t, this.forwardEquation.t, this.steerValue); | ||
vec2.rotate(this.sideEquation.t, this.sideEquation.t, this.steerValue); | ||
|
||
// Attachment point | ||
this.vehicle.chassisBody.toWorldFrame(this.forwardEquation.contactPointB, this.localPosition); | ||
vec2.copy(this.sideEquation.contactPointB, this.forwardEquation.contactPointB); | ||
|
||
this.vehicle.chassisBody.vectorToWorldFrame(this.forwardEquation.contactPointA, this.localPosition); | ||
vec2.copy(this.sideEquation.contactPointA, this.forwardEquation.contactPointA); | ||
|
||
// Add engine force | ||
vec2.normalize(tmpVec, this.forwardEquation.t); | ||
vec2.scale(tmpVec, tmpVec, this.engineForce); | ||
|
||
this.vehicle.chassisBody.applyForce(tmpVec, this.forwardEquation.contactPointA); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters