【问题标题】:Box2D Infinite Loop (b2World::SolveTOI)Box2D 无限循环 (b2World::SolveTOI)
【发布时间】:2013-09-09 23:03:38
【问题描述】:

我在 iOS 上使用 Box2D 和 Cocos2D。

游戏有时会卡住,这是由 b2World::SolveTOI 上的无限循环引起的。

for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
    {
        // Invalidate TOI
        c->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag);
        c->m_toiCount = 0;
        c->m_toi = 1.0f;
    }

我有一个“英雄”必须收集硬币的游戏。硬币是物体,通过接触监听器,我将物体添加到一个数组中,以便稍后在数组满时销毁它们(计数 = 2)。

以下是我如何将实体添加到数组中:

+ (void) addBodyToDestroy:(b2Body *)body {
[toDestroyArray addObject:[NSValue valueWithPointer:body]];
}

我是这样销毁它们的:

+ (void) destroyAllBodies {

b2World *world = [InGame getWorld];

for (NSValue *bodyValue in toDestroyArray)
{
    b2Body *body;
    body = (b2Body*)[bodyValue pointerValue];
    world->DestroyBody(body);
    body = NULL;
}

[toDestroyArray removeAllObjects];
}

我觉得很奇怪的是它不会每次都冻结,只是有时,而且我不知道什么似乎阻塞了......

解决方案: body被多次添加到要销毁的数组中,所以当数组满时,多次被销毁,导致死循环。

【问题讨论】:

  • 你试过添加断点和NSLogs吗?
  • 是的,有问题的循环是这个:for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) 但我不确定我是否真的理解它的作用,似乎m_contactManager.m_contactList 没有结束。

标签: iphone ios cocos2d-iphone box2d objective-c++


【解决方案1】:
  1. 联系人管理器的b2Contact是链表数据。 所以,for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) 表示从 m_contactList 开始并循环直到 c->next 遇到 NULL

  2. 我不知道你的接触监听器是如何工作的,但是你必须注意世界步、碰撞检查和销毁的时间。 因为,在世界步进时,每次有联系人时都会调用联系人监听器。因此,如果您的联系人监听器旨在存储联系人数据,那么您必须处理 world step 和 destroy 之间的所有联系人数据。 (如果不这样做,联系人数据中可能会有被破坏的主体的悬空指针)

  3. 如果要在硬币填满数组时销毁,最好检查数组是否有相同的对象。

【讨论】:

  • 这是我的联系人监听器。我没有检查尸体是否已经进入阵列,所以我想我不止一次试图摧毁它。我使用 userData 来避免数组并且它有效!
【解决方案2】:

for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) 是一个非常不寻常的 for 循环,至少从我的经验来看是这样。我可以清楚地解释它的作用,也许这会对你有所帮助。

这就是 for 循环的工作原理:

for( /*code called at beginning, usually to create a counting variable*/;/*code that is checked for a boolean value every loop.  True means loop again, false means stop.  Usually this is checking the value of the counting variable.*/;/*code that is called at the end of each loop.  Usually this is advancing the counting variable*/) {
//Code inside the loop that does stuff many times
}

所以对于这个循环:

  1. 循环开始。一个名为c 的新b2Contact 指针被创建并分配给m_contactManagerm_contactList 属性的值。

  2. 循环检查c 的值并确定truefalse 的值。在这种情况下,由于c 似乎是一个对象的实例,它可能正在检查c 是否为nil

  3. 在每个循环结束时,c 被设置为指向cm_next 成员。这很奇怪,因为c 不再是m_contactList,而是m_contactList 包含的东西。再一次,这可能是完全正常的。你应该知道你的代码是做什么的。

【讨论】:

  • 是的,我知道这一点。但不同寻常的是,c 从来都不是nil,所以我永远不会跳出循环。我很好奇,我似乎无法理解,这个循环对物理引擎有什么作用?
  • 你从哪里得到这个循环的?
  • 它来自 Box2D 的 b2World 类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
  • 2013-09-05
  • 1970-01-01
相关资源
最近更新 更多