没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
Box2D 是一个用于游戏的 2D 刚体仿真库。程序员可以在他们的游戏里使用它,它可以使物体的运动 更加可信,让世界看起来更具交互性。从游戏的视角来看,物理引擎就是一个程序性动画 (procedural animation)的系统,而不是由动画师去移动你的物体。你可以让牛顿来做导演。 Box2D 是用可移植的 C++ 来写成的。引擎中定义的大部分类型都有 b2 前缀,希望这能消除它和你 游戏引擎之间的名字冲突。
资源推荐
资源详情
资源评论
Box2D v2.0.1 用户手册
原文:Box2D v2.0.2 User Manual
译者:Aman JIANG(江超宇),翻译信息。
1. 导言
1.1 关于
Box2D 是一个用于游戏的 2D 刚体仿真库。程序员可以在他们的游戏里使用它,它可以使物体的运动
更加可信,让世界看起来更具交互性。从游戏的视角来看,物理引擎就是一个程序性动画(procedural
animation)的系统,而不是由动画师去移动你的物体。你可以让牛顿来做导演。
Box2D 是用可移植的 C++ 来写成的。引擎中定义的大部分类型都有
b2
前缀,希望这能消除它和你
游戏引擎之间的名字冲突。
1.2 必备条件
在此,我假定你已经熟悉了基本的物理学概念,例如质量,力,扭矩和冲量。如果没有,请先考虑读
一下 Chris Hecker 和 David Baraff (google 这些名字)的那些教程,你不需要了解得非常细致,但他们
可以使你很好地了解一些基本概念,以便你使用 Box2D。
Wikipedia 也是一个极好的物理和数学知识的获取源,在某些方面它可能比 google 更有用,因为它
的内容经过了精心的整理。
这不是必要的,但如果你好奇 Box2D 内部是如何工作的,你可以看 这些文档。
因为 Box2D 是使用 C++ 写成的,所以你应该具备 C++ 程序设计的经验,Box2D 不应该成为你的
第一个 C++ 程序项目。你应该已经能熟练地编译,链接和调试了。
1.3 核心概念
Box2D 中有一些基本的对象,这里我们先做一个简要的定义,在随后的文档里会有更详细的描述。
刚体(rigid body)
一块十分坚硬的物质,它上面的任何两点之间的距离都是完全不变的。它们就像钻石那样坚硬。在后
面的讨论中,我们用
物体
(body)来代替刚体。
形状(shape)
一块严格依附于物体(body)的 2D 碰撞几何结构(collision geometry)。形状具有摩擦(friction)和恢
复(restitution)的材料性质。
约束(constraint)
一个约束(constraint)就是消除物体自由度的物理连接。在 2D 中,一个物体有 3 个自由度。如果我
们把一个物体钉在墙上(像摆锤那样),那我们就把它约束到了墙上。这样,此物体就只能绕着这个钉子旋
转,所以这个约束消除了它 2 个自由度。
接触约束(contact constraint)
一个防止刚体穿透,以及用于模拟摩擦(friction)和恢复(restitution)的特殊约束。你永远都不必创建
一个接触约束,它们会自动被 Box2D 创建。
关节(joint)
它是一种用于把两个或多个物体固定到一起的约束。Box2D 支持的关节类型有:旋转,棱柱,距离等
等。关节可以支持限制(limits)和马达(motors)。
关节限制(joint limit)
一个关节限制(joint limit)限定了一个关节的运动范围。例如人类的胳膊肘只能做某一范围角度的运
动。
关节马达(joint motor)
一个关节马达能依照关节的自由度来驱动所连接的物体。例如,你可以使用一个马达来驱动一个肘的
旋转。
世界(world)
一个物理世界就是物体,形状和约束相互作用的集合。Box2D 支持创建多个世界,但这通常是不必要
的。
2. Hello Box2D
2.1 创建一个世界
每个 Box2D 程序都将从一个世界对象(world object)的创建开始。这是一个管理内存,对象和模拟的
中心。
要创建一个世界对象,我们首先需要定义一个世界的包围盒。Box2D 使用包围盒来加速碰撞检测。尺
寸并不关键,但合适的尺寸有助于性能。这个包围盒过大总比过小好。
b2AABB worldAABB;
worldAABB.lowerBound.Set(-100.0f, -100.0f);
worldAABB.upperBound.Set(100.0f, 100.0f);
•
注意:
worldAABB 应该永远比物体所在的区域要大,让 worldAABB 更大总比太小要好。如果一
个物体到达了 worldAABB 的边界,它就会被冻结并停止模拟。
接下来我们定义重力矢量。是的,你可以使重力朝向侧面(或者你只好转动你的显示器)。并且,我们
告诉世界(world)当物体停止移动时允许物体休眠。一个休眠中的物体不需要任何模拟。
b2Vec2 gravity(0.0f, -10.0f);
bool doSleep = true;
现在我们创建世界对象。通常你需要在堆(heap)上创建世界对象,并把它的指针保存在某一结构中。
然而,在这个例子中也可以在栈上创建。
b2World world(worldAABB, gravity, doSleep);
那么现在我们有了自己的物理世界,让我们再加些东西进去。
2.2 创建一个地面盒
物体通常由以下步骤来创建:
1. 使用位置(position),阻尼(damping)等定义一个物体
2. 使用世界对象创建物体
3. 使用几何结构,摩擦,密度等定义形状
4. 在物体上创建形状
5. 可选地调整物体的质量以和附加的形状相匹配
第一步,我们创建地面体。要创建它我们需要一个
物体定义
(body definition),通过物体定义我们来
指定地面体的初始位置。
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, -10.0f);
第二步,将物体定义传给世界对象来创建地面体。世界对象并不保存到物体定义的引用。地面体是作
为静态物体(static body)创建的,静态物体之间并没有碰撞,它们是固定的。当一个物体具有零质量的
时候 Box2D 就会确定它为静态物体,物体的默认质量是零,所以它们默认就是静态的。
b2Body* ground = world.CreateBody(&groundBodyDef);
第三步,我们创建一个地面的多边形定义。我们使用 SetAsBox 简捷地把地面多边形规定为一个盒子
(矩形)形状,盒子的中点就位于父物体的原点上。
b2PolygonDef groundShapeDef;
groundShapeDef.SetAsBox(50.0f, 10.0f);
其中,SetAsBox 函数接收了半个宽度和半个高度,这样的话,地面盒就是 100 个单位宽(x 轴)以及
20 个单位高(y 轴)。Box2D 已被调谐使用米,千克和秒来作单位,所以你可以用米来考虑长度。然而,
改变单位系统是可能的,随后的文档中会有讨论。
在第四步中,我们在地面体上创建地面多边形,以完成地面体。
groundBody->CreateShape(&groundShapeDef);
重申一次,Box2D 并不保存到形状或物体的引用。它把数据拷贝到 b2Body 结构中。
注意每个形状都必须有一个父物体,即使形状是静态的。然而你可以把所有静态形状都依附于单个静
态物体之上。这个静态物体之需求是为了保证 Box2D 内部的代码更具一致性,以减少潜在的 bug 数
量。
可能你已经注意到了,大部分 Box2D 类型都有一个 b2 前缀。这是为了降低它和你的代码之间名字冲
突的机会。
2.3 创建一个动态物体
现在我们已经有了一个地面体,我们可以使用同样的方法来创建一个动态物体。除了尺寸之外的主要
区别是,我们必须为动态物体设置质量性质。
首先我们用 CreateBody 创建物体。
b2BodyDef bodyDef;
bodyDef.position.Set(0.0f, 4.0f);
b2Body* body = world.CreateBody(&bodyDef);
接下来我们创建并添加一个多边形形状到物体上。注意我们把密度设置为 1,默认的密度是 0。并
且,形状的摩擦设置到了 0.3。形状添加好以后,我们就使用 SetMassFromShapes 方法来命令物体通
过形状去计算其自身的质量。这暗示了你可以给单个物体添加一个以上的形状。如果质量计算结果为 0,
那 么 物 体 会 变 成 真 正 的 静 态 。 物 体 默 认 的 质 量 就 是 零 , 这 就 是 为 什 么 我 们 无 需 为 地 面 体 调 用
SetMassFromShapes 的原因。
b2PolygonDef shapeDef;
shapeDef.SetAsBox(1.0f, 1.0f);
shapeDef.density = 1.0f;
shapeDef.friction = 0.3f;
body->CreateShape(&shapeDef);
body->SetMassFromShapes();
这就是初始化过程。现在我们已经准备好开始模拟了。
2.4 模拟(Box2D 的)世界
我们已经初始化好了地面盒和一个动态盒。现在是让牛顿接手的时刻了。我们只有少数几个问题需要
考虑。
Box2D 中有一些数学代码构成的
积分器
(integrator),积分器在离散的时间点上模拟物理方程,它将
与游戏动画循环一同运行。所以我们需要为 Box2D 选取一个时间步,通常来说游戏物理引擎需要至少
60Hz 的速度,也就是 1/60 的时间步。你可以使用更大的时间步,但是你必须更加小心地为你的世界调
整定义。我们也不喜欢时间步变化得太大,所以不要把时间步关联到帧频(除非你真的必须这样做)。直截
了当地,这个就是时间步:
float32 timeStep = 1.0f / 60.0f;
除了积分器之外,Box2D 中还有
约束求解器
(constraint solver)。约束求解器用于解决模拟中的所有
约束,一次一个。单个的约束会被完美的求解,然而当我们求解一个约束的时候,我们就会稍微耽误另
一个。要得到良好的解,我们需要迭代所有约束多次。建议的 Box2D 迭代次数是 10 次。你可以按自己
的喜好去调整这个数,但要记得它是速度与质量之间的平衡。更少的迭代会增加性能并降低精度,同样
地,更多的迭代会减少性能但提高模拟质量。这是我们选择的迭代次数:
int32 iterations = 10;
注意时间步和迭代数是完全无关的。一个迭代并不是一个子步。一次迭代就是在时间步之中的单次遍
历所有约束,你可以在单个时间步内多次遍历约束。
现在我们可以开始模拟循环了,在游戏中模拟循环应该并入游戏循环。每次循环你都应该调用
b2World::Step,通常调用一次就够了,这取决于帧频以及物理时间步。
这个 Hello World 程序设计得非常简单,所以它没有图形输出。胜于完全没有输出,代码会打印出动
态物体的位置以及旋转角度。Yay!这就是模拟 1 秒钟内 60 个时间步的循环:
for (int32 i = 0; i < 60; ++i)
{
world.Step(timeStep, iterations);
b2Vec2 position = body->GetPosition();
float32 angle = body->GetAngle();
printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
}
2.5 清理工作
当一个世界对象超出它的作用域,或通过指针将其 delete 时,所有物体和关节的内存都会被释放。
这能使你的生活变得更简单。然而,你应该将物体,形状或关节的指针都清零,因为它们已经无效了。
2.6 关于 Testbed
一旦你征服了 HelloWorld 例子,你应该开始看 Box2D 的 testbed 了。testbed 是一个单元测试框
架以及演示环境,这是一些它的特点:
• 可移动和缩放的摄像机
• 鼠标拣选动态物体的形状
• 可扩展的测试集
• 通过图形界面选择测试,调整参数,以及设置调试绘图
• 暂停和单步模拟
• 文字渲染
剩余30页未读,继续阅读
资源评论
beMyBest
- 粉丝: 18
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- MATLAB【面板】的语音滤波设计.zip
- MATLAB【面板】汉字语音识别.zip
- MATLAB【面板】汉字识别.zip
- MATLAB【面板】的运动行为检测.zip
- MATLAB【面板】火焰识别系统设计.zip
- MATLAB【面板】基于DWT+SVD结合傅里叶变换的数字图像水印水印系统.zip
- MATLAB【面板】火焰烟雾检测.zip
- MATLAB【面板】交通道路标识识别.zip
- MATLAB【面板】家居防火识别系统.zip
- MATLAB【面板】教室人数统计.zip
- MATLAB【面板】考勤系统设计.zip
- MATLAB【面板】金属表面缺陷分析.zip
- MATLAB【面板】口罩识别.zip
- slm 增材制造选区激光熔化SLM的粉床数值模拟 备注:资料一直在更新,不断完善,尽可能把所有的内容讲详细 1该模拟资料包含粉床建立部分(EDEM,和Gambit软件)以及模型模拟部分Flow
- MATLAB【面板】垃圾分类系统.zip
- MATLAB【面板】口罩检测.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功