/* Box2d * ------------------ * iio.js version 1.4 */ // define a new iio app function Box2dDemo( app, settings ){ // application settings var wallColor = iio.Color.random(); var objColor = iio.Color.invert(wallColor); var objLineWidth = 5; var numObjs = app.width / 20; var maxObjSize = 1.6; var wallWidth = 1; var showInstructions = true; if (settings && settings.preview){ wallColor = iio.Color.iioblue(); objColor = iio.Color.invert(wallColor); numObjs = 40; objLineWidth = 2; maxObjSize = 0.5; wallWidth = 0.1; showInstructions = false; } else { app.color = wallColor.clone(); wallColor = objColor; } // add instructions to top of screen var instructions; if (showInstructions) instructions = app.add(new iio.Text({ text: 'click objects to drag,' +' press p to pause,' +' refresh to change colors', pos: [app.center.x, 100], size: 14, color: 'white', })); // define shortcuts to Box2d classes var b2Vec2 = Box2D.Common.Math.b2Vec2, b2AABB = Box2D.Collision.b2AABB, b2BodyDef = Box2D.Dynamics.b2BodyDef, b2Body = Box2D.Dynamics.b2Body, b2FixtureDef = Box2D.Dynamics.b2FixtureDef, b2Fixture = Box2D.Dynamics.b2Fixture, b2World = Box2D.Dynamics.b2World, b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape, b2CircleShape = Box2D.Collision.Shapes.b2CircleShape, b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef; // add a Box2d World to app var world = app.addB2World(new b2World( new b2Vec2(0, 10), //gravity true //allow sleep )); // Box2d settings var b2Width = app.width / app.b2Scale; var b2Height = app.height / app.b2Scale; // define a Fixture var fixDef = new b2FixtureDef; fixDef.density = 1.0; fixDef.friction = 0.5; fixDef.restitution = 0.2; // define a Body var bodyDef = new b2BodyDef; // create static wall object bodyDef.type = b2Body.b2_staticBody; fixDef.shape = new b2PolygonShape; // set wall object dimensions fixDef.shape.SetAsBox(b2Width, wallWidth); // add a new instance of the wall fixture // positioned at the bottom bodyDef.position.Set(0, b2Height); app.add(world.CreateBody(bodyDef)) .CreateFixture(fixDef).GetShape() .set({ color: wallColor, lineWidth: 2, }); // add a new instance of the wall fixture // positioned at the top of the view bodyDef.position.Set(0,0); app.add(world.CreateBody(bodyDef)) .CreateFixture(fixDef).GetShape() .set({ color: wallColor, lineWidth: 2, }); // set wall fixture dimensions fixDef.shape.SetAsBox(wallWidth, b2Height); // add a new instance of the wall fixture // positioned at the left of the view bodyDef.position.Set(0,0); app.add(world.CreateBody(bodyDef)) .CreateFixture(fixDef).GetShape() .set({ color: wallColor, lineWidth: 2, }); // add a new instance of the wall fixture // positioned at the right of the view bodyDef.position.Set(b2Width, 0); app.add(world.CreateBody(bodyDef)) .CreateFixture(fixDef).GetShape() .set({ color: wallColor, lineWidth: 2, }); // create dynamic bodies var shape,width,height,obj; bodyDef.type = b2Body.b2_dynamicBody; for(var i = 0; i < numObjs; ++i) { width = iio.random(0.1, maxObjSize) //half width height = iio.random(0.1, maxObjSize) //half height // set shape as polygon or circle if(iio.random() > 0.5) { fixDef.shape = new b2PolygonShape; fixDef.shape.SetAsBox(width, height); } else fixDef.shape = new b2CircleShape(width); // set body position bodyDef.position.x = iio.random(1,b2Width-1); bodyDef.position.y = iio.random(1,b2Height-1); // create body and add to app obj = app.add(world.CreateBody(bodyDef)); // create fixture and set display properties obj.CreateFixture(fixDef).GetShape().set({ outline: objColor, lineWidth: objLineWidth, refLine: true, }); } //Set the update loop app.b2Loop(60, function(){ // find selected body if(isMouseDown && (!mouseJoint)) { var body = getB2BodyAt(mouseX,mouseY); // drag selected body if(body) { var md = new b2MouseJointDef(); md.bodyA = world.GetGroundBody(); md.bodyB = body; md.target.Set(mouseX, mouseY); md.collideConnected = true; md.maxForce = 300.0 * body.GetMass(); mouseJoint = app.add(world.CreateJoint(md) .set({ color: 'white', width: 1, })); body.SetAwake(true); } } // update joint if(mouseJoint) { if(isMouseDown) { mouseJoint.SetTarget(new b2Vec2(mouseX, mouseY)); } else { world.DestroyJoint(mouseJoint); app.rmv(mouseJoint); mouseJoint = null; } } }); // find box 2d object at mouse position var mouseX, mouseY, mousePVec, isMouseDown, selectedBody, mouseJoint; function getB2BodyAt(callback, v, y) { if (typeof v.x === 'undefined') v=new Box2D.Common.Math.b2Vec2(v,y); mousePVec = new b2Vec2(mouseX, mouseY); var aabb = new b2AABB(); aabb.lowerBound.Set(mouseX - 0.001, mouseY - 0.001); aabb.upperBound.Set(mouseX + 0.001, mouseY + 0.001); selectedBody = null; world.QueryAABB(getBodyCB, aabb); return selectedBody; } function getBodyCB(fixture) { if(fixture.GetBody().GetType() != b2Body.b2_staticBody) { if(fixture.GetShape().TestPoint( fixture.GetBody().GetTransform(), mousePVec)) { selectedBody = fixture.GetBody(); return false; } } return true; } // mouse input handlers app.onMouseDown = function(app, event, key){ isMouseDown = true; mouseMove(event); } app.onMouseUp = function(app, event, key){ isMouseDown = false; mouseX = undefined; mouseY = undefined; } mouseMove = function(event){ var pos = app.eventVector(event); mouseX = pos.x / 30; mouseY = pos.y / 30; } iio.addEvent(app.canvas, 'mousemove', mouseMove); // keyboard input handlers app.onKeyDown = function(event, key){ if (key === 'p') app.pauseB2World(); else if (key === 'd') app.clear(); } } // start the app fullscreen iio.start( Box2dDemo );