Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active April 10, 2019 15:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/7fca7db5fe7767d60c116e80bdeaf1a8 to your computer and use it in GitHub Desktop.
Save kenwebb/7fca7db5fe7767d60c116e80bdeaf1a8 to your computer and use it in GitHub Desktop.
Physics Engines - Planck.js
<?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