Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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?

share|improve this question
    
just realized that i forgot to update the _spritesArray!.. so, adding [_spritesArray removeObject:sprite]; before the return, it works just fine! –  Khalizar May 18 '12 at 11:25
    
You can post an answer to your question and accept it. Nice work on finding the answer. –  Byte56 May 18 '12 at 17:38
    
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. –  chaos May 18 '12 at 19:27
    
@chaos you're so right! :) thanks –  Khalizar May 25 '12 at 10:24

2 Answers 2

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.

share|improve this answer
    
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) :) –  Khalizar May 25 '12 at 10:18
up vote 0 down vote accepted

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;
}
share|improve this answer
    
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? –  Zack The Human May 25 '12 at 22:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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