mirror of
https://github.com/logsol/chuck.js.git
synced 2026-05-11 10:37:34 +00:00
changed linear interpolation to nearest and added rube ragdoll with testbed in lab
This commit is contained in:
parent
47bb5ef147
commit
86063661db
28 changed files with 31671 additions and 2 deletions
11072
lab/rube/js/box2dweb.js
Normal file
11072
lab/rube/js/box2dweb.js
Normal file
File diff suppressed because it is too large
Load diff
71
lab/rube/js/index.html
Normal file
71
lab/rube/js/index.html
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Box2D javascript (box2dweb) testbed</title>
|
||||
|
||||
<script type="text/javascript" src="box2dweb.js"></script>
|
||||
<script type="text/javascript" src="loadrube.js"></script>
|
||||
<script type="text/javascript" src="testbed.js"></script>
|
||||
|
||||
<script type="text/javascript" src="jack-min.js"></script>
|
||||
<script type="text/javascript" src="jackinthebox.js"></script>
|
||||
|
||||
<script type="text/javascript" src="ragdoll-min.js"></script>
|
||||
<script type="text/javascript" src="ragdoll.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div style="text-align:center">
|
||||
<br>
|
||||
Try the latest version of Chrome or Firefox for best performance.<br>
|
||||
<br>
|
||||
<div style="margin:auto;width:640px;padding:2px;border:1px solid #888;text-align:left">
|
||||
<!--
|
||||
If you change the size of the canvas, you'll also need to change
|
||||
the value of 'viewCenterPixel' in testbed.js
|
||||
-->
|
||||
<canvas id="canvas" width="640" height="480" tabindex='1'></canvas>
|
||||
<div style="width:636px;padding:2px;background-color:#ddd">
|
||||
<div style="text-align:center">
|
||||
Select test: <select id="testSelection" onchange="changeTest();">
|
||||
<option value="ragdoll">Ragdoll of Chuck</option>
|
||||
<option value="jackinthebox">Jack-in-the-box</option>
|
||||
</select><br>
|
||||
<div style="height:6px"></div>
|
||||
<div id="sceneinfo" style="width:500px;margin:auto;background-color:#eee;text-align:left">
|
||||
Loading...
|
||||
</div>
|
||||
<div id="testcomments" style="width:500px;margin:auto;background-color:#eee;text-align:left">
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<button id="reloadButton" onclick="resetScene();">Reset</button>
|
||||
<button id="pauseButton" onclick="pause();">Pause</button>
|
||||
<button id="stepButton" onclick="step();">Single step</button>
|
||||
(Keyboard: R, P, S)<br>
|
||||
Zoom
|
||||
<button id="zoomInButton" onclick="zoomIn();">+</button>
|
||||
<button id="zoomOutButton" onclick="zoomOut();">-</button>
|
||||
(Keyboard: X, Z)<br>
|
||||
Hold down Shift while moving the mouse to pan (Keyboard: arrow keys)<br>
|
||||
You need to click on the canvas before using the keyboard.<br>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
Debug draw flags:<br>
|
||||
<input id="drawShapesCheck" type="checkbox" onclick="updateWorldFromDebugDrawCheckboxes();">Shapes<br>
|
||||
<input id="drawJointsCheck" type="checkbox" onclick="updateWorldFromDebugDrawCheckboxes();">Joints<br>
|
||||
<input id="drawAABBsCheck" type="checkbox" onclick="updateWorldFromDebugDrawCheckboxes();">AABBs<br>
|
||||
<input id="drawTransformsCheck" type="checkbox" onclick="updateWorldFromDebugDrawCheckboxes();">Transforms<br>
|
||||
<br>
|
||||
|
||||
<input id="showStatsCheck" type="checkbox" onclick="updateContinuousRefreshStatus();">Show stats<br>
|
||||
<span id="feedbackSpan"></span>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
12
lab/rube/js/jack-min.js
vendored
Normal file
12
lab/rube/js/jack-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
26
lab/rube/js/jackinthebox.js
Normal file
26
lab/rube/js/jackinthebox.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
var jackinthebox = function() {
|
||||
//constructor
|
||||
}
|
||||
|
||||
jackinthebox.prototype.setNiceViewCenter = function() {
|
||||
//called once when the user changes to this test from another test
|
||||
PTM = 70;
|
||||
setViewCenterWorld( new b2Vec2(0, 10.5), true );
|
||||
}
|
||||
|
||||
jackinthebox.prototype.setup = function() {
|
||||
//set up the Box2D scene here - the world is already created
|
||||
|
||||
if ( loadSceneFromRUBE(jack_scene) ) //jack_scene is defined in jack-min.js
|
||||
console.log("RUBE scene loaded successfully.");
|
||||
else
|
||||
console.log("Failed to load RUBE scene");
|
||||
|
||||
doAfterLoading();
|
||||
|
||||
}
|
||||
|
||||
jackinthebox.prototype.getComments = function(canvas, evt) {
|
||||
return "Created in R.U.B.E editor. Pull the latch to the side to open the box.";
|
||||
}
|
||||
416
lab/rube/js/loadrube.js
Normal file
416
lab/rube/js/loadrube.js
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
|
||||
Object.prototype.hasOwnProperty = function(property) {
|
||||
return typeof(this[property]) !== 'undefined'
|
||||
};
|
||||
|
||||
function loadBodyFromRUBE(bodyJso, world) {
|
||||
//console.log(bodyJso);
|
||||
|
||||
if ( ! bodyJso.hasOwnProperty('type') ) {
|
||||
console.log("Body does not have a 'type' property");
|
||||
return null;
|
||||
}
|
||||
|
||||
var bd = new b2BodyDef();
|
||||
if ( bodyJso.type == 2 )
|
||||
bd.type = b2_dynamicBody;
|
||||
else if ( bodyJso.type == 1 )
|
||||
bd.type = b2_kinematicBody;
|
||||
if ( bodyJso.hasOwnProperty('angle') )
|
||||
bd.angle = bodyJso.angle;
|
||||
if ( bodyJso.hasOwnProperty('angularVelocity') )
|
||||
bd.angularVelocity = bodyJso.angularVelocity;
|
||||
if ( bodyJso.hasOwnProperty('active') )
|
||||
bd.awake = bodyJso.active;
|
||||
if ( bodyJso.hasOwnProperty('fixedRotation') )
|
||||
bd.fixedRotation = bodyJso.fixedRotation;
|
||||
if ( bodyJso.hasOwnProperty('linearVelocity') && bodyJso.linearVelocity instanceof Object )
|
||||
bd.linearVelocity.SetV( bodyJso.linearVelocity );
|
||||
if ( bodyJso.hasOwnProperty('position') && bodyJso.position instanceof Object )
|
||||
bd.position.SetV( bodyJso.position );
|
||||
if ( bodyJso.hasOwnProperty('awake') )
|
||||
bd.awake = bodyJso.awake;
|
||||
else
|
||||
bd.awake = false;
|
||||
var body = world.CreateBody(bd);
|
||||
if ( bodyJso.hasOwnProperty('fixture') ) {
|
||||
for (k = 0; k < bodyJso['fixture'].length; k++) {
|
||||
var fixtureJso = bodyJso['fixture'][k];
|
||||
loadFixtureFromRUBE(body, fixtureJso);
|
||||
}
|
||||
}
|
||||
if ( bodyJso.hasOwnProperty('name') )
|
||||
body.name = bodyJso.name;
|
||||
if ( bodyJso.hasOwnProperty('customProperties') )
|
||||
body.customProperties = bodyJso.customProperties;
|
||||
return body;
|
||||
}
|
||||
|
||||
function loadFixtureFromRUBE(body, fixtureJso) {
|
||||
//console.log(fixtureJso);
|
||||
var fd = new b2FixtureDef();
|
||||
if (fixtureJso.hasOwnProperty('friction'))
|
||||
fd.friction = fixtureJso.friction;
|
||||
if (fixtureJso.hasOwnProperty('density'))
|
||||
fd.density = fixtureJso.density;
|
||||
if (fixtureJso.hasOwnProperty('restitution'))
|
||||
fd.restitution = fixtureJso.restitution;
|
||||
if (fixtureJso.hasOwnProperty('sensor'))
|
||||
fd.isSensor = fixtureJso.sensor;
|
||||
if ( fixtureJso.hasOwnProperty('filter-categoryBits') )
|
||||
fd.filter.categoryBits = fixtureJso['filter-categoryBits'];
|
||||
if ( fixtureJso.hasOwnProperty('filter-maskBits') )
|
||||
fd.filter.maskBits = fixtureJso['filter-maskBits'];
|
||||
if ( fixtureJso.hasOwnProperty('filter-groupIndex') )
|
||||
fd.filter.groupIndex = fixtureJso['filter-groupIndex'];
|
||||
if (fixtureJso.hasOwnProperty('circle')) {
|
||||
fd.shape = new b2CircleShape();
|
||||
fd.shape.m_radius = fixtureJso.circle.radius;
|
||||
if ( fixtureJso.circle.center )
|
||||
fd.shape.m_p.SetV(fixtureJso.circle.center);
|
||||
var fixture = body.CreateFixture(fd);
|
||||
if ( fixtureJso.name )
|
||||
fixture.name = fixtureJso.name;
|
||||
}
|
||||
else if (fixtureJso.hasOwnProperty('polygon')) {
|
||||
fd.shape = new b2PolygonShape();
|
||||
var verts = [];
|
||||
for (v = 0; v < fixtureJso.polygon.vertices.x.length; v++)
|
||||
verts.push( new b2Vec2( fixtureJso.polygon.vertices.x[v], fixtureJso.polygon.vertices.y[v] ) );
|
||||
fd.shape.SetAsArray(verts, verts.length);
|
||||
var fixture = body.CreateFixture(fd);
|
||||
if ( fixture && fixtureJso.name )
|
||||
fixture.name = fixtureJso.name;
|
||||
}
|
||||
else if (fixtureJso.hasOwnProperty('chain')) {
|
||||
fd.shape = new b2PolygonShape();
|
||||
var lastVertex = new b2Vec2();
|
||||
for (v = 0; v < fixtureJso.chain.vertices.x.length; v++) {
|
||||
var thisVertex = new b2Vec2( fixtureJso.chain.vertices.x[v], fixtureJso.chain.vertices.y[v] );
|
||||
if ( v > 0 ) {
|
||||
fd.shape.SetAsEdge( lastVertex, thisVertex );
|
||||
var fixture = body.CreateFixture(fd);
|
||||
if ( fixtureJso.name )
|
||||
fixture.name = fixtureJso.name;
|
||||
}
|
||||
lastVertex = thisVertex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log("Could not find shape type for fixture");
|
||||
}
|
||||
}
|
||||
|
||||
function getVectorValue(val) {
|
||||
if ( val instanceof Object )
|
||||
return val;
|
||||
else
|
||||
return { x:0, y:0 };
|
||||
}
|
||||
|
||||
function loadJointCommonProperties(jd, jointJso, loadedBodies) {
|
||||
jd.bodyA = loadedBodies[jointJso.bodyA];
|
||||
jd.bodyB = loadedBodies[jointJso.bodyB];
|
||||
jd.localAnchorA.SetV( getVectorValue(jointJso.anchorA) );
|
||||
jd.localAnchorB.SetV( getVectorValue(jointJso.anchorB) );
|
||||
if ( jointJso.collideConnected )
|
||||
jd.collideConnected = jointJso.collideConnected;
|
||||
}
|
||||
|
||||
function loadJointFromRUBE(jointJso, world, loadedBodies)
|
||||
{
|
||||
if ( ! jointJso.hasOwnProperty('type') ) {
|
||||
console.log("Joint does not have a 'type' property");
|
||||
return null;
|
||||
}
|
||||
if ( jointJso.bodyA >= loadedBodies.length ) {
|
||||
console.log("Index for bodyA is invalid: " + jointJso.bodyA );
|
||||
return null;
|
||||
}
|
||||
if ( jointJso.bodyB >= loadedBodies.length ) {
|
||||
console.log("Index for bodyB is invalid: " + jointJso.bodyB );
|
||||
return null;
|
||||
}
|
||||
|
||||
var joint = null;
|
||||
if ( jointJso.type == "revolute" ) {
|
||||
var jd = new b2RevoluteJointDef();
|
||||
loadJointCommonProperties(jd, jointJso, loadedBodies);
|
||||
if ( jointJso.hasOwnProperty('refAngle') )
|
||||
jd.referenceAngle = jointJso.refAngle;
|
||||
if ( jointJso.hasOwnProperty('lowerLimit') )
|
||||
jd.lowerAngle = jointJso.lowerLimit;
|
||||
if ( jointJso.hasOwnProperty('upperLimit') )
|
||||
jd.upperAngle = jointJso.upperLimit;
|
||||
if ( jointJso.hasOwnProperty('maxMotorTorque') )
|
||||
jd.maxMotorTorque = jointJso.maxMotorTorque;
|
||||
if ( jointJso.hasOwnProperty('motorSpeed') )
|
||||
jd.motorSpeed = jointJso.motorSpeed;
|
||||
if ( jointJso.hasOwnProperty('enableLimit') )
|
||||
jd.enableLimit = jointJso.enableLimit;
|
||||
if ( jointJso.hasOwnProperty('enableMotor') )
|
||||
jd.enableMotor = jointJso.enableMotor;
|
||||
joint = world.CreateJoint(jd);
|
||||
}
|
||||
else if ( jointJso.type == "distance" || jointJso.type == "rope" ) {
|
||||
if ( jointJso.type == "rope" )
|
||||
console.log("Replacing unsupported rope joint with distance joint!");
|
||||
var jd = new b2DistanceJointDef();
|
||||
loadJointCommonProperties(jd, jointJso, loadedBodies);
|
||||
if ( jointJso.hasOwnProperty('length') )
|
||||
jd.length = jointJso.length;
|
||||
if ( jointJso.hasOwnProperty('dampingRatio') )
|
||||
jd.dampingRatio = jointJso.dampingRatio;
|
||||
if ( jointJso.hasOwnProperty('frequency') )
|
||||
jd.frequencyHz = jointJso.frequency;
|
||||
joint = world.CreateJoint(jd);
|
||||
}
|
||||
else if ( jointJso.type == "prismatic" ) {
|
||||
var jd = new b2PrismaticJointDef();
|
||||
loadJointCommonProperties(jd, jointJso, loadedBodies);
|
||||
if ( jointJso.hasOwnProperty('localAxisA') )
|
||||
jd.localAxisA.SetV( getVectorValue(jointJso.localAxisA) );
|
||||
if ( jointJso.hasOwnProperty('refAngle') )
|
||||
jd.referenceAngle = jointJso.refAngle;
|
||||
if ( jointJso.hasOwnProperty('enableLimit') )
|
||||
jd.enableLimit = jointJso.enableLimit;
|
||||
if ( jointJso.hasOwnProperty('lowerLimit') )
|
||||
jd.lowerTranslation = jointJso.lowerLimit;
|
||||
if ( jointJso.hasOwnProperty('upperLimit') )
|
||||
jd.upperTranslation = jointJso.upperLimit;
|
||||
if ( jointJso.hasOwnProperty('enableMotor') )
|
||||
jd.enableMotor = jointJso.enableMotor;
|
||||
if ( jointJso.hasOwnProperty('maxMotorForce') )
|
||||
jd.maxMotorForce = jointJso.maxMotorForce;
|
||||
if ( jointJso.hasOwnProperty('motorSpeed') )
|
||||
jd.motorSpeed = jointJso.motorSpeed;
|
||||
joint = world.CreateJoint(jd);
|
||||
}
|
||||
else if ( jointJso.type == "wheel" ) {
|
||||
//Make a fake wheel joint using a line joint and a distance joint.
|
||||
//Return the line joint because it has the linear motor controls.
|
||||
//Use ApplyTorque on the bodies to spin the wheel...
|
||||
|
||||
var jd = new b2DistanceJointDef();
|
||||
loadJointCommonProperties(jd, jointJso, loadedBodies);
|
||||
jd.length = 0.0;
|
||||
if ( jointJso.hasOwnProperty('springDampingRatio') )
|
||||
jd.dampingRatio = jointJso.springDampingRatio;
|
||||
if ( jointJso.hasOwnProperty('springFrequency') )
|
||||
jd.frequencyHz = jointJso.springFrequency;
|
||||
world.CreateJoint(jd);
|
||||
|
||||
jd = new b2LineJointDef();
|
||||
loadJointCommonProperties(jd, jointJso, loadedBodies);
|
||||
if ( jointJso.hasOwnProperty('localAxisA') )
|
||||
jd.localAxisA.SetV( getVectorValue(jointJso.localAxisA) );
|
||||
|
||||
joint = world.CreateJoint(jd);
|
||||
}
|
||||
else if ( jointJso.type == "friction" ) {
|
||||
var jd = new b2FrictionJointDef();
|
||||
loadJointCommonProperties(jd, jointJso, loadedBodies);
|
||||
if ( jointJso.hasOwnProperty('maxForce') )
|
||||
jd.maxForce = jointJso.maxForce;
|
||||
if ( jointJso.hasOwnProperty('maxTorque') )
|
||||
jd.maxTorque = jointJso.maxTorque;
|
||||
joint = world.CreateJoint(jd);
|
||||
}
|
||||
else if ( jointJso.type == "weld" ) {
|
||||
var jd = new b2WeldJointDef();
|
||||
loadJointCommonProperties(jd, jointJso, loadedBodies);
|
||||
if ( jointJso.hasOwnProperty('referenceAngle') )
|
||||
jd.referenceAngle = jointJso.referenceAngle;
|
||||
joint = world.CreateJoint(jd);
|
||||
}
|
||||
else {
|
||||
console.log("Unsupported joint type: " + jointJso.type);
|
||||
console.log(jointJso);
|
||||
}
|
||||
if ( joint && jointJso.name )
|
||||
joint.name = jointJso.name;
|
||||
return joint;
|
||||
}
|
||||
|
||||
function makeClone(obj) {
|
||||
var newObj = (obj instanceof Array) ? [] : {};
|
||||
for (var i in obj) {
|
||||
if (obj[i] && typeof obj[i] == "object")
|
||||
newObj[i] = makeClone(obj[i]);
|
||||
else
|
||||
newObj[i] = obj[i];
|
||||
}
|
||||
return newObj;
|
||||
};
|
||||
|
||||
function loadImageFromRUBE(imageJso, world, loadedBodies)
|
||||
{
|
||||
var image = makeClone(imageJso);
|
||||
|
||||
if ( image.hasOwnProperty('body') && image.body >= 0 )
|
||||
image.body = loadedBodies[image.body];//change index to the actual body
|
||||
else
|
||||
image.body = null;
|
||||
|
||||
image.center = new b2Vec2();
|
||||
image.center.SetV( getVectorValue(imageJso.center) );
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//mainly just a convenience for the testbed - uses global 'world' variable
|
||||
function loadSceneFromRUBE(worldJso) {
|
||||
return loadSceneIntoWorld(worldJso, world);
|
||||
}
|
||||
|
||||
//load the scene into an already existing world variable
|
||||
function loadSceneIntoWorld(worldJso, world) {
|
||||
var success = true;
|
||||
|
||||
var loadedBodies = [];
|
||||
if ( worldJso.hasOwnProperty('body') ) {
|
||||
for (var i = 0; i < worldJso.body.length; i++) {
|
||||
var bodyJso = worldJso.body[i];
|
||||
var body = loadBodyFromRUBE(bodyJso, world);
|
||||
if ( body )
|
||||
loadedBodies.push( body );
|
||||
else
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
var loadedJoints = [];
|
||||
if ( worldJso.hasOwnProperty('joint') ) {
|
||||
for (var i = 0; i < worldJso.joint.length; i++) {
|
||||
var jointJso = worldJso.joint[i];
|
||||
var joint = loadJointFromRUBE(jointJso, world, loadedBodies);
|
||||
if ( joint )
|
||||
loadedJoints.push( joint );
|
||||
//else
|
||||
// success = false;
|
||||
}
|
||||
}
|
||||
|
||||
var loadedImages = [];
|
||||
if ( worldJso.hasOwnProperty('image') ) {
|
||||
for (var i = 0; i < worldJso.image.length; i++) {
|
||||
var imageJso = worldJso.image[i];
|
||||
var image = loadImageFromRUBE(imageJso, world, loadedBodies);
|
||||
if ( image )
|
||||
loadedImages.push( image );
|
||||
else
|
||||
success = false;
|
||||
}
|
||||
world.images = loadedImages;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//create a world variable and return it if loading succeeds
|
||||
function loadWorldFromRUBE(worldJso) {
|
||||
var gravity = new b2Vec2(0,0);
|
||||
if ( worldJso.hasOwnProperty('gravity') && worldJso.gravity instanceof Object )
|
||||
gravity.SetV( worldJso.gravity );
|
||||
var world = new b2World( gravity );
|
||||
if ( ! loadSceneIntoWorld(worldJso, world) )
|
||||
return false;
|
||||
return world;
|
||||
}
|
||||
|
||||
function getNamedBodies(world, name) {
|
||||
var bodies = [];
|
||||
for (b = world.m_bodyList; b; b = b.m_next) {
|
||||
if ( b.name == name )
|
||||
bodies.push(b);
|
||||
}
|
||||
return bodies;
|
||||
}
|
||||
|
||||
function getNamedFixtures(world, name) {
|
||||
var fixtures = [];
|
||||
for (b = world.m_bodyList; b; b = b.m_next) {
|
||||
for (f = b.m_fixtureList; f; f = f.m_next) {
|
||||
if ( f.name == name )
|
||||
fixtures.push(f);
|
||||
}
|
||||
}
|
||||
return fixtures;
|
||||
}
|
||||
|
||||
function getNamedJoints(world, name) {
|
||||
var joints = [];
|
||||
for (j = world.m_jointList; j; j = j.m_next) {
|
||||
if ( j.name == name )
|
||||
joints.push(j);
|
||||
}
|
||||
return joints;
|
||||
}
|
||||
|
||||
function getNamedImages(world, name) {
|
||||
var images = [];
|
||||
for (i = 0; i < world.images.length; i++) {
|
||||
if ( world.images[i].name == name )
|
||||
images.push(world.images[i].name);
|
||||
}
|
||||
return images;
|
||||
}
|
||||
|
||||
//custom properties
|
||||
function getBodiesByCustomProperty(world, propertyType, propertyName, valueToMatch) {
|
||||
var bodies = [];
|
||||
for (b = world.m_bodyList; b; b = b.m_next) {
|
||||
if ( ! b.hasOwnProperty('customProperties') )
|
||||
continue;
|
||||
for (var i = 0; i < b.customProperties.length; i++) {
|
||||
if ( ! b.customProperties[i].hasOwnProperty("name") )
|
||||
continue;
|
||||
if ( ! b.customProperties[i].hasOwnProperty(propertyType) )
|
||||
continue;
|
||||
if ( b.customProperties[i].name == propertyName &&
|
||||
b.customProperties[i][propertyType] == valueToMatch)
|
||||
bodies.push(b);
|
||||
}
|
||||
}
|
||||
return bodies;
|
||||
}
|
||||
|
||||
function hasCustomProperty(item, propertyType, propertyName) {
|
||||
if ( !item.hasOwnProperty('customProperties') )
|
||||
return false;
|
||||
for (var i = 0; i < item.customProperties.length; i++) {
|
||||
if ( ! item.customProperties[i].hasOwnProperty("name") )
|
||||
continue;
|
||||
if ( ! item.customProperties[i].hasOwnProperty(propertyType) )
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getCustomProperty(item, propertyType, propertyName, defaultValue) {
|
||||
if ( !item.hasOwnProperty('customProperties') )
|
||||
return defaultValue;
|
||||
for (var i = 0; i < item.customProperties.length; i++) {
|
||||
if ( ! item.customProperties[i].hasOwnProperty("name") )
|
||||
continue;
|
||||
if ( ! item.customProperties[i].hasOwnProperty(propertyType) )
|
||||
continue;
|
||||
if ( item.customProperties[i].name == propertyName )
|
||||
return item.customProperties[i][propertyType];
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1379
lab/rube/js/ragdoll-min.js
vendored
Normal file
1379
lab/rube/js/ragdoll-min.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
40
lab/rube/js/ragdoll.js
Normal file
40
lab/rube/js/ragdoll.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
var ragdoll = function() {
|
||||
//constructor
|
||||
}
|
||||
|
||||
ragdoll.prototype.setNiceViewCenter = function() {
|
||||
//called once when the user changes to this test from another test
|
||||
PTM = 70;
|
||||
setViewCenterWorld( new b2Vec2(0, 1), true );
|
||||
}
|
||||
|
||||
ragdoll.prototype.setup = function() {
|
||||
//set up the Box2D scene here - the world is already created
|
||||
|
||||
var c = document.getElementById('canvas');
|
||||
|
||||
var ctx = c.getContext("2d");
|
||||
if(ctx) {
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
ctx.mozImageSmoothingEnabled = false;
|
||||
ctx.webkitImageSmoothingEnabled = false;
|
||||
}
|
||||
setTimeout(function(){
|
||||
document.getElementById('drawShapesCheck').checked = false;
|
||||
updateWorldFromDebugDrawCheckboxes();
|
||||
}, 10);
|
||||
|
||||
|
||||
if ( loadSceneFromRUBE(ragdoll_scene) ) //jack_scene is defined in jack-min.js
|
||||
console.log("RUBE scene loaded successfully.");
|
||||
else
|
||||
console.log("Failed to load RUBE scene");
|
||||
|
||||
doAfterLoading();
|
||||
|
||||
}
|
||||
|
||||
ragdoll.prototype.getComments = function(canvas, evt) {
|
||||
return "Created in R.U.B.E editor. Pull the latch to the side to open the box.";
|
||||
}
|
||||
830
lab/rube/js/testbed.js
Normal file
830
lab/rube/js/testbed.js
Normal file
|
|
@ -0,0 +1,830 @@
|
|||
|
||||
//Having to type 'Box2D.' in front of everything makes porting
|
||||
//existing C++ code a pain in the butt. This function can be used
|
||||
//to make everything in the Box2D namespace available without
|
||||
//needing to do that.
|
||||
/*function using(ns, pattern) {
|
||||
if (pattern == undefined) {
|
||||
// import all
|
||||
for (var name in ns) {
|
||||
//console.log(this[name]);
|
||||
this[name] = ns[name];
|
||||
}
|
||||
} else {
|
||||
if (typeof(pattern) == 'string') {
|
||||
pattern = new RegExp(pattern);
|
||||
}
|
||||
// import only stuff matching given pattern
|
||||
for (var name in ns) {
|
||||
//console.log(name);
|
||||
if (name.match(pattern)) {
|
||||
//console.log(ns[name]);
|
||||
this[name] = ns[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
var e_shapeBit = 0x0001;
|
||||
var e_jointBit = 0x0002;
|
||||
var e_aabbBit = 0x0004;
|
||||
var e_pairBit = 0x0008;
|
||||
var e_centerOfMassBit = 0x0010;
|
||||
|
||||
var PTM = 32;
|
||||
|
||||
var world = null;
|
||||
var mouseJointGroundBody;
|
||||
var canvas;
|
||||
var context;
|
||||
var myDebugDraw;
|
||||
var mouseDownQueryCallback;
|
||||
var visibleFixturesQueryCallback;
|
||||
var mouseJoint = null;
|
||||
var run = true;
|
||||
var frameTime60 = 0;
|
||||
var statusUpdateCounter = 0;
|
||||
var showStats = false;
|
||||
var mouseDown = false;
|
||||
var shiftDown = false;
|
||||
var originTransform;
|
||||
var mousePosPixel = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
var prevMousePosPixel = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
var mousePosWorld = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
var canvasOffset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
var viewCenterPixel = {
|
||||
x:320,
|
||||
y:240
|
||||
};
|
||||
var viewAABB;
|
||||
|
||||
function myRound(val,places) {
|
||||
var c = 1;
|
||||
for (var i = 0; i < places; i++)
|
||||
c *= 10;
|
||||
return Math.round(val*c)/c;
|
||||
}
|
||||
|
||||
function getWorldPointFromPixelPoint(pixelPoint) {
|
||||
return {
|
||||
x: (pixelPoint.x - canvasOffset.x)/PTM,
|
||||
y: (pixelPoint.y - (canvas.height - canvasOffset.y))/PTM
|
||||
};
|
||||
}
|
||||
|
||||
function updateMousePos(canvas, evt) {
|
||||
var rect = canvas.getBoundingClientRect();
|
||||
mousePosPixel = {
|
||||
x: evt.clientX - rect.left,
|
||||
y: canvas.height - (evt.clientY - rect.top)
|
||||
};
|
||||
mousePosWorld = getWorldPointFromPixelPoint(mousePosPixel);
|
||||
}
|
||||
|
||||
function setViewCenterWorld(b2vecpos, instantaneous) {
|
||||
var currentViewCenterWorld = getWorldPointFromPixelPoint( viewCenterPixel );
|
||||
var toMoveX = b2vecpos.x - currentViewCenterWorld.x;
|
||||
var toMoveY = b2vecpos.y - currentViewCenterWorld.y;
|
||||
var fraction = instantaneous ? 1 : 0.25;
|
||||
canvasOffset.x -= myRound(fraction * toMoveX * PTM, 0);
|
||||
canvasOffset.y += myRound(fraction * toMoveY * PTM, 0);
|
||||
}
|
||||
|
||||
function onMouseMove(canvas, evt) {
|
||||
prevMousePosPixel = mousePosPixel;
|
||||
updateMousePos(canvas, evt);
|
||||
updateStats();
|
||||
if ( shiftDown ) {
|
||||
canvasOffset.x += (mousePosPixel.x - prevMousePosPixel.x);
|
||||
canvasOffset.y -= (mousePosPixel.y - prevMousePosPixel.y);
|
||||
draw();
|
||||
}
|
||||
else if ( mouseDown && mouseJoint != null ) {
|
||||
mouseJoint.SetTarget( new b2Vec2(mousePosWorld.x, mousePosWorld.y) );
|
||||
}
|
||||
}
|
||||
|
||||
var getBodyCB = function(fixture) {
|
||||
if(fixture.GetBody().GetType() != Box2D.Dynamics.b2BodyDef.b2_staticBody) {
|
||||
if(fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePosWorld)) {
|
||||
selectedBody = fixture.GetBody();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
function startMouseJoint() {
|
||||
|
||||
if ( mouseJoint != null )
|
||||
return;
|
||||
|
||||
// Make a small box.
|
||||
var aabb = new b2AABB();
|
||||
var d = 0.001;
|
||||
aabb.lowerBound.Set(mousePosWorld.x - d, mousePosWorld.y - d);
|
||||
aabb.upperBound.Set(mousePosWorld.x + d, mousePosWorld.y + d);
|
||||
|
||||
// Query the world for overlapping shapes.
|
||||
mouseDownQueryCallback.m_fixture = null;
|
||||
mouseDownQueryCallback.m_point.Set(mousePosWorld.x, mousePosWorld.y);
|
||||
world.QueryAABB(mouseDownQueryCallback, aabb);
|
||||
if (mouseDownQueryCallback.m_fixture)
|
||||
{
|
||||
var body = mouseDownQueryCallback.m_fixture.GetBody();
|
||||
|
||||
/*selectedBody = null;
|
||||
world.QueryAABB(getBodyCB, aabb);
|
||||
if (selectedBody)
|
||||
{
|
||||
var body = selectedBody;*/
|
||||
var md = new b2MouseJointDef();
|
||||
md.bodyA = mouseJointGroundBody;
|
||||
md.bodyB = body;
|
||||
md.target.Set(mousePosWorld.x, mousePosWorld.y);
|
||||
md.maxForce = 1000 * body.GetMass();
|
||||
md.collideConnected = true;
|
||||
|
||||
mouseJoint = world.CreateJoint(md);
|
||||
body.SetAwake(true);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseDown(canvas, evt) {
|
||||
updateMousePos(canvas, evt);
|
||||
if ( !mouseDown )
|
||||
startMouseJoint();
|
||||
mouseDown = true;
|
||||
updateStats();
|
||||
}
|
||||
|
||||
function onMouseUp(canvas, evt) {
|
||||
mouseDown = false;
|
||||
updateMousePos(canvas, evt);
|
||||
updateStats();
|
||||
if ( mouseJoint != null ) {
|
||||
world.DestroyJoint(mouseJoint);
|
||||
mouseJoint = null;
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseOut(canvas, evt) {
|
||||
onMouseUp(canvas,evt);
|
||||
}
|
||||
|
||||
function onKeyDown(canvas, evt) {
|
||||
//console.log(evt.keyCode);
|
||||
if ( evt.keyCode == 80 ) {//p
|
||||
pause();
|
||||
}
|
||||
else if ( evt.keyCode == 82 ) {//r
|
||||
resetScene();
|
||||
}
|
||||
else if ( evt.keyCode == 83 ) {//s
|
||||
step();
|
||||
}
|
||||
else if ( evt.keyCode == 88 ) {//x
|
||||
zoomIn();
|
||||
}
|
||||
else if ( evt.keyCode == 90 ) {//z
|
||||
zoomOut();
|
||||
}
|
||||
else if ( evt.keyCode == 37 ) {//left
|
||||
canvasOffset.x += 32;
|
||||
}
|
||||
else if ( evt.keyCode == 39 ) {//right
|
||||
canvasOffset.x -= 32;
|
||||
}
|
||||
else if ( evt.keyCode == 38 ) {//up
|
||||
canvasOffset.y += 32;
|
||||
}
|
||||
else if ( evt.keyCode == 40 ) {//down
|
||||
canvasOffset.y -= 32;
|
||||
}
|
||||
else if ( evt.keyCode == 16 ) {//shift
|
||||
shiftDown = true;
|
||||
}
|
||||
|
||||
if ( window['currentTest'] && window['currentTest']['onKeyDown'] )
|
||||
window['currentTest']['onKeyDown'](canvas, evt);
|
||||
|
||||
draw();
|
||||
}
|
||||
|
||||
function onKeyUp(canvas, evt) {
|
||||
if ( evt.keyCode == 16 ) {//shift
|
||||
shiftDown = false;
|
||||
}
|
||||
|
||||
if ( window['currentTest'] && window['currentTest']['onKeyUp'] )
|
||||
window['currentTest']['onKeyUp'](canvas, evt);
|
||||
}
|
||||
|
||||
function zoomIn() {
|
||||
var currentViewCenterWorld = getWorldPointFromPixelPoint( viewCenterPixel );
|
||||
PTM *= 1.1;
|
||||
var newViewCenterWorld = getWorldPointFromPixelPoint( viewCenterPixel );
|
||||
canvasOffset.x += (newViewCenterWorld.x-currentViewCenterWorld.x) * PTM;
|
||||
canvasOffset.y -= (newViewCenterWorld.y-currentViewCenterWorld.y) * PTM;
|
||||
draw();
|
||||
}
|
||||
|
||||
function zoomOut() {
|
||||
var currentViewCenterWorld = getWorldPointFromPixelPoint( viewCenterPixel );
|
||||
PTM /= 1.1;
|
||||
var newViewCenterWorld = getWorldPointFromPixelPoint( viewCenterPixel );
|
||||
canvasOffset.x += (newViewCenterWorld.x-currentViewCenterWorld.x) * PTM;
|
||||
canvasOffset.y -= (newViewCenterWorld.y-currentViewCenterWorld.y) * PTM;
|
||||
draw();
|
||||
}
|
||||
|
||||
function updateDebugDrawCheckboxesFromWorld() {
|
||||
var flags = myDebugDraw.GetFlags();
|
||||
document.getElementById('drawShapesCheck').checked = (( flags & e_shapeBit ) != 0);
|
||||
document.getElementById('drawJointsCheck').checked = (( flags & e_jointBit ) != 0);
|
||||
document.getElementById('drawAABBsCheck').checked = (( flags & e_aabbBit ) != 0);
|
||||
//document.getElementById('drawPairsCheck').checked = (( flags & e_pairBit ) != 0);
|
||||
document.getElementById('drawTransformsCheck').checked = (( flags & e_centerOfMassBit ) != 0);
|
||||
}
|
||||
|
||||
function updateWorldFromDebugDrawCheckboxes() {
|
||||
var flags = 0;
|
||||
if ( document.getElementById('drawShapesCheck').checked )
|
||||
flags |= e_shapeBit;
|
||||
if ( document.getElementById('drawJointsCheck').checked )
|
||||
flags |= e_jointBit;
|
||||
if ( document.getElementById('drawAABBsCheck').checked )
|
||||
flags |= e_aabbBit;
|
||||
/*if ( document.getElementById('drawPairsCheck').checked )
|
||||
flags |= e_pairBit;*/
|
||||
if ( document.getElementById('drawTransformsCheck').checked )
|
||||
flags |= e_centerOfMassBit;
|
||||
myDebugDraw.SetFlags( flags );
|
||||
}
|
||||
|
||||
function updateContinuousRefreshStatus() {
|
||||
showStats = ( document.getElementById('showStatsCheck').checked );
|
||||
if ( !showStats ) {
|
||||
var fbSpan = document.getElementById('feedbackSpan');
|
||||
fbSpan.innerHTML = "";
|
||||
}
|
||||
else
|
||||
updateStats();
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
canvas = document.getElementById("canvas");
|
||||
context = canvas.getContext( '2d' );
|
||||
|
||||
canvasOffset.x = canvas.width/2;
|
||||
canvasOffset.y = canvas.height/2;
|
||||
|
||||
canvas.addEventListener('mousemove', function(evt) {
|
||||
onMouseMove(canvas,evt);
|
||||
}, false);
|
||||
|
||||
canvas.addEventListener('mousedown', function(evt) {
|
||||
onMouseDown(canvas,evt);
|
||||
}, false);
|
||||
|
||||
canvas.addEventListener('mouseup', function(evt) {
|
||||
onMouseUp(canvas,evt);
|
||||
}, false);
|
||||
|
||||
canvas.addEventListener('mouseout', function(evt) {
|
||||
onMouseOut(canvas,evt);
|
||||
}, false);
|
||||
|
||||
canvas.addEventListener('keydown', function(evt) {
|
||||
onKeyDown(canvas,evt);
|
||||
}, false);
|
||||
|
||||
canvas.addEventListener('keyup', function(evt) {
|
||||
onKeyUp(canvas,evt);
|
||||
}, false);
|
||||
|
||||
myDebugDraw = new b2DebugDraw();
|
||||
myDebugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
|
||||
myDebugDraw.SetDrawScale(1.0);
|
||||
myDebugDraw.SetFillAlpha(0.5);
|
||||
myDebugDraw.SetLineThickness(1.0);
|
||||
myDebugDraw.SetXFormScale(0.25);
|
||||
myDebugDraw.SetFlags(b2DebugDraw.e_shapeBit /*| b2DebugDraw.e_jointBit*/);
|
||||
|
||||
originTransform = new b2Transform();
|
||||
|
||||
var MouseDownQueryCallback = function() {
|
||||
this.m_fixture = null;
|
||||
this.m_point = new b2Vec2();
|
||||
}
|
||||
MouseDownQueryCallback.prototype.ReportFixture = function(fixture) {
|
||||
if(fixture.GetBody().GetType() == 2) { //dynamic bodies only
|
||||
if ( fixture.TestPoint(this.m_point) ) {
|
||||
this.m_fixture = fixture;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
mouseDownQueryCallback = new MouseDownQueryCallback();
|
||||
|
||||
|
||||
var VisibleFixturesQueryCallback = function() {
|
||||
this.m_fixtures = [];
|
||||
}
|
||||
VisibleFixturesQueryCallback.prototype.ReportFixture = function(fixture) {
|
||||
this.m_fixtures.push(fixture);
|
||||
return true;
|
||||
};
|
||||
|
||||
viewAABB = new b2AABB();
|
||||
visibleFixturesQueryCallback = new VisibleFixturesQueryCallback();
|
||||
}
|
||||
|
||||
function changeTest() {
|
||||
resetScene();
|
||||
if ( window['currentTest'] && window['currentTest']['setNiceViewCenter'] )
|
||||
window['currentTest']['setNiceViewCenter']();
|
||||
updateDebugDrawCheckboxesFromWorld();
|
||||
draw();
|
||||
}
|
||||
|
||||
function createWorld() {
|
||||
|
||||
var sceneInfoDiv = document.getElementById('sceneinfo');
|
||||
var commentsDiv = document.getElementById('testcomments');
|
||||
sceneInfoDiv.innerHTML = "Loading...";
|
||||
commentsDiv.innerHTML = "";
|
||||
|
||||
if ( world != null )
|
||||
//Box2D.destroy(world);
|
||||
world = null;
|
||||
|
||||
world = new b2World( new b2Vec2(0.0, -10.0) );
|
||||
//world = new Box2D.Dynamics.b2World(new Box2D.Common.Math.b2Vec2(0, 9.8) /* gravity */, true /* allowSleep */);
|
||||
world.SetDebugDraw(myDebugDraw);
|
||||
|
||||
mouseJointGroundBody = world.CreateBody( new b2BodyDef() );
|
||||
|
||||
var e = document.getElementById("testSelection");
|
||||
var v = e.options[e.selectedIndex].value;
|
||||
|
||||
eval( "window['currentTest']= new "+v+"();" );
|
||||
|
||||
window['currentTest']['setup']();
|
||||
}
|
||||
|
||||
function getWorldInfo() {
|
||||
var numBodies = 0;
|
||||
var numFixtures = 0;
|
||||
var numJoints = 0;
|
||||
for (b = world.m_bodyList; b; b = b.m_next) {
|
||||
numBodies++;
|
||||
for (f = b.m_fixtureList; f; f = f.m_next)
|
||||
numFixtures++;
|
||||
}
|
||||
for (j = world.m_jointList; j; j = j.m_next)
|
||||
numJoints++;
|
||||
return ""+numBodies+" bodies, "+numFixtures+" fixtures, "+numJoints+" joints";
|
||||
}
|
||||
|
||||
var resettingScene = false;
|
||||
function resetScene() {
|
||||
resettingScene = true;
|
||||
createWorld();
|
||||
draw();
|
||||
}
|
||||
|
||||
//the RUBE scenes are loaded via jQuery post, so the draw() call above usually
|
||||
//does not catch them. Call this at the end of the post function.
|
||||
function doAfterLoading() {
|
||||
|
||||
if ( world.images ) {
|
||||
for (var i = 0; i < world.images.length; i++) {
|
||||
var imageObj = new Image();
|
||||
imageObj.src = world.images[i].file;
|
||||
world.images[i].imageObj = imageObj;
|
||||
}
|
||||
}
|
||||
|
||||
var sceneInfoDiv = document.getElementById('sceneinfo');
|
||||
sceneInfoDiv.innerHTML = "Scene info: "+getWorldInfo();;
|
||||
|
||||
var comments = "";
|
||||
if ( window['currentTest']['getComments'] )
|
||||
comments = window['currentTest']['getComments']();
|
||||
var commentsDiv = document.getElementById('testcomments');
|
||||
commentsDiv.innerHTML = "About: "+comments;
|
||||
|
||||
resettingScene = false;
|
||||
|
||||
draw();
|
||||
}
|
||||
|
||||
function step(timestamp) {
|
||||
|
||||
if ( resettingScene )
|
||||
return;
|
||||
|
||||
if ( window['currentTest'] && window['currentTest']['step'] )
|
||||
window['currentTest']['step']();
|
||||
|
||||
if ( ! showStats ) {
|
||||
world.Step(1/60, 10, 6);
|
||||
draw();
|
||||
//logBodyPositions();
|
||||
return;
|
||||
}
|
||||
|
||||
var current = Date.now();
|
||||
world.Step(1/60, 10, 6);
|
||||
var frametime = (Date.now() - current);
|
||||
frameTime60 = frameTime60 * (59/60) + frametime * (1/60);
|
||||
|
||||
draw();
|
||||
statusUpdateCounter++;
|
||||
if ( statusUpdateCounter > 20 ) {
|
||||
updateStats();
|
||||
statusUpdateCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function setColorFromBodyType(color, b) {
|
||||
if (b.IsActive() == false)
|
||||
color.Set(0.5, 0.5, 0.3);
|
||||
else if (b.GetType() == b2_staticBody)
|
||||
color.Set(0.5, 0.9, 0.5);
|
||||
else if (b.GetType() == b2_kinematicBody)
|
||||
color.Set(0.5, 0.5, 0.9);
|
||||
else if (b.IsAwake() == false)
|
||||
color.Set(0.6, 0.6, 0.6);
|
||||
else
|
||||
color.Set(0.9, 0.7, 0.7);
|
||||
}
|
||||
|
||||
//for drawing polygons as one path
|
||||
function drawLinePolygon(poly, xf) {
|
||||
var vertexCount = parseInt(poly.GetVertexCount());
|
||||
var localVertices = poly.GetVertices();
|
||||
var vertices = new Vector(vertexCount);
|
||||
for (var i = 0; i < vertexCount; ++i) {
|
||||
vertices[i] = b2Math.MulX(xf, localVertices[i]);
|
||||
}
|
||||
var drawScale = myDebugDraw.m_drawScale;
|
||||
context.moveTo(vertices[0].x * drawScale, vertices[0].y * drawScale);
|
||||
for (var i = 1; i < vertexCount; i++) {
|
||||
context.lineTo(vertices[i].x * drawScale, vertices[i].y * drawScale);
|
||||
}
|
||||
context.lineTo(vertices[0].x * drawScale, vertices[0].y * drawScale);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
//black background
|
||||
context.fillStyle = 'rgb(0,0,0)';
|
||||
context.fillRect( 0, 0, canvas.width, canvas.height );
|
||||
|
||||
context.save();
|
||||
context.translate(canvasOffset.x, canvasOffset.y);
|
||||
context.scale(1,-1);
|
||||
context.scale(PTM,PTM);
|
||||
context.lineWidth /= PTM;
|
||||
|
||||
//draw images
|
||||
context.save();
|
||||
context.scale(1,-1);
|
||||
if ( world.images ) {
|
||||
for (var i = 0; i < world.images.length; i++) {
|
||||
var imageObj = world.images[i].imageObj;
|
||||
context.save();
|
||||
if ( world.images[i].body ) {
|
||||
//body position in world
|
||||
var bodyPos = world.images[i].body.GetPosition();
|
||||
context.translate(bodyPos.x, -bodyPos.y);
|
||||
context.rotate(-world.images[i].body.GetAngle());
|
||||
|
||||
//image position in body
|
||||
var imageLocalCenter = world.images[i].center;
|
||||
context.translate(imageLocalCenter.x, -imageLocalCenter.y);
|
||||
context.rotate(-world.images[i].angle);
|
||||
}
|
||||
var ratio = 1 / imageObj.height;
|
||||
ratio *= world.images[i].scale;
|
||||
context.scale(ratio, ratio);
|
||||
context.translate(-imageObj.width / 2, -imageObj.height / 2);
|
||||
context.drawImage(imageObj, 0, 0);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
context.restore();
|
||||
|
||||
myDebugDraw.DrawTransform(originTransform);
|
||||
|
||||
var flags = myDebugDraw.GetFlags();
|
||||
myDebugDraw.SetFlags(flags & ~e_shapeBit);
|
||||
world.DrawDebugData();
|
||||
myDebugDraw.SetFlags(flags);
|
||||
|
||||
if (( flags & e_shapeBit ) != 0) {
|
||||
//query the world for visible fixtures
|
||||
var currentViewCenterWorld = getWorldPointFromPixelPoint( viewCenterPixel );
|
||||
var viewHalfwidth = 0.5 * canvas.width / PTM;
|
||||
var viewHalfheight = 0.5 * canvas.height / PTM;
|
||||
viewAABB.lowerBound.Set(currentViewCenterWorld.x - viewHalfwidth, currentViewCenterWorld.y - viewHalfheight);
|
||||
viewAABB.upperBound.Set(currentViewCenterWorld.x + viewHalfwidth, currentViewCenterWorld.y + viewHalfheight);
|
||||
visibleFixturesQueryCallback.m_fixtures = [];
|
||||
world.QueryAABB(visibleFixturesQueryCallback, viewAABB);
|
||||
var f, b, xf, s;
|
||||
var color = new b2Color(0, 0, 0);
|
||||
var circleFixtures = [];
|
||||
var polygonFixtures = [];
|
||||
var staticPolygonFixtures = [];
|
||||
var kinematicPolygonFixtures = [];
|
||||
var dynamicPolygonFixtures = [];
|
||||
for (var i = 0; i < visibleFixturesQueryCallback.m_fixtures.length; i++) {
|
||||
f = visibleFixturesQueryCallback.m_fixtures[i];
|
||||
s = f.GetShape();
|
||||
if ( s.GetType() == b2Shape.e_circleShape ) {
|
||||
circleFixtures.push(f);
|
||||
}
|
||||
else if ( s.GetType() == b2Shape.e_polygonShape ) {
|
||||
polygonFixtures.push(f);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < circleFixtures.length; i++) {
|
||||
f = circleFixtures[i];
|
||||
s = f.GetShape();
|
||||
b = f.GetBody();
|
||||
xf = b.GetTransform();
|
||||
setColorFromBodyType(color, b);
|
||||
world.DrawShape(s, xf, color);
|
||||
}
|
||||
for (var i = 0; i < polygonFixtures.length; i++) {
|
||||
f = polygonFixtures[i];
|
||||
b = f.GetBody();
|
||||
if (b.GetType() == b2_staticBody)
|
||||
staticPolygonFixtures.push(f);
|
||||
else if (b.GetType() == b2_kinematicBody)
|
||||
kinematicPolygonFixtures.push(f);
|
||||
else
|
||||
dynamicPolygonFixtures.push(f);
|
||||
}
|
||||
context.strokeStyle = "rgb(128,230,128)";
|
||||
context.beginPath();//draw all static polygons as one path
|
||||
for (var i = 0; i < staticPolygonFixtures.length; i++) {
|
||||
f = staticPolygonFixtures[i];
|
||||
s = f.GetShape();
|
||||
b = f.GetBody();
|
||||
xf = b.GetTransform();
|
||||
//world.DrawShape(s, xf, color);
|
||||
drawLinePolygon(s, xf);
|
||||
}
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
|
||||
context.strokeStyle = "rgb(128,128,230)";
|
||||
context.beginPath();//draw all kinematic polygons as one path
|
||||
for (var i = 0; i < kinematicPolygonFixtures.length; i++) {
|
||||
f = kinematicPolygonFixtures[i];
|
||||
s = f.GetShape();
|
||||
b = f.GetBody();
|
||||
xf = b.GetTransform();
|
||||
//world.DrawShape(s, xf, color);
|
||||
drawLinePolygon(s, xf);
|
||||
}
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
|
||||
context.strokeStyle = "rgb(230,178,178)";
|
||||
context.beginPath();//draw all dynamic polygons as one path
|
||||
for (var i = 0; i < dynamicPolygonFixtures.length; i++) {
|
||||
f = dynamicPolygonFixtures[i];
|
||||
s = f.GetShape();
|
||||
b = f.GetBody();
|
||||
xf = b.GetTransform();
|
||||
//world.DrawShape(s, xf, color);
|
||||
drawLinePolygon(s, xf);
|
||||
}
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
if ( mouseJoint != null ) {
|
||||
//mouse joint is not drawn with regular joints in debug draw
|
||||
var p1 = mouseJoint.GetAnchorB();
|
||||
var p2 = mouseJoint.GetTarget();
|
||||
context.strokeStyle = 'rgb(204,204,204)';
|
||||
context.beginPath();
|
||||
context.moveTo(p1.x,p1.y);
|
||||
context.lineTo(p2.x,p2.y);
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
function updateStats() {
|
||||
if ( ! showStats )
|
||||
return;
|
||||
var currentViewCenterWorld = getWorldPointFromPixelPoint( viewCenterPixel );
|
||||
var fbSpan = document.getElementById('feedbackSpan');
|
||||
fbSpan.innerHTML =
|
||||
"Status: "+(run?'running':'paused') +
|
||||
"<br>Physics step time (average of last 60 steps): "+myRound(frameTime60,2)+"ms" +
|
||||
//"<br>Mouse down: "+mouseDown +
|
||||
"<br>PTM: "+myRound(PTM,2) +
|
||||
"<br>View center: "+myRound(currentViewCenterWorld.x,3)+", "+myRound(currentViewCenterWorld.y,3) +
|
||||
//"<br>Canvas offset: "+myRound(canvasOffset.x,0)+", "+myRound(canvasOffset.y,0) +
|
||||
"<br>Mouse pos (pixel): "+mousePosPixel.x+", "+mousePosPixel.y +
|
||||
"<br>Mouse pos (world): "+myRound(mousePosWorld.x,3)+", "+myRound(mousePosWorld.y,3);
|
||||
}
|
||||
|
||||
window.requestAnimFrame = (function(){
|
||||
return window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function( callback ){
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
})();
|
||||
|
||||
function animate() {
|
||||
if ( run )
|
||||
requestAnimFrame( animate );
|
||||
step();
|
||||
}
|
||||
|
||||
function pause() {
|
||||
run = !run;
|
||||
if (run)
|
||||
animate();
|
||||
updateStats();
|
||||
}
|
||||
|
||||
//console.log(A.a);
|
||||
//console.log(Box2D.Dynamics);
|
||||
//console.log(Box2D.Dynamics.b2BodyDef);
|
||||
|
||||
var b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
|
||||
b2EdgeChainDef = Box2D.Collision.Shapes.b2EdgeChainDef,
|
||||
b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape,
|
||||
b2MassData = Box2D.Collision.Shapes.b2MassData,
|
||||
b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
|
||||
b2Shape = Box2D.Collision.Shapes.b2Shape,
|
||||
b2CircleContact = Box2D.Dynamics.Contacts.b2CircleContact,
|
||||
b2Contact = Box2D.Dynamics.Contacts.b2Contact,
|
||||
b2ContactConstraint = Box2D.Dynamics.Contacts.b2ContactConstraint,
|
||||
b2ContactConstraintPoint = Box2D.Dynamics.Contacts.b2ContactConstraintPoint,
|
||||
b2ContactEdge = Box2D.Dynamics.Contacts.b2ContactEdge,
|
||||
b2ContactFactory = Box2D.Dynamics.Contacts.b2ContactFactory,
|
||||
b2ContactRegister = Box2D.Dynamics.Contacts.b2ContactRegister,
|
||||
b2ContactResult = Box2D.Dynamics.Contacts.b2ContactResult,
|
||||
b2ContactSolver = Box2D.Dynamics.Contacts.b2ContactSolver,
|
||||
b2EdgeAndCircleContact = Box2D.Dynamics.Contacts.b2EdgeAndCircleContact,
|
||||
b2NullContact = Box2D.Dynamics.Contacts.b2NullContact,
|
||||
b2PolyAndCircleContact = Box2D.Dynamics.Contacts.b2PolyAndCircleContact,
|
||||
b2PolyAndEdgeContact = Box2D.Dynamics.Contacts.b2PolyAndEdgeContact,
|
||||
b2PolygonContact = Box2D.Dynamics.Contacts.b2PolygonContact,
|
||||
b2PositionSolverManifold = Box2D.Dynamics.Contacts.b2PositionSolverManifold,
|
||||
b2Body = Box2D.Dynamics.b2Body,
|
||||
b2_staticBody = Box2D.Dynamics.b2Body.b2_staticBody,
|
||||
b2_kinematicBody = Box2D.Dynamics.b2Body.b2_kinematicBody,
|
||||
b2_dynamicBody = Box2D.Dynamics.b2Body.b2_dynamicBody,
|
||||
b2BodyDef = Box2D.Dynamics.b2BodyDef,
|
||||
b2ContactFilter = Box2D.Dynamics.b2ContactFilter,
|
||||
b2ContactImpulse = Box2D.Dynamics.b2ContactImpulse,
|
||||
b2ContactListener = Box2D.Dynamics.b2ContactListener,
|
||||
b2ContactManager = Box2D.Dynamics.b2ContactManager,
|
||||
b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
|
||||
b2DestructionListener = Box2D.Dynamics.b2DestructionListener,
|
||||
b2FilterData = Box2D.Dynamics.b2FilterData,
|
||||
b2Fixture = Box2D.Dynamics.b2Fixture,
|
||||
b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
|
||||
b2Island = Box2D.Dynamics.b2Island,
|
||||
b2TimeStep = Box2D.Dynamics.b2TimeStep,
|
||||
b2World = Box2D.Dynamics.b2World,
|
||||
b2Color = Box2D.Common.b2Color,
|
||||
b2internal = Box2D.Common.b2internal,
|
||||
b2Settings = Box2D.Common.b2Settings,
|
||||
b2Mat22 = Box2D.Common.Math.b2Mat22,
|
||||
b2Mat33 = Box2D.Common.Math.b2Mat33,
|
||||
b2Math = Box2D.Common.Math.b2Math,
|
||||
b2Sweep = Box2D.Common.Math.b2Sweep,
|
||||
b2Transform = Box2D.Common.Math.b2Transform,
|
||||
b2Vec2 = Box2D.Common.Math.b2Vec2,
|
||||
b2Vec3 = Box2D.Common.Math.b2Vec3,
|
||||
b2AABB = Box2D.Collision.b2AABB,
|
||||
b2Bound = Box2D.Collision.b2Bound,
|
||||
b2BoundValues = Box2D.Collision.b2BoundValues,
|
||||
b2Collision = Box2D.Collision.b2Collision,
|
||||
b2ContactID = Box2D.Collision.b2ContactID,
|
||||
b2ContactPoint = Box2D.Collision.b2ContactPoint,
|
||||
b2Distance = Box2D.Collision.b2Distance,
|
||||
b2DistanceInput = Box2D.Collision.b2DistanceInput,
|
||||
b2DistanceOutput = Box2D.Collision.b2DistanceOutput,
|
||||
b2DistanceProxy = Box2D.Collision.b2DistanceProxy,
|
||||
b2DynamicTree = Box2D.Collision.b2DynamicTree,
|
||||
b2DynamicTreeBroadPhase = Box2D.Collision.b2DynamicTreeBroadPhase,
|
||||
b2DynamicTreeNode = Box2D.Collision.b2DynamicTreeNode,
|
||||
b2DynamicTreePair = Box2D.Collision.b2DynamicTreePair,
|
||||
b2Manifold = Box2D.Collision.b2Manifold,
|
||||
b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint,
|
||||
b2Point = Box2D.Collision.b2Point,
|
||||
b2RayCastInput = Box2D.Collision.b2RayCastInput,
|
||||
b2RayCastOutput = Box2D.Collision.b2RayCastOutput,
|
||||
b2Segment = Box2D.Collision.b2Segment,
|
||||
b2SeparationFunction = Box2D.Collision.b2SeparationFunction,
|
||||
b2Simplex = Box2D.Collision.b2Simplex,
|
||||
b2SimplexCache = Box2D.Collision.b2SimplexCache,
|
||||
b2SimplexVertex = Box2D.Collision.b2SimplexVertex,
|
||||
b2TimeOfImpact = Box2D.Collision.b2TimeOfImpact,
|
||||
b2TOIInput = Box2D.Collision.b2TOIInput,
|
||||
b2WorldManifold = Box2D.Collision.b2WorldManifold,
|
||||
ClipVertex = Box2D.Collision.ClipVertex,
|
||||
Features = Box2D.Collision.Features,
|
||||
IBroadPhase = Box2D.Collision.IBroadPhase,
|
||||
b2Joint = Box2D.Dynamics.Joints.b2Joint,
|
||||
b2JointDef = Box2D.Dynamics.Joints.b2JointDef,
|
||||
b2JointEdge = Box2D.Dynamics.Joints.b2JointEdge,
|
||||
b2LineJoint = Box2D.Dynamics.Joints.b2LineJoint,
|
||||
b2LineJointDef = Box2D.Dynamics.Joints.b2LineJointDef,
|
||||
b2MouseJoint = Box2D.Dynamics.Joints.b2MouseJoint,
|
||||
b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef,
|
||||
b2PrismaticJoint = Box2D.Dynamics.Joints.b2PrismaticJoint,
|
||||
b2PrismaticJointDef = Box2D.Dynamics.Joints.b2PrismaticJointDef,
|
||||
b2PulleyJoint = Box2D.Dynamics.Joints.b2PulleyJoint,
|
||||
b2PulleyJointDef = Box2D.Dynamics.Joints.b2PulleyJointDef,
|
||||
b2RevoluteJoint = Box2D.Dynamics.Joints.b2RevoluteJoint,
|
||||
b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef,
|
||||
b2WeldJoint = Box2D.Dynamics.Joints.b2WeldJoint,
|
||||
b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef,
|
||||
b2DistanceJoint = Box2D.Dynamics.Joints.b2DistanceJoint,
|
||||
b2DistanceJointDef = Box2D.Dynamics.Joints.b2DistanceJointDef,
|
||||
b2FrictionJoint = Box2D.Dynamics.Joints.b2FrictionJoint,
|
||||
b2FrictionJointDef = Box2D.Dynamics.Joints.b2FrictionJointDef;
|
||||
|
||||
window['onload'] = function doOnload() {
|
||||
/*
|
||||
using(Box2D.Common, "b2.+");
|
||||
using(Box2D.Common.Math, "b2.+");
|
||||
using(Box2D.Collision, "b2.+");
|
||||
using(Box2D.Collision.Shapes, "b2.+");
|
||||
using(Box2D.Dynamics, "b2.+");
|
||||
using(Box2D.Dynamics.Joints, "b2.+");
|
||||
using(Box2D.Dynamics.b2Body, "b2.+");//b2_dynamicBody etc
|
||||
*/
|
||||
init();
|
||||
changeTest();
|
||||
animate();
|
||||
}
|
||||
|
||||
//these need to be kept global for closure advanced optimization
|
||||
window['currentTest'] = null;
|
||||
//window['Box2D'] = Box2D;
|
||||
|
||||
/*
|
||||
String.prototype.endsWith = function(suffix) {
|
||||
return this.indexOf(suffix, this.length - suffix.length) !== -1;
|
||||
};
|
||||
|
||||
function ttt(ns, recurse) {
|
||||
if ( typeof recurse === 'undefined' ) recurse = true;
|
||||
var parts = ns.split(".");
|
||||
var base = "window";
|
||||
for (i=0;i<parts.length;i++)
|
||||
base += "['"+parts[i]+"']";
|
||||
//if ( ns.endsWith('prototype') )
|
||||
// recurse = false;
|
||||
for (var name in eval(ns)) {
|
||||
console.log(base+"['"+name+"'] = "+ns+"."+name+";");
|
||||
//if ( typeof eval(ns+"."+name) == 'function' ) {
|
||||
if ( recurse )
|
||||
ttt(ns+"."+name+".prototype", true);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
//ttt('Box2D.Collision');
|
||||
//ttt('Box2D.Collision.Shapes');
|
||||
//ttt('Box2D.Common');
|
||||
//ttt('Box2D.Common.Math');
|
||||
//ttt('Box2D.Dynamics');
|
||||
//ttt('Box2D.Dynamics.Contacts');
|
||||
//ttt('Box2D.Dynamics.Joints');
|
||||
*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue