我正在使用Box2D和Cocos2D for iOS。
游戏不时冻结,它是由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;
}
我有一个游戏,“英雄”必须收集硬币。硬币是主体,通过接触监听器,我在数组中添加主体,以便在数组满时(count = 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];
}
我觉得非常奇怪的是,它不会每次都冻结,有时候,我无法知道阻止什么... ...
解决方案: 身体被多次添加到要被破坏的数组中,所以当数组已满时,它被多次破坏,导致无限循环。
答案 0 :(得分:1)
b2联系人管理器的联系人是链表数据。
所以,for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
表示从m_contactList开始并循环,直到c->next
符合NULL
我不知道您的联系人听众是如何工作的,但您必须注意世界步骤,碰撞检查和销毁的时间。 因为,每当世界踩踏时有联系人,就会调用联系人监听器。因此,如果您的联系人侦听器旨在存储联系人数据,那么您必须处理world step和destroy之间的所有联系人数据。 (如果不这样做,联系人数据中可能会有被摧毁的身体的悬空指示)
如果要在填充数组时销毁硬币,最好检查数组是否有相同的对象。
答案 1 :(得分:0)
for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
是一个非常不寻常的循环。我可以清楚地解释它的作用,也许这会对你有帮助。
这就是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
}
所以对于这个循环:
循环开始。创建了一个名为b2Contact
的新c
指针,并将其指定为m_contactList
的{{1}}属性的值。
循环检查m_contactManager
的值,并确定c
或true
的值。在这种情况下,由于false
似乎是对象的实例,因此可能正在检查c
是否为c
。
在每个循环结束时,nil
设置为指向c
的{{1}}成员。这很奇怪,因为m_next
不再是c
,而是由c
包含的内容。然后,这可能是完全正常的。你应该知道你的代码做了什么。