box2djsの作法 その6

# 概要

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

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0cce7356-6a70-8265-2fc0-ec0b7e352413.png)

# サンプルコード


```
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
	};
}




```

# 成果物

https://embed.plnkr.co/plunk/cPjKucqHQUbj2AUq


以上。