box2djsの作法 その6


概要

box2djsの作法、調べてみた。
マウスで剛体引っ張るやつやってみた。

写真

サンプルコード

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,
    b2MassData = Box2D.Collision.Shapes.b2MassData,
    b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
    b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
    b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
  b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef,
    b2DistanceJointDef  = Box2D.Dynamics.Joints.b2DistanceJointDef;
var canvas = document.getElementById("c");
canvas.width = 456;
canvas.height = 456;
var world = new b2World(new b2Vec2(0, 10),  true);
var fixDef = new b2FixtureDef;
fixDef.density = 1.0;
fixDef.friction = 1.0;
fixDef.restitution = 0.2;
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_staticBody;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(20, 2);
bodyDef.position.Set(10, 400 / 30 + 1.8);
world.CreateBody(bodyDef).CreateFixture(fixDef);
bodyDef.position.Set(10, -1.8);
world.CreateBody(bodyDef).CreateFixture(fixDef);
fixDef.shape.SetAsBox(2, 14);
bodyDef.position.Set(-1.8, 13);
world.CreateBody(bodyDef).CreateFixture(fixDef);
bodyDef.position.Set(17.0, 13);
world.CreateBody(bodyDef).CreateFixture(fixDef);
var jointDef = new b2DistanceJointDef;
fixDef.density = 1.0;
fixDef.friction = 5;
fixDef.restitution = 0.2;
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.angularDamping = 1;
bodyDef.linearDamping = 1;
var bodyTmp = null;
var bodies = [];
var num = 8;
for (var i = 0; i < num; ++i)
{
    fixDef.shape = new b2CircleShape(0.2);
    bodyDef.position.x = Math.random() * 10;
    bodyDef.position.y = Math.random() * 10;
    bodyTmp = world.CreateBody(bodyDef);
    bodyTmp.CreateFixture(fixDef);
    bodies.push(bodyTmp);
}
jointDef.bodyA = bodies[bodies.length - 1];
jointDef.bodyB = bodies[0];
jointDef.collideConnected = false;
jointDef.length = 5 * 3.14 / num;
jointDef.frequencyHz  = 0;
jointDef.dampingRatio = 0;
jointDef.anchorPoint1 = bodies[bodies.length - 1].GetLocalCenter();
jointDef.anchorPoint2 = bodies[0].GetLocalCenter();
world.CreateJoint(jointDef);
for (var j = 0; j < bodies.length - 1; j++)
{
    jointDef.bodyA = bodies[j];
    jointDef.bodyB = bodies[j + 1];
    jointDef.anchorPoint1 = bodies[j].GetLocalCenter();
    jointDef.anchorPoint2 = bodies[j + 1].GetLocalCenter();
    world.CreateJoint(jointDef);
}
for (var k = 0; k < bodies.length / 2; k++)
{
    jointDef.frequencyHz  = 5;
    jointDef.dampingRatio = 0.9;
    jointDef.bodyA = bodies[k];
    jointDef.bodyB = bodies[k + bodies.length / 2];
    jointDef.length = 5; 
    jointDef.anchorPoint1 = bodies[k].GetLocalCenter();
    jointDef.anchorPoint2 = bodies[k * 2].GetLocalCenter();
    world.CreateJoint(jointDef);
}
var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(document.getElementById("c").getContext("2d"));
debugDraw.SetDrawScale(30.0);
debugDraw.SetFillAlpha(0.5);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
world.SetDebugDraw(debugDraw);
window.setInterval(update, 1000 / 60);
var mouseX, 
    mouseY, 
    mousePVec, 
    isMouseDown, 
    selectedBody, 
    mouseJoint;
var canvasPosition = getElementPosition(document.getElementById("c"));
addEventListener("mousedown", function(e) {
    isMouseDown = true;
    handleMouseMove(e);
    document.addEventListener("mousemove", handleMouseMove, true);
}, true);
addEventListener("mouseup", function() {
    document.removeEventListener("mousemove", handleMouseMove, true);
    isMouseDown = false;
    mouseX = undefined;
    mouseY = undefined;
}, true);
function handleMouseMove(e) {
    mouseX = (e.clientX - canvasPosition.x) / 30;
    mouseY = (e.clientY - canvasPosition.y) / 30;
};
function getBodyAtMouse() {
    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;
}
function update() {
    if (isMouseDown && (!mouseJoint))
    {
        var body = getBodyAtMouse();
        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 = world.CreateJoint(md);
            body.SetAwake(true);
        }
    }
    if (mouseJoint)
    {
        if (isMouseDown)
        {
            mouseJoint.SetTarget(new b2Vec2(mouseX, mouseY));
        }
        else
        {
            world.DestroyJoint(mouseJoint);
            mouseJoint = null;
        }
    }
    world.Step(1 / 60, 10, 10);
    world.DrawDebugData();
    world.ClearForces();
};
function getElementPosition(element) {
    var elem = element, 
        tagname = "", 
        x = 0, 
        y = 0;
    while ((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined"))
    {
        y += elem.offsetTop;
        x += elem.offsetLeft;
        tagname = elem.tagName.toUpperCase();
        if (tagname == "BODY") elem = 0;
        if (typeof(elem) == "object")
        {
            if (typeof(elem.offsetParent) == "object") elem = elem.offsetParent;
        }
    }
    return {
        x: x, 
        y: y
    };
}




成果物

以上。