Skip to content

Instantly share code, notes, and snippets.

@abernier abernier/README.md
Last active Mar 26, 2018

Embed
What would you like to do?
Box2D
html, body {height:100%;}
html {display:table; width:100%;}
body {display:table-cell; text-align:center; vertical-align:bottom;}
* {-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none; -webkit-user-drag:none;-moz-user-drag:none;-ms-user-drag:none;-o-user-drag:none;user-drag:none;}
.ball,
.ball b,
.crate,
.ground {box-sizing:border-box;}
.ball {display:inline-block; width:3em; height:3em; border-radius:100%; border:.4em solid; color:#dc3132; position:relative;}
.ball b {display:block; width:100%; border:.2em solid; border-radius:.2em;}
.ball {padding:.4em 0;}
.ball > div {width:100%; height:100%; position:relative;}
.ball b {position:absolute; left:100%; top:50%;margin-top:-.2em; margin-left:.45em;}
.ball b:first-child,
.ball b:last-child {margin-left:.3em;}
.ball b:first-child {top:0;}
.ball b:last-child {top:auto;margin-top:auto;bottom:0;margin-bottom:-.2em;}
.crate {display:inline-block; width:3em; height:3em; border:.4em solid #30aebf; border-radius:.15em;}
.ground {display:inline-block; width:12em; border:.2em solid; color:#8cc924; border-radius:.15em;}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>box2d</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="ball">
<div>
<b></b>
<b></b>
<b></b>
</div>
</div><br>
<div class="crate"></div><br>
<div class="crate"></div><div class="crate"></div><br>
<div class="ground"></div>
<script src="https://cdn.jsdelivr.net/npm/box2dweb@2.1.0-b/box2d.min.js"></script>
<script src="https://rawgithub.com/paulirish/1579671/raw/rAF.js"></script>
<script src="https://rawgithub.com/abernier/3225993/raw/loop.js"></script>
<script src="https://code.jquery.com/jquery-latest.js"></script>
<script src="index.js"></script>
</body>
</html>
(function () {
// Flatten Box2d (ugly but handy!)
(function b2(o) {
for (k in o) {
if (o.hasOwnProperty(k)) {
if ($.isPlainObject(o[k])) {
b2(o[k]);
} else if (/^b2/.test(k)) {
window[k] = o[k];
}
}
}
}(Box2D));
var world = new b2World(
new b2Vec2(0, 9.81), // gravity
true // allow sleep
);
var SCALE = 30;
//
// Ground
//
(function ($ground) {
// Fixture
var fixDef = new b2FixtureDef;
fixDef.density = 1;
fixDef.friction = 0.5;
fixDef.restitution = 0.2;
// Shape
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(
$ground.outerWidth() / 2 / SCALE, //half width
$ground.outerHeight() / 2 / SCALE //half height
);
// Body
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.x = ($ground.offset().left + $ground.outerWidth() / 2) / SCALE;
bodyDef.position.y = ($ground.offset().top + $ground.outerHeight() / 2) / SCALE;
var body = world.CreateBody(bodyDef);
body.CreateFixture(fixDef);
$ground.data('body', body);
}($('.ground')));
//
// Crates
//
$('.crate').each(function (i, el) {
var $crate = $(el);
// Fixture
var fixDef = new b2FixtureDef;
fixDef.density = 1;
fixDef.friction = 0.5;
fixDef.restitution = 0.2;
// Shape
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(
$crate.outerWidth() / 2 / SCALE, //half width
$crate.outerHeight() / 2 / SCALE //half height
);
// Body
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.position.x = ($crate.offset().left + $crate.outerWidth() / 2) / SCALE;
bodyDef.position.y = ($crate.offset().top + $crate.outerHeight() / 2) / SCALE;
var body = world.CreateBody(bodyDef);
body.CreateFixture(fixDef);
$crate.data('body', body);
});
//
// Ball
//
(function ($ball) {
// Fixture
var fixDef = new b2FixtureDef;
fixDef.density = 1;
fixDef.friction = 0.5;
fixDef.restitution = 0.2;
// Shape
fixDef.shape = new b2CircleShape($ball.outerWidth() / 2 / SCALE);
// Body
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.position.x = ($ball.offset().left + $ball.outerWidth() / 2) / SCALE;
bodyDef.position.y = ($ball.offset().top + $ball.outerHeight() / 2) / SCALE;
var body = world.CreateBody(bodyDef);
body.CreateFixture(fixDef);
$ball.data('body', body);
}($('.ball')));
//
// MouseJoint
//
var mouse = new b2Vec2();
$(window).mousemove(function (e) {
mouse.Set(e.pageX / SCALE, e.pageY / SCALE);
});
window.mouse = mouse;
(function (mouse) {
var mouseJointDef = new b2MouseJointDef();
mouseJointDef.target = mouse;
mouseJointDef.bodyA = world.GetGroundBody();
mouseJointDef.collideConnected = true;
var mouseJoint;
$('*').on({
mousedown: function (e) {
var body = $(this).data('body');
if (!body) {
return;
}
mouseJointDef.bodyB = body;
mouseJointDef.maxForce = 3000 * body.GetMass();
mouseJoint = world.CreateJoint(mouseJointDef);
mouseJoint.SetTarget(mouse);
function mouseup(e) {
world.DestroyJoint(mouseJoint);
}
$(window).one('mouseup', mouseup);
}
});
}(mouse));
//
// Loops
//
(function () {
var dt = 30;
new Loop(function () {
world.Step(
1/dt, //frame-rate
10, //velocity iterations
10 //position iterations
);
world.ClearForces();
}, 1000/dt).start();
}());
(function () {
var $entities = $('.ball, .crate');
// cache some initial coordinates informations
$entities.each(function (i, el) {
var $el = $(el);
$el.data('origPos', {
left: $el.offset().left,
top: $el.offset().top,
width: $el.outerWidth(),
height: $el.outerHeight()
});
});
$ball = $('.ball');
$tails = $('b', $ball);
new Loop(function (t, t0) {
if (!t0) {
return;
}
var dt = t - t0;
if (dt <= 0) {
return;
}
var i = $entities.length
while (i--) {(function () {
var entity = $entities[i];
var $entity = $(entity);
var body = $entity.data('body');
var pos = body.GetPosition();
var ang = body.GetAngle() * 180 / Math.PI;
var origPos = $entity.data('origPos')
$entity.css('transform', 'translate3d(' + ~~(pos.x*SCALE - origPos.left - origPos.width / 2) + 'px, ' + ~~(pos.y*SCALE - origPos.top - origPos.height / 2) + 'px, 0) rotate3d(0,0,1,' + ~~ang + 'deg)');
}());}
function angleVV(v1, v2) {
var n1 = v1.Length();
var n2 = v2.Length();
return Math.atan2(v1.y/n1, v1.x/n1) - Math.atan2(v2.y/n2, v2.x/n2);
}
var vel = $ball.data('body').GetLinearVelocityFromLocalPoint(new b2Vec2(0,0));
$tails
.parent().css('transform', 'rotate3d(0,0,1,' + ~~((-$ball.data('body').GetAngle() + angleVV(vel, new b2Vec2(0, 1)) - Math.PI / 2) * 180 / Math.PI) + 'deg)').end()
.css({
width: vel.Length() * 10 + '%',
opacity: vel.Length() / 10
});
}).start();
}());
}(jQuery, Box2D));
@abernier

This comment has been minimized.

Copy link
Owner Author

abernier commented Aug 22, 2012

@abernier

This comment has been minimized.

Copy link
Owner Author

abernier commented Aug 22, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.