Tanner Ewing
Tanner Ewing

Reputation: 337

Calling on individuals of the same array cocos2d iphone

I have been working on a game for iphone and have run into a major snag. The game works as follows: the player controls the character at the bottom of the screen. They move the character back and forth to catch balls that are falling from the top of the screen. these ball are all part of an array which causes them to move down the screen. They all have the same pointer. *Ball. A method creates new balls when its called on. If the balls collide with the character they stack on top of on another. To do this they are removed from the array that moves them and added to another array that causes them to become part of a stack by making their X position equal the characters and there Y position to be where it was when they collided. My problem is as the stack gets taller the entire screen needs to scroll downward. So the character disappears off the screen and with each additional ball the bottom one ball also moves down and off the screen. keeping only three balls on screen at a time. I have tried making the second array move them down but is places all of them in the same position and thus destroys the "stack" Below is my update method. please inform me of how to make this work. I am a bit new to this so good explaination is greatly appreciated!!

Thanks Tanner

    if (CGRectIntersectsRect(SealRect, BallRect)) {

            BallIsMoving = NO;
            BallHasIntersectedSeal = NO;
            //BallIntersectedSeal = YES;
            [self CollisionRectUpdate];
            NumberOfCollisions = NumberOfCollisions + 1;
            Ball.position = ccp(SealSprite.position.x + 10, SealSprite.position.y + 20 + (NumberOfCollisions * 60));
            [BallArray_ removeObject: Ball];
            [BallHasCollidedArray_ addObject: Ball];

        }
}

for (CCSprite *Ball in BallHasCollidedArray_) {
    Ball.position = ccp(SealSprite.position.x + 10, Ball.position.y);

}
for (CCSprite *SealSprite in AllObjectsArray_) {

    if (NumberOfCollisions > 3) {

        FullScreenDisplacementSeal = (NumberOfCollisions - 4) * -60;

        if (SealSprite.position.y > FullScreenDisplacementSeal) { 

            SealSprite.position = ccp(SealSprite.position.x, SealSprite.position.y - 5);

        }
    }
}

for (CCSprite *Ball in BallHasCollidedArray_) {

    if (NumberOfCollisions > 3) {

        FullScreenDisplacement = (NumberOfCollisions - 4) * 60;
        Ball.position = ccp(Ball.position.x, Ball.position.y - FullScreenDisplacement);     
    }

}

}

I guess I need a way to act on all the "balls" in the BallHasCollidedArray while still acting on each one individually. This needs to be expressed so that even if there were 5000 balls it would still work.

Upvotes: 0

Views: 232

Answers (1)

Mac
Mac

Reputation: 14791

You're giving all your balls exactly the same y-coordinate in the line

Ball.position = ccp(Ball.position.x, FullScreenDisplacement);

As such, since they also have exactly the same x-coordinate, they will by definition be in the same place (as you describe).

Additionally, your math for deciding the displacement seems off to me:

FullScreenDisplacement = ((NumberOfCollisions - 3) * -60) + (NumberOfCollisions * 60)
                       = (-60 * NumberOfCollisions) + 180 + (60 * numberOfCollisions)
                       = 180

As you can see, after some simplification your number of collisions actually factors out. I think what you actually want is to displace each ball's original y-coordinate by the same amount as you displaced your seal (assuming it has been displaced correctly). I'll assume here that your balls are 60 pixels in height (hence the factor of 60 you have used):

for (CCSprite *Ball in BallHasCollidedArray_)
{
    if (NumberOfCollisions > 3)
    {
        FullScreenDisplacement = (NumberOfCollisions - 3) * -60;
        Ball.position = ccp(Ball.position.x, Ball.position.y - FullScreenDisplacement);
    }
}

If that's the case, is suspect your seal is probably also not in the right position, given the code you have posted for that. If so, the same approach applies.

Finally, you'll notice that FullScreenDisplacement is loop invariant - it's value does not change at any point in the loop. As such it's much more efficient to calculate it just once, outside the loop. The same also applies for the if test.

if (NumberOfCollisions > 3)
{
    FullScreenDisplacement = (NumberOfCollisions - 3) * -60;
    for (CCSprite *Ball in BallHasCollidedArray_)
    {
        Ball.position = ccp(Ball.position.x, Ball.position.y - FullScreenDisplacement);
    }
}

Additionally, I'm not sure what this ccp function you call does, but if it only creates a new position from the arguments, then the following is a much simpler and efficient equivalent:

Ball.position.y -= FullScreenDisplacement;

Hope all of the above helps. If anything doesn't make sense, or my proposed changes don't help matters, let me know and I'll tweak my answer to suit.

Upvotes: 1

Related Questions