Benny Abramovici
Benny Abramovici

Reputation: 582

CCSequence not waiting for action to finish before next one starts

I am writing a blackjack game using cocos2D. Im using CCSequence a lot and in numerous places in my code have issues with it. The problem I'm having is that one action is firing before the previous one is done running. for example:

-(void)standButtonPressed:(id)sender
{
    [self removeChildByTag:333];

    if ((splitNumber<3)&&(numberSplitHits>0))
    {
        [self removeChildByTag:333];
        splitNumber++;
        if ([[hands objectAtIndex:splitNumber]handTotal]==0)
            goto end;
        [self afterSpliting];
        [self addArrow];
        return;
    }

    end:
    [self removeChildByTag:333];
    [[BackgroundLayer sharedBackground]menuSetup:hand gamePhase:3];
    BJDrawnCard *holeCard = [dealerHand getFlippedCard];
    [holeCard flipCard];
    [[SimpleAudioEngine sharedEngine] playEffect:SND_DEAL_CARD];
    [self generateDealerHandDisplay];
    [self updateDealerHandScoreDisplay];
    id myCallFun1 = [CCCallFunc actionWithTarget:self                  selector:@selector(finishDrawingDealer)];
    id myCallFun2 = [CCCallFunc actionWithTarget:self selector:@selector(checkWhoWonHand)];
    id myCallFun3 = [CCCallFuncND actionWithTarget:[BackgroundLayer sharedBackground]    selector:@selector(menuSetup:gamePhase:)data:(void*)6];
    CCDelayTime *delay = [CCDelayTime actionWithDuration:2];
    [self runAction:[CCSequence actions:myCallFun1,delay,myCallFun2,myCallFun3 ,nil]];
}

so myCallFunc2 would start running before myCallFun1 finishes. I have the same problem in other parts of my code when using CCSequence, actions would start in order but not wait for an action to finish before the next one starts.

Is there a better way to sequence actions, or maybe even a substitute to CCSequence?

here is the method that myCallFun1 calls:

-(void)finishDrawingDealer
{
if (dealerHand.handTotal<17)
{
drawnCard=[havila drawFromDeck];
 [drawnCard setDisplayFrame:[[CCSpriteFrameCache     sharedSpriteFrameCache]spriteFrameByName:drawnCard.imageFileName]];
 CCMoveTo *move =[self animateDealerCards:drawnCard andPosition:[self  dealerCardPosition]];
CCDelayTime *delay = [CCDelayTime
                      actionWithDuration:0.5];
[dealerHand getCard:drawnCard];

//Run the action

numDealerHits++;
[self performSelector:@selector(updateDealerHandScoreDisplay) withObject:nil    afterDelay:1.0];


if (dealerHand.handTotal<17) {
    id more = [CCCallFunc actionWithTarget:self selector:@selector(finishDrawingDealer)];


    [drawnCard runAction:[CCSequence actions:delay,move,delay,more,nil]];
} else {
    [drawnCard runAction:[CCSequence actions:delay,move,delay,nil]];
 }
if (dealerHand.handTotal>21)

    [self dealerBusted];
}
}

Upvotes: 0

Views: 866

Answers (1)

Ben Trengrove
Ben Trengrove

Reputation: 8729

The problem comes from that the CCCallFunc actions are instantaneous. They don't care about how long a given selector takes to run, all they care about is calling that selector. After they have called their selector they have effectively finished their job and then the sequence moves onto the next action.

Instead what you can do is call the next method at the end of each method like follows. I also noticed you wanted a delay which you could do with a sequence and CCCallFunc.

- (void)finishDrawingDealer
{
    //Do your work that takes time

    //Once it has finished
    id callNextMethod = [CCCallFunc actionWithTarget:self selector:@selector(checkWhoWonHand)];
    id sequence = [CCSequence actions:[CCDelayTime actionWithDuration:2.0f], callNextMethod, nil];
    [self runAction:sequence];
}

Upvotes: 2

Related Questions