Skip to content

Instantly share code, notes, and snippets.

@mkuklis
Created May 4, 2012 06:18
Show Gist options
  • Save mkuklis/2592550 to your computer and use it in GitHub Desktop.
Save mkuklis/2592550 to your computer and use it in GitHub Desktop.
Leonardo + Box2D = Bonnet.js
(function (b2d, L) {
// Box2d shortcuts
var b2Vec2 = b2d.Common.Math.b2Vec2,
b2BodyDef = b2d.Dynamics.b2BodyDef,
b2Body = b2d.Dynamics.b2Body,
b2FixtureDef = b2d.Dynamics.b2FixtureDef,
b2Fixture = b2d.Dynamics.b2Fixture,
b2World = b2d.Dynamics.b2World,
b2PolygonShape = b2d.Collision.Shapes.b2PolygonShape,
b2CircleShape = b2d.Collision.Shapes.b2CircleShape,
b2DebugDraw = b2d.Dynamics.b2DebugDraw,
scale = 30;
// creates correct shapes for fixtures
var shapeCommands = {
circle: function (fixDef, attrs) {
fixDef.shape = new b2CircleShape(attrs.r / scale);
},
rect: function (fixDef, attrs) {
fixDef.shape = new b2PolygonShape();
fixDef.shape.SetAsBox(attrs.w / scale, attrs.h / scale);
}
};
/**
* Initialize `Bonnet`
*/
function Bonnet(leonardo) {
this.l = leonardo;
this.fr = 1 / 60 //frame-rate
this.vi = 10 // velocity iterations
this.pi = 10 //position iterations
}
// bonnet API
Bonnet.prototype = {
/**
* Creates new box2d world
*
* @api public
*/
world: function () {
if (!this.w) {
this.w = new b2World(new b2Vec2(0, 10), true);
}
return this;
},
/**
* Runs world.
*
* @api public
*/
run: function () {
this.w.Step(this.fr, this.vi, this.pi);
this.l.redraw(this.update);
this.w.ClearForces();
requestAnimationFrame(L.proxy(this.run, this));
},
/**
* Updates positions of the elements
* in the world.
*
* @param {Element} el
* @api private
*/
update: function (el) {
var body = el.attr('body');
if (body) {
p = body.m_body.GetPosition();
//el.rotate(L.deg(body.m_body.GetAngle()));
el.attr({x: p.x * scale, y: p.y * scale});
}
},
/**
* Adds dynamic element to the world.
*
* @param {Element} element
* @param {object} options
* @api publc
*/
add: function (el, opts) {
// TODO: reuse bodyDef and fixDef?
var bodyDef = new b2BodyDef(),
fixDef = new b2FixtureDef(),
attrs = el.attrs;
opts = opts || {};
fixDef.density = opts.d || 1.0;
fixDef.friction = opts.f || 0.5;
fixDef.restitution = opts.r || 0.2;
bodyDef.position.x = attrs.x / scale;
bodyDef.position.y = attrs.y / scale;
shapeCommands[el.type].call(this, fixDef, attrs);
bodyDef.type = b2Body.b2_dynamicBody;
// create new body
var body = this.w.CreateBody(bodyDef).CreateFixture(fixDef);
// associate body with element
el.attr({body: body});
return this;
},
/**
* Adds static element to the world.
*
* @api public
*/
addStatic: function (el, opts) {
// TODO: reuse bodyDef and fixDef?
var bodyDef = new b2BodyDef(),
fixDef = new b2FixtureDef(),
attrs = el.attrs;
opts = opts || {};
fixDef.density = opts.d || 1.0;
fixDef.friction = opts.f || 0.5;
fixDef.restitution = opts.r || 0.2;
bodyDef.position.x = attrs.x / scale;
bodyDef.position.y = attrs.y / scale;
shapeCommands[el.type].call(this, fixDef, attrs);
bodyDef.type = b2Body.b2_staticBody;
// create new body
this.w.CreateBody(bodyDef).CreateFixture(fixDef);
return this;
}
};
Leonardo.fn.world = function () {
this.b = new Bonnet(this);
return this.b.world();
}
})(Box2D, Leonardo);
// usage
var leo = leonardo(0, 0, 1100, 500),
world = leo.world(),
circle1 = leo.circle(70, 70, 50, {fill: "#ff0000"}),
circle2 = leo.circle(75, 75, 10, {fill: "#ff0000"}),
rect = leo.rect(10, 450, 500, 10, {fill: "#000000"});
world.add(circle1).add(circle2);
world.addStatic(rect);
world.run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment