RepeatForever bug?

I’ve created very simple animation which moves a balloon up and down:

    auto _action = RepeatForever::create(Sequence::create(MoveBy::create(1.0f, Vec2(0, 60)), MoveBy::create(1.0f, Vec2(0, -60)), NULL));
    balloonNode->runAction(_action);

Works.

Now I wanted to add a small random delay so not every balloon will start at the same time:

    float t = rand_0_1();
    auto _action = RepeatForever::create(Sequence::create(MoveBy::create(1.0f, Vec2(0, 60)), MoveBy::create(1.0f, Vec2(0, -60)), NULL));
    auto action = Sequence::createWithTwoActions(DelayTime::create(t), _action);
    balloonNode->runAction(action);

Doesn’t work. Nothing’s moving. Variable “t” is ok. I printed it and it has correct value (between 0 and 1). I’ve also tried any fixed “t”.

Now I’ve created alternative version using Repeat instead:

    float t = rand_0_1();
    auto _action = Repeat::create(Sequence::create(MoveBy::create(1.0f, Vec2(0, 60)), MoveBy::create(1.0f, Vec2(0, -60)), NULL), -1);
    auto action = Sequence::createWithTwoActions(DelayTime::create(t), _action);
    balloonNode->runAction(action);

Works like a charm.

Why version with RepeatForever doesn’t work?

It’s not a bug, it’s by design:

CCSequence means run action one by another, if you add a CCRepeatForever, than it will block other actions.

But shouldn’t it block actions after RepeatForever?

That’s a question of design/implementation and yes, it would be logical to only block following actions. I guess it was easier to implement it that way.

The implementation blocks all actions in the same sequence with a repeat forever action.
You would need to ask the person, who implemented the function to find out his/her intentions to design/implement it that way.
Maybe @slackmoehrle can help you out with that question.

Does this way work?

auto delay = DelayTime::create(0.25f);
    
auto goRight = MoveBy::create(2, Vec2(700, 0));
auto goLeft = MoveBy::create(2, Vec2(-300, 0));
auto putCenter = MoveTo::create(4, Vec2(_screenWidth/2, _screenHeight));
    
auto seq = Sequence::create(goRight, delay, goLeft, delay->clone(), goLeft->clone(), delay->clone(), goRight->clone(), delay->clone(), putCenter, nullptr);
    
_aliens.at(1)->runAction(RepeatForever::create(seq));

Yeah it should. Why not? Look at my first example.

@slackmoehrle I believe they want the delay to be a one off, not every loop of a sequence.

@piotrros I would recommend using the CallFunc action. Something like:

auto delayedFunction = [balloonNode]()
{
   auto moveUp = MoveBy::create(1.0f, Vec2(0, 60));
   auto moveDown = MoveBy::create(1.0f, Vec2(0, -60));
   auto seq = Sequence::create(moveUp, moveDown, NULL);
   balloonNode->runAction(RepeatForever::create(seq));
}
float t = rand_0_1();
auto delayedFuncSeq = Sequence::create(DelayTime::create(t), CallFunc::create(delayedFunction), NULL);
balloonNode->runAction(delayedFuncSeq);

Hope this helps

1 Like

Thanks, well there’re a lot of possibilities. But I find Repeat with -1 loops the easiest solution.