Box2D基本概念的学习记录

Box2D基本概念的学习记录

关于Box2D

Box2D 是一个用于游戏的 2D 刚体仿真库。程序员可以在游戏中使用它,让物体的运动更加可信,让世界看起来更具交互性。从游戏引擎的视角来看,物理引擎就是一个为程序化动画 (procedural animation)的系统。Box2D是用C++开发的一款物理引擎, 而本文用的是Box2dWeb,即Box2D的JS版本。

一些基本概念

Box2D使用了一些基本的对象来定义和模拟游戏世界。最重要的几个对象如下:* World(世界):最主要的Box2D对象, 包括了所有的世界对象并模拟着游戏的物理行为。* Body(刚体): 刚体可以由一个或多个通过设备附属在刚体上的形状组成。* Shapes(形状): 一个二维形状,如圆形或多边形, 这些是用于Box2D内的基础形状。* Fixture(设备): 将一个形状附属在一个刚体上,用于碰撞检测。设备持有额外的,非几何的数据,如摩擦,碰撞和滤器。* Joint(关节):用来将两个刚体以不同的方式限制在一起。比如,一个转动关节限制两个刚体共享一个共同的节点,同时它们可以通过这个节点自由的旋转。

计算单位系统

Box2D的所有计算使用米制系统, 而我们在绘图时使用的是像素, 因此需要建立一个米到像素的映射, 通常使用30像素代表1米。

创建世界的步骤

  1. 创建重力系数,重力系数通过b2Vec来创建, 接收两个参数,代表x和y的值。
  2. 设置是否允许睡眠,即当刚体处于空闲时,是否可以被排除计算。处于空闲的刚体,可以被碰撞唤醒。###一个简单的定义如下
var gravity = new Box2D.Common.Math.b2Vec2(0, 9.8),
    allowSleep = true;

var world = new Box2D.Dynamics.b2World(gravity, allowSleep);

有了世界,则可以添加刚体在世界中。

创建刚体的步骤

  1. 创建刚体(Body)定义对象数据(b2BodyDef), 设置定义对象的各种属性,包括刚体的位置,以及类型(动态或静态).静态刚体不受重力和其他刚体的碰撞影响。
  2. 创建设备(Fixture)定义对象数据(b2FixtureDef), 设置定义对象的各种属性, 包括摩擦系数,密度以及附加形状的恢复系数。
  3. 设置设备定义对象数据的形状属性,在Box2D中用到的两种形状为圆形(b2CircleShape)和多边形(b2PolygonShape)
  4. 调用World对象的crateBody方法, 传入刚体定义数据, 将返回一个刚体(Body)对象。
  5. 调用刚体(Body)的createFixture方法,传入设备定义数据, 这会把设备上的形状对象(Shape)附加到刚体上,并返回一个设备对象。

一个简单的定义如下

[javascript]  view plain copy
  1. //单位映射值  
  2.     var scale = 30;  
  3.   
  4.     //创建刚体定义数据对象  
  5.     var bodyDef = new b2BodyDef;  
  6.     //为静态刚体, 即不受碰撞影响  
  7.     bodyDef.type = b2Body.b2_staticBody;  
  8.     //位置  
  9.     bodyDef.position.x = 640 / 2 / scale;  
  10.     bodyDef.position.y = 450 / scale;  
  11.   
  12.     //创建设备定义数据对象  
  13.     var fixtureDef = new b2FixtureDef;  
  14.     //密度  
  15.     fixtureDef.density = 1.0;  
  16.     //摩擦  
  17.     fixtureDef.friction = 0.5;  
  18.     //恢复系数  
  19.     fixtureDef.restitution = 0.2;  
  20.     //设备形状为多边形  
  21.     fixtureDef.shape = new b2PolygonShape;  
  22.     //设置为矩形  
  23.     fixtureDef.shape.SetAsBox(320 / scale, 10 / scale);  
  24.   
  25.     //世界创建刚体, 刚体创建设备, 设备拥有形状  
  26.     var body = world.CreateBody(bodyDef);  
  27.     var fixture = body.CreateFixture(fixtureDef);  
[javascript]  view plain copy
  1.   

绘制世界

Box2D对我们来说主要是用来处理物理计算, 而我们自行处理绘制世界中的所有对象。尽管如此,Box2D还是给我们提供了一个简单的方法DrawDebugData(), 我们可以用它将世界绘制在Canvas上。在使用DrawDebugData()之前, 需要先通过定义b2DebugDraw对象,并将其传入world.setDeugDraw()方法来设置调试绘制环境。

可以通过如下方式设置调试绘制

[javascript]  view plain copy
  1. var context = document.getElementById('canvas').getContext('2d');  
  2. var debugDraw = new b2DebugDraw();  
  3.   
  4. //设置绘图上下文  
  5. debugDraw.SetSprite(context);  
  6. //设置绘图比例  
  7. debugDraw.SetDrawScale(scale);  
  8. //设置填充透明度  
  9. debugDraw.SetFillAlpha(0.3);  
  10. //设置线条厚度  
  11. debugDraw.SetLineThickness(1.0);  
  12. // 绘制所有的形状和关节  
  13. debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);  
  14. //使用调试绘图  
  15. world.SetDebugDraw(debugDraw);  

让世界动起来

让世界产生动画效果, 无非就是不断的重复擦除旧的数据, 绘制新的数据,在Box2D中,通过以下步骤产生动画效果:

  1. 告诉Box2D为一小段时间片(通常是1/60秒)进行模拟运算。我们通过调用world.Step()函数完成这一步骤。
  2. 清除旧的绘制数据, 这可以通过world.ClearForces()来完成。
  3. 绘制世界中的一切对象, 此时对象经过Box2D的运算,将会出现在新的位置, 可以使用world.DrawDebugData()或者我们自己的绘制函数来绘制。
  4. 重复1-3步骤。###以下是一段示范代码

[javascript]  view plain copy
  1. var timeStep = 1 / 60;  
  2. //设置速度约束求解器的迭代次数, 位置约束求解器迭代次数. 根据Box2d的文档, 8和3是建议的数值.  
  3. var velocityIterations = 8;  
  4. var positionIterations = 3;  
  5. function animate() {  
  6.     world.Step(timeStep, velocityIterations, positionIterations);  
  7.     world.ClearForces();  
  8.     world.DrawDebugData();  
  9.     setTimeout(animate, timeStep);  
  10. }  

world.Step接收3个参数: 每次计算的时间片, 速度约束求解器迭代次数, 位置约束求解器迭代次数。后面2个参数和数学的积分器相关, 看不懂也无关紧要, 我们根据Box2D的文档, 设置建议数值8和3就行了。Box2D内部使用了积分器算法进行计算。积分器在每个不同的时间点内模拟计算物理公式。 时间步长则是我们想要Box2D要模拟计算的总时间。在这里,我们设置了1/60秒, 则也是官方文档建议的数值。

总结

Box2D将一个游戏映射为一个世界, 当然可以有很多的世界,不过没有太多的必要。世界本身具有重力,一个世界拥有许多的刚体, 而刚体又拥有形状。形状则被设备持有,设备拥有各种系数,包括摩擦,密度,恢复等,刚体之间又可以通过关节连接。而这个世界中的一切运作都通过Box2D自动计算。Box2D帮助我们从复杂的数学和物理公式中脱离出来, 让我们将更多的精力放在了游戏逻辑上。游戏开发者就像是一个创始者,创造了一个世界,并设置了相关的参数,接着将Box2D丢入这个世界中, 这个世界就开始了生生不息的循环运作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值