CCMoveBy behaviour

1.2k views Asked by At

I'm getting stuck to implement some Cocos2D animations for my Tetris clone(that works perfectly, no logic bugs, i just want to perform some smooth animation when deleting rows).

The current code(no animation) just drops the block position, like this:

   block.position = ccp(block.position.x, block.position.y - kBlockSize);

This happens in a for loop for, classic tetris programming. But when i try to animate, like this:

id move = [CCMoveBy actionWithDuration:0.5f position:(0, -kBlockSize)];
[block runAction:move];

Some blocks just moves down once, even tough the action may be called multiple times for the same block(when breaking more than one row for example)...

Why that happens ? I know it's a little bit confusing, but the point is that i'm doing the same stuff and getting different results...i could post more code to help clarify!

Thanks!

2

There are 2 answers

0
Rob Segal On BEST ANSWER

I'm quite sure actions are parallel operations so you could be calling a CCMoveBy action before a previous one is completed. Some alternatives I have used are...

  1. Monitor for when the action completes by using a CCSequence finishing with a CCCallFunc action that sets a flag. Something like...

    id myAction = [[CCSequence runWithActions:[CCMoveBy actionWithDuration:0.5f position:(0, -kBlockSize)], [CCCallFunc actionWithTarget:self selector:@selector(myFunc)], nil]

  2. Roll your own solution using a velocity variable in a tick or update function where you can get a hold of delta time/# of ticks since the last update

Hope some of that helps.

0
Fernando On

Thank you guys, those answers help me a lot!

I've tried CCSequences before posting here, but without success. The problem was the following:

Inside the CCSequence that deletes a row, i have 2 actions: the first one fades out the entire row of blocks(duration of x seconds), and the second one drops all the blocks above the row(duration of y seconds).

This works fine if ONLY ONE row needs to be deleted, because if there is more than one row, the next CCSequence starts nearly the same time the previous, reading a incorrect position of the blocks above, leading to a incorrect cascade of blocks.

I solved that using a longer CCSequence, that takes a CCCallFuncND as the last argument:

id fadeOutSequence = [CCSequence actions:fadeout, destroyBlocks, notifyFadeFinish, nil];

//inside method specified for notifyFadeFinish:
id dropAbove = [CCSequence actions: dropBlocks, notifyDropFinish, nil];

//inside method specified for notifyDropFinish
//start a new delete sequence, if there is more rows to delete.

Now going to implement gravity mode, thanks again!