box2D(转)

转自:http://www.ityran.com/thread-650-1-1.html

第六章  fixture
6.1关于
记得,shape不了解body,并且shape可以在物理模拟中被单独使用。因此Box2D
提供了b2Fixture类将shape附属到body上,fixture持有以下:
         单个外形a singleshape
      ·broad-phaseproxies
      ·密度,摩擦,和恢复
      ·碰撞过滤旗帜
      ·返回父辈body的指针
      ·用户数据user data

     ·传感器旗帜sensorflag
具体将在以下章节中描述


6.2创建Fixture

fixture是通过初始化fixture定义并把定义传递给父辈body创建的。
     b2FixtureDeffixtureDef;
     fixtureDef.shape=&myShape;
     fixtureDef.density=1.0f;
     b2Fixture*myFixture =myBody->CreateFixture(&fixtureDef);
这创建了fixture,并把它附属到body上。你没必要存储fixture指针,因为
当父辈body被破坏时,fixture会自动被破坏。

你可以在父辈body上破坏fixture,你可以用这种方法来创建一个易碎的对象。
否则
youcanjustleavethefixture andletthebodydestructiontakecare
of destroyingthe attachedfixtures.
       myBody->DestroyFixture(myFixture);


密度

Fixture的密度可以用来计算父辈body的质量性能。密度可以为零或者为正数。
对所有的fixture,你应该使用相似的密度,这样可以提高堆的稳定性。

当你设置密度时,Body的质量是不可改变的。你需要访问ResetMassData才能
改变。
      fixture->SetDensity(5.0f);
      body->ResetMassData();


摩擦

摩擦用来保证对象像现实生活中一样移动。Box2D提供了静态和动态摩擦,但都
需要使用相同的参数。 在Box2D模拟中,摩擦需要非常准确,摩擦强度与正常
力量成正比(这就是所谓的库仑摩擦)。

摩擦参数通常是设置在0和1之间,但也可以是任何非负价值。将值设为0,摩擦关
掉。值为1,摩擦增强。当计算两个shape之间的摩擦力的时候,Box2D必须结
合两个父辈夹具的摩擦参数。
This isdonewith thegeometricmean:
     float32friction;
     friction=sqrtf(shape1->friction*shape2->friction);
如果一个夹具含有零摩擦,那么接触也会有零摩擦。


恢复Restitution

恢复用来使对象弹回。恢复值通常设置在0和1之间。考虑将一个球坠到桌子上,
9值意味着这个球不能返回。这就是所谓的一个非弹性碰撞。1值意味着这个球会
准确快速的反弹。这就是所谓的“完全弹性碰撞”。恢复则是组合使用下列公式:
      float32restitution;
     restitution=b2Max(shape1->restitution,shape2->restitution);

夹具通过携带碰撞过滤器的信息来帮助你阻止游戏对象之间的碰撞。
当一个形状发展多种接触时候,恢复会被近似模拟.这是因为Box2D使用一个迭
代求解器进行求解。当碰撞速度小的时候,Box2D也采用弹性碰撞。这是为了防
止抖动。


过滤

碰撞过滤可以帮助你防止fixture之间的碰撞。例如,你创建一个骑着自行车的
角色,你像让这个自行车和角色与地形碰撞,但是你不想让自行车与角色碰撞(因
为他们必须重叠), Box2D通过类别和分组支持这样的过滤碰撞。
Box2D支持16种碰撞类别,对于每一个夹具,你都能制定其属于哪一个类别。你
也可以制定这个夹具可以与哪种类型碰撞。例如,

你可以在一个多人游戏中指定,所有玩家之间不能互相碰撞,怪物与怪物之间不
能碰撞,但是玩家与怪物之间可以碰撞。Thisis donewith maskingbits.例
如:
    playerFixtureDef.filter.categoryBits=0x0002;
    monsterFixtureDef.filter.categoryBits=0x0004;
    playerFixtureDef.filter.maskBits=0x0004;
    monsterFixtureDef.filter.maskBits=0x0002;
    这是碰撞规则:

         uint16catA =fixtureA.filter.categoryBits;
         uint16maskA =fixtureA.filter.maskBits;
         uint16catB =fixtureB.filter.categoryBits;
         uint16maskB =fixtureB.filter.maskBits;

          if((catA &maskB)!=0&&(catB&maskA) !=0)
         {
            //fixtures cancollide
          }
    碰撞组让你指定一个整体分类指标。你可以让所有包含相同群指标的夹具永
远碰撞或者从不碰撞(negative index).集团指标通常用于一些相关的东西,像
自行车的一部分,在下面的例子中,夹具1和夹具2一直互相碰撞,但是夹具3和

夹具4却始终不碰撞。
         fixture1Def.filter.groupIndex=2;
         fixture2Def.filter.groupIndex=2;
         fixture3Def.filter.groupIndex=-8;
         fixture4Def.filter.groupIndex=-8;

     不同的群指标(groupindex)夹具之间的碰撞,会根据类别和屏蔽位(mask
bits)而被过滤。换句话说,集团过滤优先级高于类别过滤。
     注意在Box2D中的额外碰撞过滤,清单如下:
          静态body上的夹具只能与动态body上的夹具碰撞
          运动的body上的夹具只能与动态body上的夹具碰撞
          相同body上的夹具永远不能互相碰撞
          Youcanoptionallyenable/disablecollisionbetweenfixtureson
bodiesconnectedby ajoint.

有时候当一个fixture被创建的时候,你可能需要修改它的碰撞过滤。你可以用
b2Fixture::GetFilterData和b2Fixture::SetFilterData获取和设置一个已经
存在的fixture的b2Filter结构。要注意过滤数据不会增加或删除接触,直到
下一个时间步。


6.3 传感器

有些时候,游戏逻辑需要知道,什么时候两个fixture相交但不会碰撞。这将通
过传感器实现。传感器可以检测碰撞但不会产生碰撞反应。

你可以将任一shape标记为传感器,传感器可以是静态或动态的。记得,每个物
体上可以有多个shape,并且传感器和实体shape是可以混合的。传感器可以
是静态的或者动态的。记住每个body都可以有多个fixture并且也可以有任何
的混合传感器,和固体fixture。

传感器器不会产生触点,有两种方式获得感应器的状态;
     1. b2Contact::IsTouching
     2. b2ContactListener::BeginContactandEndContact   

另外,有下边一些概念要记住:

1,钢体

2,形状

3,约束

4,接触约束

5,关节

6,关节限制

7,关节马达

8,世界

一、创建一个世界的步骤:

1.先创建世界的AABB盒子:

     b2AABB worldAABB;

     worldAABB.lowerBound.Set(-100.0f,-100.0f);

     worldAABB.upperBound.Set(100.0f,100.0f);

2.再设置世界的重力失量

   b2Vec2 gravity(0.0f,-10.0f);

3.再设置是否使能世界体眠功能

   bool doSleep = true;

4.创建世界

  b2World World(worldAABB,gravity,doSleep);

二、创建一个物体的步骤:

1.创建物体定义

   b2BodyDef groundBodyDef;

2.设置定义物体的初始坐标

  groundBodyDef.position.Set(0.0f,10.0f);

3.使用世界创建这个物体

b2Body *groundbody = world.CreatBody(&groundBodyDef);

4.创建物体定义形状

b2PolygonDef groundShapeDef;
groundShapeDef.SetAsBox(50.0f, 10.0f);

5.将形状绑定到物体

groundBody->CreateShape(&groundShapeDef);

三、创建活动物体

1.先使用世界创建一个物体

b2BodyDef bodyDef;
bodyDef.position.Set(0.0f, 4.0f);
b2Body* body = world.CreateBody(&bodyDef);

2.设置形状,并设定物体密度和摩擦系数

b2PolygonDef shapeDef;
shapeDef.SetAsBox(1.0f, 1.0f);
shapeDef.density = 1.0f;  //密码,如果密度为0说明物体是固定物体
shapeDef.friction = 0.3f;  //摩擦系数
body->CreateShape(&shapeDef);
body->SetMassFromShapes(); //通过物体形状和密度设置物体质量

四、模拟

float32 timeStep = 1.0f / 60.0f;

int32 iterations = 10;

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);
}

说明一下,以上的代码是box2D的2.0版的,2.2.0版好像形状这一块改了一些东西,我这里找到的是2.0版的说明文档

### Box2D关节(Revolute Joint)的详细用法和参数说明 旋关节(Revolute Joint)是 Box2D 中的一种关节类型,它允许两个刚体围绕一个固定的锚点进行相对旋。这种关节非常适合模拟铰链、车轮轴等需要旋自由度的场景[^3]。 以下是旋关节的关键参数及其作用: 1. **锚点(Anchor Point)** 旋关节的核心是一个固定的锚点,该点定义了两个刚体之间的连接位置。锚点可以通过 `b2RevoluteJointDef.Initialize` 方法设置。默认情况下,锚点位于第一个刚体的世界中心。 ```python jointDef.Initialize(bodyA, bodyB, anchor) ``` 2. **限制角度范围(Angle Limit)** 可以通过启用限制功能来约束旋的角度范围。这适用于模拟门铰链或其他具有有限旋角度的物体。 - `jointDef.enableLimit`:是否启用角度限制。 - `jointDef.lowerAngle` 和 `jointDef.upperAngle`:分别定义旋的下限和上限角度(单位为弧度)。注意,Box2D 使用弧度而非角度作为单位,因此需要将角度换为弧度(例如,45° = 45 * π / 180 ≈ 0.785 弧度)。 ```python jointDef.enableLimit = True jointDef.lowerAngle = 0 # 最小角度为 0 弧度 jointDef.upperAngle = 1.57 # 最大角度为 90° ``` 3. **马达功能(Motor Functionality)** 旋关节可以配置为带有马达功能,从而驱动刚体以特定速度旋。这适用于模拟发动机或风扇等需要主动旋的物体。 - `jointDef.enableMotor`:是否启用马达功能。 - `jointDef.motorSpeed`:马达的目标角速度(单位为弧度/秒)。 - `jointDef.maxMotorTorque`:马达的最大扭矩(单位为力矩),用于限制旋时的功率。 ```python jointDef.enableMotor = True jointDef.motorSpeed = 2 # 目标角速度为 2 弧度/秒 jointDef.maxMotorTorque = 10 # 最大扭矩为 10 ``` 4. **反作用力与反扭矩(Reaction Force and Torque)** 跟其他关节类似,旋关节也会产生反作用力和反扭矩。这些值可以通过关节对象获取,并可用于实现关节折断逻辑或其他游戏事件[^2]。 ```python reactionForce = joint.GetReactionForce(1 / timeStep) # 获取反作用力 reactionTorque = joint.GetReactionTorque(1 / timeStep) # 获取反扭矩 ``` ### 示例代码 以下是一个完整的示例代码,展示如何创建并配置一个旋关节: ```python import Box2D.Common.Math.b2Vec2 import Box2D.Dynamics.b2Body import Box2D.Dynamics.Joints.b2RevoluteJointDef # 创建静态和动态刚体 bodyA = world.CreateStaticBody(position=(0, 0)) # 静态刚体 bodyB = world.CreateDynamicBody(position=(1, 0)) # 动态刚体 # 定义旋关节 jointDef = b2RevoluteJointDef() jointDef.bodyA = bodyA jointDef.bodyB = bodyB jointDef.localAnchorA = (0, 0) # 锚点相对于 bodyA 的局部坐标 jointDef.localAnchorB = (-1, 0) # 锚点相对于 bodyB 的局部坐标 # 启用角度限制 jointDef.enableLimit = True jointDef.lowerAngle = 0 # 最小角度为 0 弧度 jointDef.upperAngle = 1.57 # 最大角度为 90° # 启用马达功能 jointDef.enableMotor = True jointDef.motorSpeed = 2 # 目标角速度为 2 弧度/秒 jointDef.maxMotorTorque = 10 # 最大扭矩为 10 # 创建关节 joint = world.CreateJoint(jointDef) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值