/LGC物理引擎/javascript 版的 Box2D

本文介绍如何使用JavaScript实现Box2D物理引擎,并通过实例演示如何创建2D物理场景,包括自由落体碰撞和悬挂小球摆动。
javascript 版的 Box2D
作者: 刘鹏
日期: 2009-03-09
本文介绍了用 javascript 实现的 2d 物理引擎 Box2D,利用它可以在浏览器中实现带丰富物理效果的游戏和 UI。
简介

Box2DJS 是用 Javascript 实现的 Box2D 物理引擎 ,事实上它的代码由 Box2DFlashAS3 1.4.3.1 转换而来。

Box2DJS 使用 2D 命令往 canvas 标签定义的区域中绘制,Firefox、 Safari 和 Opera 9 都支持 canvas 标签,同时Box2DJS 也实现了一个 ExploreCanvas 标签供不支持 Canvas 标签的 IE 浏览器使用。

Box2DJS 的源码主要包括如下内容:

  • js,这里是物理引擎的核心代码,包括几何形状的绘制、动态效果的实现以 及碰撞检测等;
  • lib,这里实现了 ExploreCanvas 标签,在 IE 浏览器中使用;
  • style,这里保存了源码用到的 CSS 样式表;
  • demos,这里提供了一个 demo。

使用 Box2DJS 遵循下面两个步骤:

  1. 把 js/ 和 lib/ 目录拷到你的应用程序目录中;
  2. 在你的 index.html 源码 head 标签中增加 script 标签。
摆动的小球

这个例子是一个小球悬挂在空中左右摆动,随着摆动时间越来越长,小球摆动振 幅越来越小。截图如下所示:

程序序列图如下所示:

源代码如下所示:

index.html 代码如下所示:

/* index.html */

<html>
<head>
<!--=============================-->
<!-- Copy this part to your app. -->
<!-- START -->
<!--=============================-->
<!-- libs -->
<!--[if IE]><script type="text/javascript" src="lib/excanvas.js"></script><![endif]-->
<script src="lib/prototype-1.6.0.2.js"></script>

<!-- box2djs -->
<script src='js/box2d/common/b2Settings.js'></script>
<script src='js/box2d/common/math/b2Vec2.js'></script>
<script src='js/box2d/common/math/b2Mat22.js'></script>
<script src='js/box2d/common/math/b2Math.js'></script>
<script src='js/box2d/collision/b2AABB.js'></script>
<script src='js/box2d/collision/b2Bound.js'></script>
<script src='js/box2d/collision/b2BoundValues.js'></script>
<script src='js/box2d/collision/b2Pair.js'></script>
<script src='js/box2d/collision/b2PairCallback.js'></script>
<script src='js/box2d/collision/b2BufferedPair.js'></script>
<script src='js/box2d/collision/b2PairManager.js'></script>
<script src='js/box2d/collision/b2BroadPhase.js'></script>
<script src='js/box2d/collision/b2Collision.js'></script>
<script src='js/box2d/collision/Features.js'></script>
<script src='js/box2d/collision/b2ContactID.js'></script>
<script src='js/box2d/collision/b2ContactPoint.js'></script>
<script src='js/box2d/collision/b2Distance.js'></script>
<script src='js/box2d/collision/b2Manifold.js'></script>
<script src='js/box2d/collision/b2OBB.js'></script>
<script src='js/box2d/collision/b2Proxy.js'></script>
<script src='js/box2d/collision/ClipVertex.js'></script>
<script src='js/box2d/collision/shapes/b2Shape.js'></script>
<script src='js/box2d/collision/shapes/b2ShapeDef.js'></script>
<script src='js/box2d/collision/shapes/b2BoxDef.js'></script>
<script src='js/box2d/collision/shapes/b2CircleDef.js'></script>
<script src='js/box2d/collision/shapes/b2CircleShape.js'></script>
<script src='js/box2d/collision/shapes/b2MassData.js'></script>
<script src='js/box2d/collision/shapes/b2PolyDef.js'></script>
<script src='js/box2d/collision/shapes/b2PolyShape.js'></script>
<script src='js/box2d/dynamics/b2Body.js'></script>
<script src='js/box2d/dynamics/b2BodyDef.js'></script>
<script src='js/box2d/dynamics/b2CollisionFilter.js'></script>
<script src='js/box2d/dynamics/b2Island.js'></script>
<script src='js/box2d/dynamics/b2TimeStep.js'></script>
<script src='js/box2d/dynamics/contacts/b2ContactNode.js'></script>
<script src='js/box2d/dynamics/contacts/b2Contact.js'></script>
<script src='js/box2d/dynamics/contacts/b2ContactConstraint.js'></script>
<script src='js/box2d/dynamics/contacts/b2ContactConstraintPoint.js'></script>
<script src='js/box2d/dynamics/contacts/b2ContactRegister.js'></script>
<script src='js/box2d/dynamics/contacts/b2ContactSolver.js'></script>
<script src='js/box2d/dynamics/contacts/b2CircleContact.js'></script>
<script src='js/box2d/dynamics/contacts/b2Conservative.js'></script>
<script src='js/box2d/dynamics/contacts/b2NullContact.js'></script>
<script src='js/box2d/dynamics/contacts/b2PolyAndCircleContact.js'></script>
<script src='js/box2d/dynamics/contacts/b2PolyContact.js'></script>
<script src='js/box2d/dynamics/b2ContactManager.js'></script>
<script src='js/box2d/dynamics/b2World.js'></script>
<script src='js/box2d/dynamics/b2WorldListener.js'></script>
<script src='js/box2d/dynamics/joints/b2JointNode.js'></script>
<script src='js/box2d/dynamics/joints/b2Joint.js'></script>
<script src='js/box2d/dynamics/joints/b2JointDef.js'></script>
<script src='js/box2d/dynamics/joints/b2DistanceJoint.js'></script>
<script src='js/box2d/dynamics/joints/b2DistanceJointDef.js'></script>
<script src='js/box2d/dynamics/joints/b2Jacobian.js'></script>
<script src='js/box2d/dynamics/joints/b2Jacobian.js'></script>
<script src='js/box2d/dynamics/joints/b2GearJoint.js'></script>
<script src='js/box2d/dynamics/joints/b2GearJointDef.js'></script>
<script src='js/box2d/dynamics/joints/b2MouseJoint.js'></script>
<script src='js/box2d/dynamics/joints/b2MouseJointDef.js'></script>
<script src='js/box2d/dynamics/joints/b2PrismaticJoint.js'></script>
<script src='js/box2d/dynamics/joints/b2PrismaticJointDef.js'></script>
<script src='js/box2d/dynamics/joints/b2PulleyJoint.js'></script>
<script src='js/box2d/dynamics/joints/b2PulleyJointDef.js'></script>
<script src='js/box2d/dynamics/joints/b2RevoluteJoint.js'></script>
<script src='js/box2d/dynamics/joints/b2RevoluteJointDef.js'></script>
<!--=============================-->
<!-- Copy this part to your app. -->
<!-- END -->
<!--=============================-->

/* my app */
<script src='mytest/mytest.js'></script>

<link href="style/distant-planet.css" rel="stylesheet" type="text/css" />
<link href="style/box2d.css" rel="stylesheet" type="text/css" />

<head>
</html>

javascript 代码如下所示:

/* mytest.js*/

var world;
var ctx;
var canvasWidth;
var canvasHeight;
var canvasTop;
var canvasLeft;

function createGround(world) {
var groundSd = new b2BoxDef();
groundSd.extents.Set(1000, 50);
groundSd.restitution = 0.2;
var groundBd = new b2BodyDef();
groundBd.AddShape(groundSd);
groundBd.position.Set(-500, 340);
return world.CreateBody(groundBd)
}

function createBox(world, x, y, width, height, fixed) {
if (typeof(fixed) == 'undefined') fixed = true;
var boxSd = new b2BoxDef();
if (!fixed) boxSd.density = 1.0;
boxSd.extents.Set(width, height);
var boxBd = new b2BodyDef();
boxBd.AddShape(boxSd);
boxBd.position.Set(x,y);
return world.CreateBody(boxBd)
}

function createCircle (world, x, y) {
var circleSd = new b2CircleDef();
circleSd.density = 1.0;
circleSd.radius = 20;
circleSd.restitution = 1.0;
circleSd.friction = 0;
var circleBd = new b2BodyDef();
circleBd.AddShape(circleSd);
circleBd.position.Set(x,y);
return world.CreateBody(circleBd);

}

function createJoint (world, circleBody, x, y) {
var jointDef = new b2RevoluteJointDef();
jointDef.anchorPoint.Set(x, y);
jointDef.body1 = world.GetGroundBody();
jointDef.body2 = circleBody;
world.CreateJoint(jointDef);
}

function createWorld() {
var worldAABB = new b2AABB();
worldAABB.minVertex.Set(-1000, -1000);
worldAABB.maxVertex.Set(1000, 1000);
var gravity = new b2Vec2(0, 300);
var doSleep = true;
var world = new b2World(worldAABB, gravity, doSleep);
/*bottom box*/
createGround(world);
/*left box*/
createBox(world, 0, 125, 10, 250);
/*right box*/
createBox(world, 500, 125, 10, 250);
var circleBody = createCircle (world, 150, 10);
createJoint (world, circleBody, 200, 100);
return world;
}


function step(cnt) {
var stepping = false;
var timeStep = 1.0/60;
var iteration = 1;
world.Step(timeStep, iteration);
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
drawWorld(world, ctx);
setTimeout('step(' + (cnt || 0) + ')', 10);
}

Event.observe(window, 'load', function() {
world = createWorld ();

ctx = $('canvas').getContext('2d');
var canvasElm = $('canvas');
canvasWidth = parseInt(canvasElm.width);
canvasHeight = parseInt(canvasElm.height);
canvasTop = parseInt(canvasElm.style.top);
canvasLeft = parseInt(canvasElm.style.left);
step ();
});


代码下载地址:http://guitestbed.googlecode.com/files/box2d-js.tar.gz

碰撞

这个例子是一个小球自由落体落下,与一个矩形 box 碰撞后落到地面,截图如下所示:

碰撞前自由落体
碰撞前自由落体
碰撞后自由落体
碰撞后自由落体

js代码:

var world;
var ctx;
var canvasWidth;
var canvasHeight;
var canvasTop;
var canvasLeft;

function createGround(world) {
var groundSd = new b2BoxDef();
groundSd.extents.Set(1000, 50);
groundSd.restitution = 0.2;
var groundBd = new b2BodyDef();
groundBd.AddShape(groundSd);
groundBd.position.Set(-500, 340);
return world.CreateBody(groundBd)
}


function createBox(world, x, y, width, height, fixed) {
if (typeof(fixed) == 'undefined') fixed = true;
var boxSd = new b2BoxDef();
if (!fixed) boxSd.density = 1.0;
/*if density of body is 0, then the body is static. */
//boxSd.density = 1.0;
boxSd.extents.Set(width, height);
var boxBd = new b2BodyDef();
boxBd.AddShape(boxSd);
boxBd.position.Set(x,y);
return world.CreateBody(boxBd)
}

function createCircle (world, x, y) {
var circleSd = new b2CircleDef();
circleSd.density = 1.0;
circleSd.radius = 10;
circleSd.restitution = 0.5;
circleSd.friction = 0.1;
var circleBd = new b2BodyDef();
circleBd.AddShape(circleSd);
circleBd.position.Set(x,y);
return world.CreateBody(circleBd);
}

function createWorld() {
var worldAABB = new b2AABB();
worldAABB.minVertex.Set(-1000, -1000);
worldAABB.maxVertex.Set(1000, 1000);
var gravity = new b2Vec2(0, 300);
var doSleep = true;
var world = new b2World(worldAABB, gravity, doSleep);
/*bottom box*/
createGround(world);
/*left box*/
createBox(world, 0, 125, 10, 250);
/*right box*/
createBox(world, 500, 125, 10, 250);

/*The falling ball*/
var circleBody = createCircle (world, 150, 10);
/*The static box*/
var boxBody = createBox (world, 156, 100, 5, 5);


return world;
}

function step(cnt) {
var stepping = false;
var timeStep = 1.0/60;
var iteration = 1;
world.Step(timeStep, iteration);
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
drawWorld(world, ctx);
setTimeout('step(' + (cnt || 0) + ')', 10);
}


Event.observe(window, 'load', function() {

world = createWorld ();

ctx = $('canvas').getContext('2d');
var canvasElm = $('canvas');
canvasWidth = parseInt(canvasElm.width);
canvasHeight = parseInt(canvasElm.height);
canvasTop = parseInt(canvasElm.style.top);
canvasLeft = parseInt(canvasElm.style.left);
step ();
});

Reference
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值