Last active
April 10, 2019 15:14
-
-
Save kenwebb/7fca7db5fe7767d60c116e80bdeaf1a8 to your computer and use it in GitHub Desktop.
Physics Engines - Planck.js
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
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Wed Apr 10 2019 11:13:04 GMT-0400 (Eastern Daylight Time)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: Physics Engines - Planck.js | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 7fca7db5fe7767d60c116e80bdeaf1a8 | |
Keywords: | |
My Notes | |
-------- | |
April 10, 2019 | |
To Run a Xholon app: | |
------------------- | |
http://127.0.0.1:8888/Xholon.html?app=Physics%20Engines&src=lstr&gui=clsc&jslib=physics/planck-with-testbed | |
All of the following examples work, unless otherwise noted. | |
//then try the following in Dev Tools (from ref[1] main page): | |
planck.testbed(function(testbed) { | |
var world = planck.World({ | |
gravity: planck.Vec2(0, -10) | |
}); | |
console.log(world); | |
// rest of your code | |
var ground = world.createBody({ | |
type: 'static', | |
position: planck.Vec2(2, 5) | |
}); | |
ground.createFixture({ | |
shape: planck.Edge(planck.Vec2(-40.0, 0.0),planck.Vec2(40.0, 0.0)) | |
}); | |
return world; // make sure you return the world | |
}); | |
// another example (HeavyOnLight.js from ref[1] examples): | |
planck.testbed('HeavyOnLight', function(testbed) { | |
var pl = planck, Vec2 = pl.Vec2; | |
var world = new pl.World(Vec2(0, -10)); | |
world.createBody().createFixture(pl.Edge(Vec2(-40.0, 0.0), Vec2(40.0, 0.0))); | |
world.createDynamicBody(Vec2(0.0, 4.5)).createFixture(pl.Circle(0.5), 10.0); | |
world.createDynamicBody(Vec2(0.0, 10.0)).createFixture(pl.Circle(5.0), 10.0); | |
return world; | |
}); | |
// another | |
planck.testbed('Chain', function(testbed) { | |
var pl = planck, Vec2 = pl.Vec2; | |
var world = pl.World(Vec2(0, -10)); | |
var ground = world.createBody(); | |
ground.createFixture(pl.Edge(Vec2(-40.0, 0.0), Vec2(40.0, 0.0)), 0.0); | |
var shape = pl.Box(0.6, 0.125); | |
var y = 25.0; | |
var prevBody = ground; | |
for (var i = 0; i < 30; ++i) { | |
var body = world.createDynamicBody(Vec2(0.5 + i, y)); | |
body.createFixture(shape, { | |
density: 20.0, | |
friction: 0.2, | |
}); | |
var anchor = Vec2(i, y); | |
world.createJoint(pl.RevoluteJoint({ | |
collideConnected: false, | |
}, prevBody, body, anchor)); | |
prevBody = body; | |
} | |
return world; | |
}); | |
// ===================================================== | |
// Car example | |
planck.testbed('Car', function(testbed) { | |
testbed.speed = 1.3; | |
testbed.hz = 50; | |
var pl = planck, Vec2 = pl.Vec2; | |
var world = new pl.World({ | |
gravity : Vec2(0, -10) | |
}); | |
// wheel spring settings | |
var HZ = 4.0; | |
var ZETA = 0.7; | |
var SPEED = 50.0; | |
var ground = world.createBody(); | |
var groundFD = { | |
density : 0.0, | |
friction : 0.6 | |
}; | |
ground.createFixture(pl.Edge(Vec2(-20.0, 0.0), Vec2(20.0, 0.0)), groundFD); | |
var hs = [ 0.25, 1.0, 4.0, 0.0, 0.0, -1.0, -2.0, -2.0, -1.25, 0.0 ]; | |
var x = 20.0, y1 = 0.0, dx = 5.0; | |
for (var i = 0; i < 10; ++i) { | |
var y2 = hs[i]; | |
ground.createFixture(pl.Edge(Vec2(x, y1), Vec2(x + dx, y2)), groundFD); | |
y1 = y2; | |
x += dx; | |
} | |
for (var i = 0; i < 10; ++i) { | |
var y2 = hs[i]; | |
ground.createFixture(pl.Edge(Vec2(x, y1), Vec2(x + dx, y2)), groundFD); | |
y1 = y2; | |
x += dx; | |
} | |
ground.createFixture(pl.Edge(Vec2(x, 0.0), Vec2(x + 40.0, 0.0)), groundFD); | |
x += 80.0; | |
ground.createFixture(pl.Edge(Vec2(x, 0.0), Vec2(x + 40.0, 0.0)), groundFD); | |
x += 40.0; | |
ground.createFixture(pl.Edge(Vec2(x, 0.0), Vec2(x + 10.0, 5.0)), groundFD); | |
x += 20.0; | |
ground.createFixture(pl.Edge(Vec2(x, 0.0), Vec2(x + 40.0, 0.0)), groundFD); | |
x += 40.0; | |
ground.createFixture(pl.Edge(Vec2(x, 0.0), Vec2(x, 20.0)), groundFD); | |
// Teeter | |
var teeter = world.createDynamicBody(Vec2(140.0, 1.0)); | |
teeter.createFixture(pl.Box(10.0, 0.25), 1.0); | |
world.createJoint(pl.RevoluteJoint({ | |
lowerAngle : -8.0 * Math.PI / 180.0, | |
upperAngle : 8.0 * Math.PI / 180.0, | |
enableLimit : true | |
}, ground, teeter, teeter.getPosition())); | |
teeter.applyAngularImpulse(100.0, true); | |
// Bridge | |
var bridgeFD = {}; | |
bridgeFD.density = 1.0; | |
bridgeFD.friction = 0.6; | |
var prevBody = ground; | |
for (var i = 0; i < 20; ++i) { | |
var bridgeBlock = world.createDynamicBody(Vec2(161.0 + 2.0 * i, -0.125)); | |
bridgeBlock.createFixture(pl.Box(1.0, 0.125), bridgeFD); | |
world.createJoint(pl.RevoluteJoint({}, prevBody, bridgeBlock, Vec2(160.0 + 2.0 * i, -0.125))); | |
prevBody = bridgeBlock; | |
} | |
world.createJoint(pl.RevoluteJoint({}, prevBody, ground, Vec2(160.0 + 2.0 * i, -0.125))); | |
// Boxes | |
var box = pl.Box(0.5, 0.5); | |
world.createDynamicBody(Vec2(230.0, 0.5)) | |
.createFixture(box, 0.5); | |
world.createDynamicBody(Vec2(230.0, 1.5)) | |
.createFixture(box, 0.5); | |
world.createDynamicBody(Vec2(230.0, 2.5)) | |
.createFixture(box, 0.5); | |
world.createDynamicBody(Vec2(230.0, 3.5)) | |
.createFixture(box, 0.5); | |
world.createDynamicBody(Vec2(230.0, 4.5)) | |
.createFixture(box, 0.5); | |
// Car | |
var car = world.createDynamicBody(Vec2(0.0, 1.0)); | |
car.createFixture(pl.Polygon([ | |
Vec2(-1.5, -0.5), | |
Vec2(1.5, -0.5), | |
Vec2(1.5, 0.0), | |
Vec2(0.0, 0.9), | |
Vec2(-1.15, 0.9), | |
Vec2(-1.5, 0.2) | |
]), 1.0); | |
var wheelFD = {}; | |
wheelFD.density = 1.0; | |
wheelFD.friction = 0.9; | |
var wheelBack = world.createDynamicBody(Vec2(-1.0, 0.35)); | |
wheelBack.createFixture(pl.Circle(0.4), wheelFD); | |
var wheelFront = world.createDynamicBody(Vec2(1.0, 0.4)); | |
wheelFront.createFixture(pl.Circle(0.4), wheelFD); | |
var springBack = world.createJoint(pl.WheelJoint({ | |
motorSpeed : 0.0, | |
maxMotorTorque : 20.0, | |
enableMotor : true, | |
frequencyHz : HZ, | |
dampingRatio : ZETA | |
}, car, wheelBack, wheelBack.getPosition(), Vec2(0.0, 1.0))); | |
var springFront = world.createJoint(pl.WheelJoint({ | |
motorSpeed : 0.0, | |
maxMotorTorque : 10.0, | |
enableMotor : false, | |
frequencyHz : HZ, | |
dampingRatio : ZETA | |
}, car, wheelFront, wheelFront.getPosition(), Vec2(0.0, 1.0))); | |
testbed.keydown = function() { | |
if (testbed.activeKeys.down) { | |
HZ = Math.max(0.0, HZ - 1.0); | |
springBack.setSpringFrequencyHz(HZ); | |
springFront.setSpringFrequencyHz(HZ); | |
} else if (testbed.activeKeys.up) { | |
HZ += 1.0; | |
springBack.setSpringFrequencyHz(HZ); | |
springFront.setSpringFrequencyHz(HZ); | |
} | |
}; | |
testbed.step = function() { | |
if (testbed.activeKeys.right && testbed.activeKeys.left) { | |
springBack.setMotorSpeed(0); | |
springBack.enableMotor(true); | |
} else if (testbed.activeKeys.right) { | |
springBack.setMotorSpeed(-SPEED); | |
springBack.enableMotor(true); | |
} else if (testbed.activeKeys.left) { | |
springBack.setMotorSpeed(+SPEED); | |
springBack.enableMotor(true); | |
} else { | |
springBack.setMotorSpeed(0); | |
springBack.enableMotor(false); | |
} | |
var cp = car.getPosition(); | |
if (cp.x > testbed.x + 10) { | |
testbed.x = cp.x - 10; | |
} else if (cp.x < testbed.x - 10) { | |
testbed.x = cp.x + 10; | |
} | |
}; | |
testbed.info('←/→: Accelerate car, ↑/↓: Change spring frequency'); | |
return world; | |
}); | |
// ===================================================== | |
see also: Physics Engines - Planck.js | |
References | |
---------- | |
(1) https://github.com/shakiba/planck.js | |
2D JavaScript Physics Engine | |
Planck.js is JavaScript rewrite of Box2D physics engine for cross-platform HTML5 game development. | |
(2) http://piqnt.com/planck.js/ | |
]]></Notes> | |
<_-.XholonClass> | |
<!-- domain objects --> | |
<PhysicalSystem/> | |
<Block/> | |
<Brick/> | |
<!-- quantities --> | |
<Height superClass="Quantity"/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
<Block> | |
<port name="height" connector="Height"/> | |
</Block> | |
</xholonClassDetails> | |
<PhysicalSystem> | |
<Block> | |
<Height>0.1 m</Height> | |
</Block> | |
<Brick multiplicity="2"/> | |
</PhysicalSystem> | |
<Blockbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
$wnd.xh.avatar().action("pause"); | |
//# sourceURL=Blockbehavior.js | |
]]></Blockbehavior> | |
<Heightbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
var myHeight, testing; | |
var beh = { | |
postConfigure: function() { | |
testing = Math.floor(Math.random() * 10); | |
myHeight = this.cnode.parent(); | |
}, | |
act: function() { | |
myHeight.println(this.toString()); | |
}, | |
toString: function() { | |
return "testing:" + testing; | |
} | |
} | |
//# sourceURL=Heightbehavior.js | |
]]></Heightbehavior> | |
<Brickbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
$wnd.xh.Brickbehavior = function Brickbehavior() {} | |
$wnd.xh.Brickbehavior.prototype.postConfigure = function() { | |
this.brick = this.cnode.parent(); | |
this.iam = " red brick"; | |
}; | |
$wnd.xh.Brickbehavior.prototype.act = function() { | |
this.brick.println("I am a" + this.iam); | |
}; | |
//# sourceURL=Brickbehavior.js | |
]]></Brickbehavior> | |
<Brickbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
console.log("I'm another brick behavior"); | |
]]></Brickbehavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>Block</title> | |
<rect id="PhysicalSystem/Block" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
<g> | |
<title>Height</title> | |
<rect id="PhysicalSystem/Block/Height" fill="#6AB06A" height="50" width="10" x="80" y="0"/> | |
</g> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment