2
\$\begingroup\$

I'm trying to make a very simple collision detection procedure just for test purposes.
The problem is with the send/receive information between functions

I have these lines on the update method (could be later implemented for checking what kind of subclass node is)

CCSprite *sprite = [background spriteCollisionWithRect:player.boundingBox];
if (sprite!=nil) {
    [sprite removeFromParentAndCleanup:YES];
}

and this is the spriteCollisionWithRect method

-(CCSprite*)spriteCollisionWithRect:(CGRect)bounds
{
    for (CCSprite *sprite in _spritesArray) {
        if (CGRectIntersectsRect(sprite.boundingBox, bounds)) {
            return sprite;
        }
    }
    return nil;
}

Now, this way not all the sprites are removed. It only works occasionally. But if I remove the node inside the collision method instead of returning it, it works nicely.

-(CCSprite*)spriteCollisionWithRect:(CGRect)bounds
{
    for (CCSprite *sprite in _spritesArray) {
        if (CGRectIntersectsRect(sprite.boundingBox, bounds)) {
            [sprite removeFromParentAndCleanup:YES];
        }
    }
    return nil;
}

Why is this?

\$\endgroup\$
  • \$\begingroup\$ just realized that i forgot to update the _spritesArray!.. so, adding [_spritesArray removeObject:sprite]; before the return, it works just fine! \$\endgroup\$ – Khalizar May 18 '12 at 11:25
  • \$\begingroup\$ You can post an answer to your question and accept it. Nice work on finding the answer. \$\endgroup\$ – MichaelHouse May 18 '12 at 17:38
  • \$\begingroup\$ Do the removal from the _spritesArray in the update method, nex to the removeFromParentAndCleanup, not inside spriteCollisionWithRect. Doing it there is giving a function that's supposed to be just checking for a state a side-effect -- an example of the action-at-a-distance anti-pattern (en.wikipedia.org/wiki/…). Also, just adding that to the logic leaves you only finding a maximum of one collision per update cycle. \$\endgroup\$ – chaos May 18 '12 at 19:27
0
\$\begingroup\$

Beyond the collection-management issue you identified, it's because your first function exits, returning a sprite, as soon as one colliding sprite is found, so no further sprites are examined on that iteration.

The version that performs the removal internally checks collision on all the sprites.

\$\endgroup\$
  • \$\begingroup\$ yep, i know that.. and is because i'm checking on very few sprites so they could be 1 or 2 and not more than 3 and that's why i need to remove the sprite from the array (as i suggested on the firs comment of the question) :) \$\endgroup\$ – Khalizar May 25 '12 at 10:18
0
\$\begingroup\$

using an array to store the sprites to check for collision, means that if i remove some sprite, i certainly should update that array!! now i'm checking for collision always on the same sprite, even if it's removed from it's parent..

so the easiest way to fix the problem is as follows

-(CCSprite*)spriteCollisionWithRect:(CGRect)bounds
{
    for (CCSprite *sprite in _spritesArray) {
        if (CGRectIntersectsRect(sprite.boundingBox, bounds)) {
            [_spritesArray removeObject:sprite];
            return sprite;
        }
    }
    return nil;
}
\$\endgroup\$
  • \$\begingroup\$ This appears to only remove a maximum of one sprite per call, even in the case where multiple sprites may intersect the specified rectangle. Is that the desired side effect of this function call? \$\endgroup\$ – Zack The Human May 25 '12 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.