# [javascript] Box2D JS初探(一个控制小球的游戏例子)。学习用！

Box2D 开源物理引擎，第一次接触，主要用途应该是做游戏，不过也可以作些简单的页面特性，比如切割粉碎。拖动带弹性系数。

<html>
<title>Box2dWeb example</title>
<img id="tulip" style="display: none" src="33.jpg" alt="The Tulip" />
<canvas id="canvas" width="900" height="600"></canvas>
</body>
<script type="text/javascript" src="Box2dWeb-2.1.a.3.min.js"></script>
<script type="text/javascript">
var world;

function init() {
var   b2Vec2 = Box2D.Common.Math.b2Vec2
,	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
,	b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef
;

world = new b2World(
new b2Vec2(0,10)    //gravity  重力的方向，力度 单位牛，10就是重力加速度G
,  true                //allow sleep
);

var fixDef = new b2FixtureDef; //刚体创建
fixDef.density = 1.0;    //密度
fixDef.friction = 0.5;   //摩擦力 加大了之后正方形被推动就比较不容易动
fixDef.restitution = 0.8;  //弹性系数，1应该就是不衰减，大于1反而越来越快

var bodyDef = new b2BodyDef;

//create ground
bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.x = 1;  //单位是米，一米是30像素。
bodyDef.position.y = 19.8;
//以下试图建立四边框（用刚体来做，游戏四边的场景边框，不然会掉出去）
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(30, 0.1);   //长宽应该（宽长，xy对应）
world.CreateBody(bodyDef).CreateFixture(fixDef);
fixDef.shape.SetAsBox(0.1, 20);
bodyDef.position.Set(0.1, 0.1);
world.CreateBody(bodyDef).CreateFixture(fixDef);
fixDef.shape.SetAsBox(30, 0.1);
bodyDef.position.Set(0.1, 0.1);
world.CreateBody(bodyDef).CreateFixture(fixDef);
fixDef.shape.SetAsBox(0.1, 20);
bodyDef.position.Set(29.8, 0.1);
world.CreateBody(bodyDef).CreateFixture(fixDef);
//在场景中制作台阶
fixDef.shape.SetAsBox(3, 0.1);
bodyDef.position.Set(10, 18.5);
world.CreateBody(bodyDef).CreateFixture(fixDef);

var mouseX, mouseY,selectBody, keyBoll,vX, vY,keyVelocity,Death = false,barrier;
var canvasPosition = getElementPosition(document.getElementById("canvas"));
var context = document.getElementById("canvas").getContext("2d");
var img=document.getElementById("tulip");
//在场景中的空中放置一个正方形
bodyDef.type = b2Body.b2_dynamicBody;
fixDef.shape = new b2PolygonShape();
fixDef.shape.SetAsBox(1,1); //30px * 30px 的矩形
fixDef.restitution = 2;  //改变弹性系数，如果撞到他会更快的反弹
bodyDef.position.Set(10,13); //矩形陷阱的放置位置
console.log(fixDef.shape.GetVertices() );
console.log(typeof fixDef.shape.GetVertices()[0] );
selectBody = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody();
//建个链接器。把矩形固定在场景中
var jointDef = new b2MouseJointDef();
jointDef.bodyA = world.GetGroundBody();
jointDef.bodyB = selectBody;
//矩形和场景本体相连
jointDef.target.Set(10, 13);
//连接位置
jointDef.collideConnected = true;
//是否碰撞。要碰。不然就是根线，不能固定用
jointDef.maxForce = 3000.0;
//最大力，如果设置过小，会被从固定位置撞开
world.CreateJoint(jointDef);
//连接器加入世界
// 创建钉子
fixDef.restitution = 0;
fixDef.friction = 5000
fixDef.shape = new b2PolygonShape;
var vArray = [new b2Vec2(0,-0.5),new b2Vec2(0.25,0.5),new b2Vec2(-0.25,0.5)]
fixDef.shape.SetAsVector(vArray, 3);
//创建一个三角形这里要注意了，Vector字面是向量，其实穿进去的是三角形顶点坐标List，3是顶点个数。而且要顺时针方向，不然无法物理判定。
bodyDef.position.Set(15,19.5);
barrier = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody();
//创建连接，这个WeldJoint看字面就知道，是刚体连接，上面那个连接会被力改变，会旋转。这个就是焊死了。相当于固定
jointDef = new b2WeldJointDef();
jointDef.bodyA = world.GetGroundBody();
jointDef.bodyB = barrier;
jointDef.localAnchorA = new b2Vec2(15, 19.3)
jointDef.localAnchorB = barrier.GetLocalCenter();
jointDef.collideConnected = true;

world.CreateJoint(jointDef);
//创建主角--一个球
fixDef.restitution = 0.8;
fixDef.shape = new b2CircleShape(1);
bodyDef.position.Set(1,19.5);
bodyDef.userData=img;
//给球上图片
keyBoll = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody();
//把这个球的body记录下来。
/**
这里是点击小球在鼠标位置降落下来的 监听。
mouseX = (e.layerX - canvasPosition.x) / 30;
mouseY = (e.layerY - canvasPosition.y) / 30;
}, true);

fixDef.shape = new b2CircleShape(0.5);
bodyDef.position.Set(mouseX,mouseY);
selectBody = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody();
vX = (e.layerX - canvasPosition.x) / 30 - mouseX;
vY = (e.layerY - canvasPosition.y) / 30 - mouseY;
selectBody.ApplyImpulse( new b2Vec2(vX*5,vY*5), selectBody.GetLocalCenter());
}, true);
**/

//监控键盘事件
var theEvent = window.event || e;
var code = theEvent.keyCode || theEvent.which;
console.log(code);
var keyVelocity = keyBoll.GetLinearVelocity();
//按上方向键：
if(code==38){
//判定是不是y方向速度为0 ，我要球落地挺稳才让他继续下一次起跳，不然会越来越高。
if (keyVelocity.y == 0) {
//给一个y方向20的向上加速度。算下10的重力。应该也就2秒就下落了。
keyBoll.ApplyImpulse(new b2Vec2(0,-20), keyBoll.GetWorldCenter());
}
}
//左按键
if(code==37){
keyBoll.SetAwake(true);
//唤醒目标，并直接给向左10的速度，这里和上不一样，是直接替换速度，并不是加速度，所以Y方向的速度还需要加入。
keyBoll.SetLinearVelocity(new b2Vec2(-10,keyVelocity.y), keyBoll.GetWorldCenter());
}
//右按键
if(code==39){
keyBoll.SetAwake(true);
//同理
keyBoll.SetLinearVelocity(new b2Vec2(10,keyVelocity.y), keyBoll.GetWorldCenter());
}

}, false);
//监听按键弹起，并给个减速（也可以直接熟读至0）看个人喜好。
var theEvent = window.event || e;
var code = theEvent.keyCode || theEvent.which;
console.log(code);
if(code==37){
keyBoll.ApplyImpulse(new b2Vec2(10,0), keyBoll.GetWorldCenter());
}
if(code==39){
keyBoll.ApplyImpulse(new b2Vec2(-10,0), keyBoll.GetWorldCenter());
}

}, false);

//setup debug draw
var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
debugDraw.SetDrawScale(30.0);
debugDraw.SetFillAlpha(0.3);
debugDraw.SetLineThickness(2.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
world.SetDebugDraw(debugDraw);

window.setInterval(update, 1000 / 60); //配置侦数

//官网的例子里的一个canvans定位函数
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};
}

function update() {

var a = 1 / 60;
//如果2个球被被唤醒了，并且球和钉子在一定范围内，则说明撞到钉子了。GameOver 并且把刷新率置99999，表示不动了。
if (barrier.IsAwake() && keyBoll.IsAwake()) {
if (barrier.GetPosition().x + 2 > keyBoll.GetPosition().x && barrier.GetPosition().x - 2 < keyBoll.GetPosition().x ) {
a = 999999;
}
console.log(barrier.GetPosition());
console.log(keyBoll.GetPosition());
}
world.Step(
a   //frame-rate
,  10      //velocity iterations
,  10      //position iterations
);
world.DrawDebugData();
//贴图
context.save();
context.translate(keyBoll.GetPosition().x*30,keyBoll.GetPosition().y*30);
context.rotate(keyBoll.GetAngle());
context.drawImage(keyBoll.GetUserData(),-keyBoll.GetUserData().width/2,-keyBoll.GetUserData().height/2);
context.restore();
world.ClearForces();
};
};

</script>

</html>

• 本文已收录于以下专栏：

举报原因： 您举报文章：[javascript] Box2D JS初探(一个控制小球的游戏例子)。学习用！ 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)