【问题标题】:Error removing sprites from a spritesheet in Cocos2D在 Cocos2D 中从 spritesheet 中删除 sprite 时出错
【发布时间】:2012-03-10 13:40:11
【问题描述】:

我正处于 iphone 游戏的初始构建阶段,我正在使用精灵表来创建一些随机的人,每个人都有头发、衣服等的子精灵。

我正在使用 CCSpriteBatchNode 将我的精灵图像存储在精灵表中。我现在只是在进行初始设置测试,您可以在其中点击屏幕以生成一组新的随机人员。所以奇怪的是,你可以点击一次,它会删除旧人并用新人替换他们,但第二次,它会崩溃并出现错误: “CCSpriteBatchNode 不包含精灵。无法删除它” 现在我确定我已将精灵添加到批处理节点,在我的 Person.m 构造函数中我有这一行:

        [spriteSheet addChild:person];

在我的 ccTouchesEnded 测试代码中,我有以下代码:

//updated with changes suggested by Mazyod and Jer
for(int i=6; i>=0; i--){
    Person *per = [_people objectAtIndex:i];
    [_people fastRemoveObjectAtIndex:i];
    [_spritesheet removeChild:per cleanup:YES];
    per = nil;
}


for(int i = 0; i < 7; i++){
    Person *per = nil;
    per = [Citizen personFromCountry:_country1 WithSpriteSheet:_spritesheet];
    per.position = ccp(100 + (50 * i),160);
    [_people addObject:per];
    [_spritesheet addChild:per];
}

有人可以建议我缺少什么吗?我已经阅读了一堆关于 cocos2d 中的 spritesheets 的内容,并且了解到删除单个 sprite 是很棘手的,所以我确信我需要在这里添加一些重要的行。感谢您的帮助!

编辑:我用谷歌搜索了错误并找到了这个线程:http://www.cocos2d-iphone.org/forum/topic/17170 这似乎证实了 Cocos2d 认为我没有将精灵添加到精灵表中 - 但我是,正如事实上,精灵第一次正确添加,而不是第二次。

一种解决方案是完全避免移除精灵,只是让它们不可见,并在需要重复使用时用新特性重新绘制它们。我宁愿知道真正的解决方案是什么,因为它看起来更干净。

【问题讨论】:

  • 如果您依赖子项的顺序,请避免使用 fastRemoveObjectAtIndex。实际上,完全避免使用 fastRemoveObjectAtIndex。
  • 好的,我会记住的。我是 Objective-C 的新手,来自 C++、Java、Javascript 等背景,所以 obj-c 处理数组和字符串的复杂方式让我非常沮丧。

标签: objective-c ios xcode cocos2d-iphone sprite-sheet


【解决方案1】:

看来你需要改变

[_people addObject:per];

[_people replaceObjectAtIndex:i withObject:per];

在您的第一个循环中,您只是将数组中对象的值设置为 nil,而不是将其从数组中删除。在第二个循环中,您只需将其添加到数组的末尾,但您的数组中已经有 7 个 nil。

让我知道它是否有效。

【讨论】:

  • 嘿,你说得对!看起来 replaceObjectAtIndex:withObject: 是 Cocos3D 的数组类的成员,而不是 Cocos2D。我能够使用 fastRemoveObjectAtIndex 和 addObject 实现相同的效果。但是原来的问题仍然存在。
  • replaceObjectAtIndex:withObject: 也是我认为你正在使用的 NSMutableArray 的一部分,但无论如何......我总是对使用 addObject 等方法有点犹豫,因为你并不总是确定你的数组为空。尝试使用 insertObject:atIndex: 而不是 addObject - 这样您就可以准确地知道这些对象的插入位置。如果这仍然给您带来问题,您可以开始在调试器中设置断点以查看发生了什么,或者使用 addChild:z:tag 为您的精灵添加标签,然后在完成后使用 removeChildByTag。
【解决方案2】:

好吧,我现在可以帮你弄清楚一件事:

任何 CCNode 只能是一个父节点的子节点。即它必须有一个单亲。

但是,你这里有什么:

for(int i=0; i<7; i++){
    Person *per = [_people objectAtIndex:i];
    [self removeChild:per cleanup:YES];
    [_spritesheet removeChild:per cleanup:YES];
    per = nil;
}

建议您尝试同时将人添加到 spriteSheet 和 self.. 检查您的日志,它必须有类似的内容:

cocos2d: removeChild,未找到子节点。

从你得到的错误来看,我打赌这个人被添加到自己而不是精灵表中。

那么,如何解决呢?

好吧,您必须将人作为孩子添加到 spriteSheet,然后将 spriteSheet 添加到自己作为孩子。 (实际上,添加它们的顺序无关紧要)。

解决这个问题,也许这个问题会消失,或者至少会更清楚,以便我们为您提供帮助。

【讨论】:

  • 好点 - 我没有意识到这一点,虽然我实际上并没有添加精灵两次,只是在那里删除了两次。我删除了 [self removechild],但仍然出现同样的错误。
【解决方案3】:

我只想在这里提一下我在这个问题上的经验以及我是如何解决它的。

请记住,您要么尝试删除从未添加的子项..

试图删除一个孩子 TWICE。

对我来说就是这种情况。我的游戏中的碰撞检测是可靠的(至少我认为)。然后随机地,比如每 7-10 次运行中的 1 次......我会遇到这个崩溃。我意识到这是因为我对我的射弹进行了编码,一旦它们与目标相交就会被移除。

但是,如果我的 tick 方法检测到它一次与 MORE then 1 个目标发生冲突,我没有设置故障保护。

这是因为对于每个射弹,我遍历每个目标以检查碰撞,然后在检测到碰撞时移除相应的投影。所以我创建了一个简单的 BOOL,如果它已经与目标发生碰撞,则将其设置为 YES。然后我只在弹丸没有与任何东西碰撞时检查碰撞。

所以...之前:

if (CGRectIntersectsRect(projectileRect, targetRect))
{
//code to remove projectile
}

之后:

if (CGRectIntersectsRect(projectileRect, targetRect) && projectile.hasHitaTarget == NO)
{
//code to remove projectile
}

【讨论】:

    猜你喜欢
    • 2014-03-29
    • 2015-07-01
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2018-03-14
    相关资源
    最近更新 更多