Box2D v2.3.0 用户指南(第十一章)

翻译 2017年01月03日 21:52:17



第十一章零碎资料(loose ends)

11.1用户数据(user data

b2Fixtureb2Body,以及b2Joint类允许你通过一个通用指针(void pointer)来附加一个用户数据,如果你需要检查Box2D的数据结构来看他们是怎样关联到游戏引擎中的对象的时候,会觉得用户数据非常方便。

例如,一种非常典型的用法是将一个角色(actor)的指针附加到它对应的刚体上(注:通过设置刚体的UserData属性),这建立了一个循环引用,如果你有角色对象,你可以获取它对应的物体对象,如果你有物体对象,你也可以获取它对应的角色对象。

GameActor*actor = GameCreateActor();

b2BodyDefbodyDef;

bodyDef.userData= actor;

actor->body= box2DWorld->CreateBody(&bodyDef);

下面是一些需要用到用户数据的具体例子:

·通过碰撞结果对角色施加伤害

·在玩家进入一个AABB中的时候调用一段脚本

·Box2D通知你一个关节要被析构掉的时候,获取一个游戏元素(结构)

注意你可以有选择的使用或者不使用用户数据,你可以用它存放任何东西。但是你前后需要保持一致。例如,如果你想要在物体上存储一个角色的指针,那么对于所有的物体,都需要将其对应的角色指针存储到用户数据中。千万不要在一个物体中存储角色指针,而在另一个物体中存储一个别的乱七八糟的(foo)指针,当将角色物体指针转强制换成其他的指针的时候,会导致异常发生。

用户数据指针默认指向NULL。

对于装置,你可能想要定义一个用户数据结构用来存储游戏中特定的信息,例如材质类型,特效钩子(effecthooks),声音钩子(sound hooks)等等。

structFixtureUserData

{

int materialIndex;

};

FixtureUserDatamyData = new FixtureUserData;

myData->materialIndex= 2;

b2FixtureDeffixtureDef;

fixtureDef.shape= &someShape;

fixtureDef.userData= myData;

b2Fixture*fixture = body->CreateFixture(&fixtureDef);

deletefixture->GetUserData();

fixture->SetUserData(NULL);

body->DestroyFixture(fixture);

 

11.2隐式析构(implicitdestruction

Box2D不使用引用计数(referencecounting),所以如果你析构一个物体的话,那么它就真的不存在了。要访问一个已经释放了的物体指向的空间,会导致未知的问题。换句话说,你的程序很可能会崩溃。为了修复这些问题,在Debug编译模式下的内存管理器会将释放掉的内存区域填充上“FDFDFDFD”,这样在某些情况下,能使得查找问题原因变得更容易。

如果你析构了Box2D中的实体,你需要自己确保删掉所有指向被析构物体的引用,如果你只有一个实体的引用,那么很容易这样做,但是如果你有很多引用的话,那么你就应该考虑实现一个句柄类(handleclass)来封装一下原始指针(raw pointer)。

通常在Box2D中你会构造和析构很多物体、形状和关节。这些实体在某种意义上说都是由Box2D来管理的,如果你析构一个物体的话,那么所有相关的形状和关节都自动析构掉了,这就是标题中所谓的隐式析构。

当你析构一个物体的时候,所有附加到它上面的形状,关节和接触都被析构掉了,这就叫做隐式析构。(这个地方不知道为什么又要来一遍,原文中就是这么说的…)所有连接到这些析构掉的关节或者接触的物体都被唤醒(woken)了。这种处理方式通常很方便,但是你要留意一个严重的问题:你需要将指向这些析构掉的形状和关节的指针置为NULL,否则,当你的程序后面尝试访问或者析构这些对象的时候,它会死的很惨(diehorribly)。

为了帮助你将关节指针置为NULL,Box2D提供了一个叫b2DestructionListener的监听类,你可以实现这个类,然后将这个类传递给世界对象。接着世界对象就会在有关节被隐式析构的时候通知你的实现类。

需要注意的是,当某个关节或者装置被显示析构掉的时候,是没有通知的,这种情况下所有关系非常明确,你可以立即进行必要的清理工作。如果你愿意的话,你可以调用你自己实现的b2DestructionListener类中的清理方法,以保持方法的统一性。

隐式析构在很多情况下非常方便,但是同时它也可能让你的程序崩溃。你可能在你的代码中某处存储指向形状、关节等实体的指针,当指向的物体被析构的时候,这些指针也就失效了,更糟糕的情况是:你想一下,关节的创建代码通常和与它相关联的物体的管理代码无关,例如,testbed为了模拟和屏幕物体的交互而创建的b2MouseJoint类型的关节。

当隐式析构发生时,Box2D提供了一个回调机制来通知你的应用。这给你的程序提供了一个机会来将那些无效指针置为NULL,这个回调机制会在后面做描述。

你可以实现一个b2DestructionListener类,允许b2World来通知你某个形状或者关节被隐式析构了(由于相关的物体被析构了),这可以避免你的代码访问野指针。

classMyDestructionListener: public b2DestructionListener

{

void SayGoodbye(b2Joint* joint)

{

    // remove all references to joint

}

};

然后你需要将你的析构监听器(destructionlistener)的实例注册到世界中,在世界对象的初始化方法中使用下面的语句进行注册:

myWorld->SetListener(myDestructionListener);

 

11.3像素和坐标系(pixels andcoordinate systems

回忆一下我们讲过的,Box2D使用MKS(米,千克,秒)单位制以及弧度制,在使用米为单位的时候,你可能会遇到麻烦,因为你的游戏是用像素来作为单位的。在testbed中我们有一个游戏完全使用米作为单位,仅仅需要使用OpenGL提供的视图变换(viewporttransformation)来将世界坐标转换为屏幕坐标系下的尺寸。

floatlowerX = -25.0f, upperX = 25.0f, lowerY = -5.0f, upperY = 25.0f;

gluOrtho2D(lowerX,upperX, lowerY, upperY);

如果你的游戏必须要再像素单位制下才能工作,那么当你从Box2D重传出参数时,需要将长度单位从米转换为像素。当你需要向Box2D中传入参数时,需要将长度单位从像素转换为米。这样能够提高物理模拟的稳定性。

你需要一个合理的转换因子(conversionfactor),我建议根据你的角色大小来做一个合理的选择。假设你决定使用50像素来代表1米(因为你的角色可能是75像素高),那么你可以通过下面的方程来进行转换:

xMeters= 0.02f * xPixels;

yMeters= 0.02f * yPixels;

反过来:

xPixels= 50.0f * xMeters;

yPixels= 50.0f * yMeters;

你应该考虑在你的游戏代码中使用MKS单位制,仅仅在渲染的时候使用像素。这样可以简化你的游戏逻辑,减少犯错的机会,因为在渲染时做变换可以被隔离为一小段代码。

如果你使用转换因子,你应该尝试去修改它,以保证不会出现异常。你也可以尝试去调整它来提高稳定性。



相关文章推荐

Box2D v2.3.0 用户指南(第九章)

Box2D v2.3.0 用户指南

Box2D v2.3.0 用户指南(第八章)

Box2D v2.3.0 用户指南

Box2D v2.3.0 用户指南(第十章)

Box2D v2.3.0 用户指南

Box2D v2.3.0 用户指南(第七章)

Box2D v2.3.0 用户指南

Box2D v2.3.0 用户指南(第二章)

Box2D v2.3.0 用户指南

Box2D v2.1.0用户手册翻译 - 第08章 关节(Joints)

第08章 关节(Joints) 8.1 关于 关节用于把物体约束到世界,或约束到其它物体上。在游戏中, 典型例子有木偶, 跷跷板和滑轮。用不同的方式将关节结合起来使用,...

Box2D v2.1.0用户手册(10)——世界(World Class)

第10章 世界(World Class) 关于 b2World类包含物体和关节。它管理着模拟的方方面面,并允许异步查询(就像AABB查询和光线投射)。 你与Box2D的大部分交...

Box2D v2.1.0用户手册(6)——夹具(Fixtures)

第06章 夹具(Fixtures) 6.1 关于 回想一下,形状并不知道物体的存在,可以独立使用。因此Box2D需要提供b2Fixture类,用于将形状附加到物体上。 fi...

Box2D v2.1.0用户手册翻译 - 第12, 13, 14章

内容很多摘自 Aman JIANG(江超宇)翻译的Box2D v2.0.1 用户手册 第12章 调试绘图(Debug Drawing) 实现 b2De...

Box2D v2.1.0用户手册(3)——公共模块(Common)

第03章 公共模块(Common) 3.1 关于 公共模块包含了配置(Settings),内存管理(memory management)和矢量数学(vector m...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Box2D v2.3.0 用户指南(第十一章)
举报原因:
原因补充:

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