## box2dweb 学习笔记--sample讲解

之前博文"台球游戏的核心算法和AI(1)" 中, 提到过想用HTML5+Box2d来编写实现一个台球游戏. 以此来对比感慨一下游戏物理引擎的巨大威力.
做为H5+box2d的初学者, 将简单讲讲box2d的一些基础概念, 并对一个sample样例做下讲解. 权作学习笔记.

box2d源自flash版, 后迁移到各个语言版本, box2dweb是与最新flash版本同步的js 2D物理引擎库.
box2d官网: http://box2d.org/.

世界: b2world
box2d物体依托的世界存在, 其需指定重力向量, 以及静止物体的休眠开关.

var world = new b2World(gravity, doSleep);

刚体: b2body
物理世界中的具体物体, 有动态/静态物体之分.
夹具: b2fixture
定义物体的形状,材质属性(密度, 摩擦系数,弹性系数)等等.

box2dweb库采用当前最新的Box2dWeb-2.1a.3. 该库只包含一个js文件, 并附带了样例.
文件组织结构如下所示:

我们以sample.html为例, 对box2dweb库做下简单的讲解.
展示的效果如下:

具体代码如下:

<html>
<title>Box2dWeb example</title>
<canvas id="canvas" width="600" height="400"></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
;

world = new b2World(
new b2Vec2(0, 10)    //gravity
,  true                 //allow sleep
);

var fixDef = new b2FixtureDef;
fixDef.density = 1.0;
fixDef.friction = 0.5;
fixDef.restitution = 0.2;

var bodyDef = new b2BodyDef;

//create ground
bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.x = 9;
bodyDef.position.y = 13;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(10, 0.5);
world.CreateBody(bodyDef).CreateFixture(fixDef);

//create some objects
bodyDef.type = b2Body.b2_dynamicBody;
for(var i = 0; i < 10; ++i) {
if(Math.random() > 0.5) {
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(
Math.random() + 0.1 //half width
,  Math.random() + 0.1 //half height
);
} else {
fixDef.shape = new b2CircleShape(
);
}
bodyDef.position.x = Math.random() * 10;
bodyDef.position.y = Math.random() * 10;
world.CreateBody(bodyDef).CreateFixture(fixDef);
}

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

window.setInterval(update, 1000 / 60);
};

function update() {
world.Step(
1 / 60   //frame-rate
,  10       //velocity iterations
,  10       //position iterations
);
world.DrawDebugData();
world.ClearForces();
};

</script>

</html>

js应该没有类似java和c#的命令空间的概念, 为避免冲突, 往往通过添加前缀名来解决, 比如box2dweb的采用b2前缀. 另一方面, 其通过简写的技巧来缩短类和函数的引用.

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
;

注: 通过简写来缩短类名和函数对象的引用.
• 创建世界

world = new b2World(
new b2Vec2(0, 10) //gravity
, true //allow sleep
);

• 创建地面

var bodyDef = new b2BodyDef;
//create ground
bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.x = 9;
bodyDef.position.y = 13;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(10, 0.5);
world.CreateBody(bodyDef).CreateFixture(fixDef);

注: b2Body.b2_staticBody标示该物体为静态物体(固定物), 一个物体由b2BodyDef和b2FixtureDef来确定.
• 创建刚体

//create some objects
bodyDef.type = b2Body.b2_dynamicBody;
for(var i = 0; i < 10; ++i) {
if(Math.random() > 0.5) {
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(
Math.random() + 0.1 //half width
, Math.random() + 0.1 //half height
);
} else {
fixDef.shape = new b2CircleShape(
);
}
bodyDef.position.x = Math.random() * 10;
bodyDef.position.y = Math.random() * 10;
world.CreateBody(bodyDef).CreateFixture(fixDef);
}

注: 这边随机创建了10个圆形/矩形的物体
• box2dweb的调试器(可视化)

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

注: DrawScale为物理世界和像素的比例值, 以及Sprite的canvas的2d上下文.
• 事件驱动
注册定时器, 定时更新. 而物理引擎的world.step函数是整个box2d的核心, 其模拟/驱动了物理世界的运行.

window.setInterval(update, 1000 / 60);

function update() {
world.Step(
1 / 60 //frame-rate
, 10 //velocity iterations
, 10 //position iterations
);
world.DrawDebugData();
world.ClearForces();
};

从这个sample代码中, 学习到了很多. 实践出真知, 希望自己作为一个html5er的初学者能快速成长.

posted on 2015-05-28 17:08 mumuxinfei 阅读(...) 评论(...) 编辑 收藏

• 随笔 - 164
• 文章 - 0
• 评论 - 171
• 引用 - 0