基础
Box2D提供了用于分配钩子和向量数学的最小基本功能。C接口允许大多数运行时数据和类型在src文件夹内部定义。
断言
Box2D会对不良输入进行断言。这包括发送NaN或无穷大值等情况。如果您对应该为正值的事物使用负值,例如密度,它也会进行断言。
如果检测到内部错误,Box2D也会进行断言。因此,建议从源代码构建Box2D。在我的计算机上,Box2D库的编译大约需要一秒钟。
您可能希望在应用程序中捕获断言。在这种情况下,您可以使用b2SetAssertFcn()。这允许您重写调试器中断和/或执行您自己的错误处理。
内存分配
Box2D通过内存池化有效地使用内存并最小化每帧分配。引擎快速适应模拟大小。在模拟的第一步或两步之后,不应再有每帧分配。
随着物体、形状和连接的创建和销毁,它们的内存将被回收利用。内部所有这些数据都存储在连续的数组中。当对象被销毁时,数组元素将被标记为空。当对象被创建时,它将使用数组中的空槽,使用高效的空闲列表。
一旦内部内存池被初始填充,唯一的分配应该是为了睡眠岛,因为它们的数据被复制出主模拟。通常,这些分配应该是不频繁的。
您可以使用b2SetAllocator()提供自定义分配器,并可以使用b2GetByteCount()获取分配的字节数。
版本
b2Version结构保存当前版本,因此您可以在运行时使用b2GetVersion()查询此版本。
b2Version version = b2GetVersion();
printf("Box2D版本 %d.%d.%d\n", version.major, version.minor, version.patch);
向量数学
Box2D包括一个小的向量数学库,包括类型b2Vec2、b2Rot、b2Transform和b2AABB。这些类型设计用于满足Box2D和接口的内部需求。所有成员都是公开的,因此您可以在应用程序中自由使用它们。
数学库保持简单,以使Box2D易于移植和维护。
多线程
Box2D已经针对多线程进行了高度优化。多线程不是必须的,默认情况下Box2D将单线程运行。如果性能对您的应用程序很重要,您应该考虑使用多线程接口。
Box2D多线程已经设计用于与应用程序的任务系统配合工作。Box2D不会创建线程。示例应用程序展示了如何使用开源任务系统enkiTS来实现这一点。
为每个创建的Box2D世界建立多线程,并且必须将其连接到世界定义中。有关更多详细信息,请参阅b2TaskCallback()、b2EnqueueTaskCallback()和b2FinishTaskCallback()。还请参阅b2WorldDef::workerCount、b2WorldDef::enqueueTask和b2WorldDef::finishTask。
Box2D的多线程设计侧重于数据并行性。其思想是利用多个核心尽快完成世界模拟。Box2D多线程不是设计用于任务并行性。通常在游戏中,您可能有一个渲染线程和一个音频线程,它们独立于主线程工作。这些是任务并行性的示例。
因此,当设计游戏循环时,您应该让Box2D广泛地使用多个核心来快速完成其工作,而不让其他线程试图与Box2D世界交互。
注意:虽然Box2D设计用于多线程,但其接口不是线程安全的。在模拟过程中或从多个线程修改Box2D世界将导致竞争条件。
从b2World_Step()之外的多个线程执行射线投射、形状投射和重叠测试是安全的。通常,在b2World_Step()之外进行任何只读操作是安全的多线程操作。如果您有多线程游戏逻辑,这可能非常有用。