box2djsの作法 その7


概要

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,
    b2Shape = Box2D.Collision.Shapes.b2Shape,
    b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef,
    b2Joint = Box2D.Dynamics.Joints.b2Joint,
    b2Settings = Box2D.Common.b2Settings;
var world;
var ctx;
var scale = 100;
var PTM = 100;
var shape;
var drawing = false;
var previousMouseX = 0;
var previousMouseY = 0;
var u = new b2Vec2(0, 0);
var anchor = [];
var bodies = [];
var d = 1.0;
mouseX = 0;
mouseY = 0;
var  points = [];
var canvas = document.getElementById("c");
ctx = canvas.getContext('2d');
canvas.width = 460;
canvas.height = 460;
world = new b2World(new b2Vec2(0, 9.5), true);
var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(document.getElementById("c").getContext("2d"));
debugDraw.SetDrawScale(100.0);
debugDraw.SetFillAlpha(0.5);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
world.SetDebugDraw(debugDraw);

var groundFixDef = new b2FixtureDef();
groundFixDef.density = 2;
groundFixDef.friction = 0.5;
groundFixDef.restitution = 0.2;
groundFixDef.shape = new b2PolygonShape();
groundFixDef.shape.SetAsBox(2.325, 0.3);
var groundDef = new b2BodyDef();
groundDef.type = b2Body.b2_staticBody;
groundDef.position.Set(2.25, 4.6);
var body =  world.CreateBody(groundDef);
body.CreateFixture(groundFixDef);
groundDef.position.Set(2.25, -0.1);
var body =  world.CreateBody(groundDef);
body.CreateFixture(groundFixDef);
groundFixDef.shape.SetAsBox(0.3, 2.25);
groundDef.position.Set(-0.1, 2.25);
var body =  world.CreateBody(groundDef);
body.CreateFixture(groundFixDef);
groundDef.position.Set(4.6, 2.25);
var body = world.CreateBody(groundDef);
body.CreateFixture(groundFixDef);

canvas.addEventListener('mousemove', function(e) {
    mouseX = e.pageX - this.offsetLeft;
    mouseY = e.pageY - this.offsetTop;
    if (drawing)
    {
        points.push({
            x: mouseX,
            y: mouseY
        });
        ctx.beginPath();
        ctx.lineWidth = 5;
        ctx.strokeStyle = "green";
        ctx.moveTo(points[0].x, points[0].y);
        for (var i = 1; i < points.length; i++)
        {
            ctx.lineTo(points[i].x, points[i].y);
        }
        ctx.stroke();
    }
}, false);
canvas.addEventListener('mousedown', function(e) {
    points.push({
        x: mouseX,
        y: mouseY
    });
    if (!drawing)
    {
        previousMouseX = mouseX;
        previousMouseY = mouseY;
        anchor = [];
        setAnchor(mouseX, mouseY);
        drawing = true;
    }
}, false);
canvas.addEventListener('mouseup', function() {
    points.length = 0;
    drawing = false;
    setAnchor(mouseX, mouseY);
    createBody();
}, false);
function dog_eraseline() {
    for (body = world.GetBodyList(); body; body = body.GetNext())
    {
        if (body.GetUserData() == "line")
        {
            world.DestroyBody(body);
        }
    }
}
function vecMagnitude(v) {
    return Math.sqrt(Math.pow(v.x, 2) + Math.pow(v.y, 2));
}
function vecAngle(v1, v2) {
    return (v1.x * v2.x + v1.y * v2.y) / (vecMagnitude(v1) * vecMagnitude(v2));
}
function setAnchor(x, y) {
    anchor.push(new b2Vec2(x, y));
}
function createBody() {
    var boxDef = new b2BodyDef();
    boxDef.type = b2Body.b2_dynamicBody;
    boxDef.position.Set(0, 0);
    var body = world.CreateBody(boxDef);
    for (var i = 0; i < anchor.length - 1; i++)
    {
        var position = new b2Vec2((anchor[i].x + anchor[i + 1].x) / 200, (anchor[i].y + anchor[i + 1].y) / 200);
        var angle = Math.atan2(anchor[i].y - anchor[i + 1].y, anchor[i].x - anchor[i + 1].x);
        var l = vecMagnitude(new b2Vec2(anchor[i].x - anchor[i + 1].x, anchor[i].y - anchor[i + 1].y)) / 100;
        if (anchor.length == 2 && l < 0.05)
        {
            l = 0.05;
        }
        var boxFixDef = new b2FixtureDef();
        boxFixDef.density = d * l * 0.05;
        boxFixDef.friction = 0.5;
        boxFixDef.restitution = 0.1;
        boxFixDef.shape = new b2PolygonShape();
        boxFixDef.shape.SetAsOrientedBox(l / 2, 0.025, position, angle);
        body.CreateFixture(boxFixDef);
    }
    body.SetUserData("line");
    bodies.push(body);
}
document.addEventListener("keydown", function(e) {
    tilt = 0;
    switch (event.keyCode)
    {
    case 32: 
    break;
    case 69:
        dog_eraseline();
    break;
    }
}, false);
function tick() {
    world.Step(1 / 30, 8, 2);
    canvas.width = canvas.width;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    if (drawing)
    {
        var p = new b2Vec2(0, 0);
        p.x = mouseX - previousMouseX;
        p.y = mouseY - previousMouseY;
        if (vecMagnitude(p) !== 0)
        {
            if (Math.cos(10 / 180 * Math.PI) > vecAngle(p, u))
            {
                setAnchor(previousMouseX, previousMouseY);
            }
            u.x = p.x;
            u.y = p.y;
        }
        previousMouseX = mouseX;
        previousMouseY = mouseY;
    }
    world.DrawDebugData();
    for (body = world.GetBodyList(); body; body = body.GetNext())
    {
        var x = body.GetPosition().x;
        var y = body.GetPosition().y;
        var angle = body.GetAngle();
        switch (body.GetUserData())
        {
        case "circle2":
            var radius = body.GetFixtureList().GetShape().GetRadius();
            ctx.save();
            ctx.translate(x * PTM, y * PTM);
            ctx.rotate(angle * (Math.PI / 180));
            ctx.translate(-x * PTM, -y * PTM);
            ctx.beginPath();
            ctx.arc(x * PTM , y * PTM, radius * PTM, 0, 2 * Math.PI, false);
            ctx.closePath();
            ctx.lineWidth = 5;
            ctx.strokeStyle = "green";
            ctx.fillStyle = "red";
            ctx.stroke();
            ctx.fill();
            ctx.restore();
        break;
        }
    }
    world.ClearForces();
}
window.setInterval(tick, 1000 / 30);




成果物

以上。