Box2DJS入门教程

转载 2011年04月09日 13:36:00

本文的主要目的是给大家介绍如何使用Box2DJS库在浏览器中创建一个物理世界,本文为基本入门教程,如果你想更深入的了解Box2D的功能,请看本文结尾“相关资源”中的“Box2D v2.0.1 用户手册

一、主函数:

  • 主函数包括了Box2D的基本流程
  • 简单来说,一个Box2D程序的基本流程是由以下三个基本步骤构成的:

1 function box2dMain() {
2  
3     setupWorld();               //1. 创建一个世界
4     addBodys();                 //2. 为世界创建物体
5     setInterval(step, 1000/60); //3. 让世界动起来,反复计算和绘制世界
6  
7 }

二、创建世界:

  • 设定世界有效区域的大小:超过有效区域的物体将不参与计算。
  • 定义重力:重力是一个二维矢量,矢量在Box2D中用b2Vec2来定义。
  • 设定是否允许物体休眠:当物体静止下来,它就会被判定为休眠,如果打开这个开关,对于休眠的物体将停止模拟。直到它被其它物体解除,它才会醒来。
01 function setupWorld(){
02  
03     //1. 设置有效区域大小 - b2AABB 类 (左上角向量,右下角向量)
04     worldAABB = new b2AABB();
05     worldAABB.minVertex.Set(-1000, -1000);  //左上角
06     worldAABB.maxVertex.Set(1000, 1000);    //右下角
07  
08     //2. 定义重力 - 2D向量 - b2Vec2 类 (x,y)
09     gravity = new b2Vec2(0, 300);
10  
11     //3. 忽略休眠的物体
12     var doSleep = true;
13  
14     //4. 创建世界 - b2World
15     var world = new b2World(worldAABB, gravity, doSleep);
16 }

三、创建物体:

  • 形状定义:Box2D中有三种基本形状,圆形(Circle)、矩形(Box)、多边形(Poly)。每个形状可以单独定义摩擦力、弹性、密度、相对位置等参数。形状是组成物体的基本材料。(当物体的密度设定为0时,物体变为墙类物体,不可移动)
  • 物体定义:物体可由多个形状组成。形状由其定义相对位置(localPosition)决定其在物体中的位置,形状添加到物体后,其相对位置始终保持不变。
  • 物体:物体只有使用世界的CreateBody()来生成,物体是物体定义的实例。只有使用这个函数生成的物体,才会在世界中被模拟。

在下面这个例子中,我们创建了一个上图的物体和一个地面。

01 function addBodys(){
02  
03     //1. 定义形状   b2CircleDef,b2BoxDef,b2PolyDef 类
04     var Shape1 = new b2CircleDef(); //Shape1:圆形
05     Shape1.radius = 20;                 //半径
06     Shape1.localPosition.Set(0, 0);     //偏移量
07     Shape1.density = 1.0;               //密度
08     Shape1.restitution = .3;            //弹性
09     Shape1.friction = 1;                //摩擦力
10  
11     var Shape2 = new b2PolyDef();   //Shape2:多边形
12     Shape2.vertexCount = 3;                     //顶点数为5
13     Shape2.vertices[0] = new b2Vec2(0,-20);     //顶点1
14     Shape2.vertices[1] = new b2Vec2(23.10,20);  //顶点2
15     Shape2.vertices[2] = new b2Vec2(-23.10,20); //顶点3
16     Shape2.localPosition.Set(0, 30);    //偏移量
17     Shape2.density = 1.0;               //密度
18     Shape2.restitution = .3;            //弹性
19     Shape2.friction = 1;                //摩擦力
20  
21     //2. 定义物体   b2BodyDef 类
22     var BodyDef1 = new b2BodyDef();
23     BodyDef1.position.Set(100, 100);    //设置物体的初始位置
24     BodyDef1.AddShape(Shape1);          //物体中加入Shape1
25     BodyDef1.AddShape(Shape2);          //物体中加入Shape2
26  
27     //3. 将物体添加至world
28     Body = World.CreateBody(BodyDef1);  //在世界中创建物体
29  
30     //...可用同样流程继续添加物体,再定义一块地板
31     var Shape3 = new b2BoxDef();    //Shape3:矩形
32  
33     Shape3.extents.Set(200, 5);         //定义矩形高、宽
34     Shape2.density = 0;                 //墙体密度为0
35     Shape2.restitution = .3;            //弹性
36     Shape2.friction = 1;                //摩擦力
37     var BodyDef2 = new b2BodyDef();
38     BodyDef2.position.Set(220, 500);    //设置物体的初始位置
39     BodyDef2.AddShape(Shape3);          //物体中加入Shape3
40     Body2 = World.CreateBody(BodyDef2); //在世界中创建物体
41  
42 }

四、让世界运动起来:

  • step()函数的作用是计算某段时间后,世界中物体的位置和角度,并将其绘制到浏览器中。
  • 计算机中的动画,是一帧一帧构成的,每一帧表现了动画中某一时刻的一个场景。所以我们使用定时器函数setInterval(step, 1000/60),来每1/60秒执行一次计算和重绘工作,也就是上述的step()函数。
  • step()中的dt参数,告诉了计算机要计算当前时间多少秒以后的世界,Box2D官方推荐为1/60秒,当然,如果你的计算机足够快,缩小这个时间间隔。另外dt应该与setInterval()函数中的第二个参数对应起来,这样才不会导致物体看起来运动的比你想像的要快或者慢。还有一点,dt不宜过大,否则模拟会不太精确,可能出现物体穿过另一个物体之类的bug。
  • step()中的iterations参数,是多个物体同时发生碰撞时的模拟精度,越高的值会使模拟越精确,但同时也会让运算速度大幅下降,推荐值为10。
  • step()中的World.step()函数是用来计算世界中物体的位置,执行后,物体的位置、角度、速度等信息更新。;
  • step()中的drawWorld()函数会将物体绘制在浏览器中。

01 function step(){
02  
03     //计算多少秒之后的世界
04     var dt = 1/60;
05  
06     //迭代次数,影响物体碰撞的计算精度,太高会导致速度过慢
07     var iterations = 10;
08  
09     //计算dt秒之后世界中物体的位置
10     World.step(dt,iterations);
11  
12     //绘制世界
13     drawWorld();
14  
15 }

五、绘制世界:

  • 当前的demo的drawWorld()函数是通过HTML5的canvas标签来绘制物体的。当然,你也可以使用图片和CSS3来进行模拟。
  • 绘制最新的一帧前,需要清除上一帧绘制的内容。
01 //绘制世界
02 function drawWorld(){
03  
04     //绘制之前将上一帧的内容清除
05     context.clearRect(0, 0, canvasWidth, canvasHeight);
06     //遍历世界中的物体
07     for (var b = World.m_bodyList; b; b = b.m_next) {
08         //遍历物体中的形状
09         for (var s = b.GetShapeList(); s != null; s = s.GetNext())
10         {
11             this.drawShape(s);  //绘制一个形状
12         }
13     }
14  
15 }
16  
17 //绘制一个形状
18 function drawShape(shape){
19  
20     context.strokeStyle = '#000';       //线形
21     context.beginPath();
22     switch (shape.m_type) {
23         case b2Shape.e_circleShape:{    //如果是圆形,画圆
24             var circle = shape;
25             var r = circle.m_radius;
26             var pos = circle.m_position;
27             var pos2 = circle.m_R.col1.clone().scale(r).add(pos);
28             context.arc(pos.x, pos.y, r, 0, Math.PI * 2, false);
29             context.moveTo(pos.x, pos.y);
30             context.lineTo(pos2.x, pos2.y);
31             break;
32         }
33         case b2Shape.e_polyShape:{      //如果是多边形,画多边形
34             var poly = shape;
35             var tV = b2Math.AddVV(poly.m_position,
36                  b2Math.b2MulMV(poly.m_R, poly.m_vertices[0]));
37             context.moveTo(tV.x, tV.y);
38             for (var i = 0; i < poly.m_vertexCount; i++) {
39                 var v = b2Math.AddVV(poly.m_position,
40                 b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
41                 context.lineTo(v.x, v.y);
42             }
43             context.lineTo(tV.x, tV.y);
44             break;
45         }
46     }
47     context.stroke();   //绘制
48  
49 }

六、结语:

  • 本文只是介绍了如何使用基于JS的Box2D物理引擎创建最简单的程序。对于更复杂的应用,Box2D还有众多的如关节(Joint)、接触(contact)等本文没有提及内容和虽然本文提及了,但并没有详细阐述的内容。这里有一份“Aman JIANG(江超宇)”翻译的“Box2D v2.0.1 用户手册”,虽然其内容是基于c++的Box2D引擎,但其基本的API与JS版无太大差异,可能对你会有很大的帮助。
  • 另外,目前无问题的JS版是由Box2DFlashAS3_1.4.3.1转换而来,而网上Box2D教程的主流版本为2.x系列,部分api与1.4不太一样,功能也有增强,所以请大家研究的时候注意两者差别。在HTML5被众人关注的今天,希望作者能尽快发布2.0版的Box2DJS。

HTML5游戏开发-Box2dWeb应用(一)-创建各种各样的刚体

本篇开始,会介绍lufylegend-1.4.0的新功能,怎样结合box2dweb创建一个物理世界以及这个物理世界里的各种刚体准备工作首先你需要下载html5开源库件lufylegend-1.4.0h...
  • lufy_Legend
  • lufy_Legend
  • 2012年06月13日 00:30
  • 22956

[HTML5]使用Box2dWeb模拟飞行箭矢

Box2d是一个2D游戏物理引擎,由Erin Catto开发,于2007年发布。很多2D游戏都用过Box2d,其中最有名的自然是愤怒的小鸟。Box2d本身是C++编写,但在不同平台都有它的衍生版本,像...
  • RaymondCode
  • RaymondCode
  • 2013年03月18日 09:14
  • 5749

基于HTML5的WebGL结合Box2DJS物理引擎应用

Box2D最早是Erin Catto在GDC大会上的一个展示例子,后来不断完善成C++的开源物理引擎库,这些年了衍生出Java、ActionScript以及JS等版本,被广泛应用在游戏领域。说其丰富的...
  • u013161495
  • u013161495
  • 2015年12月08日 00:15
  • 1246

Box2D.js简易示例

Box2dWeb example //在页面加载完毕后启动整个Box2D程序 function init() { /...
  • MAILLIBIN
  • MAILLIBIN
  • 2015年09月18日 10:45
  • 878

【HTML5物理小Demo】用Box2dWeb实现锁链+弹簧效果

最近开始研究Box2dweb,Box2dweb是一款物理引擎,主要是对物理刚体和关节连接进行了封装,box2dweb很强大当然也有些复杂,不过幸好lufylegend.js做了这方面的封装,在制作时如...
  • yorhomwang
  • yorhomwang
  • 2014年02月05日 16:47
  • 12882

box2d-web.js

  • 2015年04月09日 16:40
  • 420KB
  • 下载

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

Box2D 开源物理引擎,第一次接触,主要用途应该是做游戏,不过也可以作些简单的特性...
  • wty19
  • wty19
  • 2014年04月18日 16:01
  • 1526

Box2D C++ 教程-力和冲量

声明:本教程翻译自:Box2D C++ tutorials-Forces and impulses,仅供学习参考。 力和冲量(Forces and impulses) 让物体移动,...
  • Const_Gong
  • Const_Gong
  • 2016年05月20日 09:46
  • 841

Box2D C++ 教程-碰撞剖析

声明:本教程翻译自:Box 2D C++ turorials - Anatomy of a collision,仅供学习参考。 在Box2D中,经常会遇到物体之间的碰撞问题,当一个碰撞发生时...
  • Const_Gong
  • Const_Gong
  • 2016年05月20日 21:20
  • 656

Cocos2d-x教程(17)-Box2D 物理引擎

Box2D的基本使用方法
  • u012945598
  • u012945598
  • 2014年01月03日 13:30
  • 7664
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Box2DJS入门教程
举报原因:
原因补充:

(最多只允许输入30个字)