Make multiple sprites run sequence after each other>? Read more to understand better

Make multiple sprites run sequence after each other>? Read more to understand better
0.0 0

#1

Hi again!
Let’s say i have 10 sprites with an image of a pig. They are all added to the scene and they are all stored in a vector.
How can i make the first run an action and then when that action is done, the next sprite should run an action and when that’s done. no. 3 should run an action…
So that it happens when the previous action is done and not just at the same time…?

Thanks!


#2

You want to use Actions and Sequences, please see this: http://cocos2d-x.org/programmersguide/4/


#3

Thanks but i still dont get it. How to check if another sprite/object has finished its own action or sequence, I mean you can only a sequence for each object right and that’s the only way I know kinda schedule what move comes first and what’s after. But i don’t know how make Another Sprite run an action after the first Sprite has finished its action…
You get me?


#4

I get you.

Totally untested or really thought about in depth.


auto someNode = Node::create();

auto mySprite1 = Sprite::create("mysprite.png");
auto mySprite2 = Sprite::create("mysprite.png");
auto mySprite3 = Sprite::create("mysprite.png");
auto mySprite4 = Sprite::create("mysprite.png");
auto mySprite5 = Sprite::create("mysprite.png");
auto mySprite6 = Sprite::create("mysprite.png");
auto mySprite7 = Sprite::create("mysprite.png");
auto mySprite8 = Sprite::create("mysprite.png");
auto mySprite9 = Sprite::create("mysprite.png");
auto mySprite10 = Sprite::create("mysprite.png");

auto mySprite1Move = CallFunc::create([](){
    log("move mySprite1");
    mySprite1->runAction(whatever you are doing);
});

auto mySprite2Move = CallFunc::create([](){
    log("move mySprite2");
    mySprite2->runAction(whatever you are doing);
});

// etc 

auto seq = Sequence::create(mySprite1Move, mySprite2Move, nullptr);

someNode->runAction(seq);

#5

Thank you so much!
But is this a good way to run actions or?


#6

Theoretically that is pretty much the way to do so. But if you want the sprite to perform the actions after the previous sprite finishes its action(s), then you need to tweak the solution. Example:

auto spriteMove = MoveTo::create(1.f, Vec2(x,y));
auto spriteScale = ScaleTo::create(1.f, 0.5f);
auto afterAction = CallFunc::create(....); //the closure or function you call after it finishes the above actions.
auto seq = Sequence::create(spriteMove, spriteScale, afterAction, nullptr);

Not saying that @slackmoehrle’s solution is wrong, but the method will result in the sprites performing their actions almost at the same time, since CallFunc is only called once and does not run for a certain interval.

Edited: Fixed a typo. (CallFunc was misspelled as CreateFunc just now :-p)


#7

Thanks, so do you say that it would be better to use createFunc instead of callFunc?


#8

My bad, should be CallFunc… a typo.


#9

Thanks for tweaking.


#10

Then i don’t really get what you think could have done better than slacks idea, sry

I appreciate your time!


#11

@nichlaspro132, @duracellrabbid solutions is better in the sense that the actions wont run almost immediately.

Another possible idea, although untested:

auto someNode = Node::create();

// NOTE: I would create these in a for loop and stuff in a vector.....
auto mySprite1 = Sprite::create("mysprite.png");
auto mySprite2 = Sprite::create("mysprite.png");
auto mySprite3 = Sprite::create("mysprite.png");
auto mySprite4 = Sprite::create("mysprite.png");
auto mySprite5 = Sprite::create("mysprite.png");
auto mySprite6 = Sprite::create("mysprite.png");
auto mySprite7 = Sprite::create("mysprite.png");
auto mySprite8 = Sprite::create("mysprite.png");
auto mySprite9 = Sprite::create("mysprite.png");
auto mySprite10 = Sprite::create("mysprite.png");

auto delay = DelayTime::create(0.25f);

auto mySprite1Move = CallFunc::create([](){
    log("move mySprite1");
    mySprite1->runAction(whatever you are doing);
});

auto mySprite2Move = CallFunc::create([](){
    log("move mySprite2");
    mySprite2->runAction(whatever you are doing);
});

// etc 

auto seq = Sequence::create(mySprite1Move, delay, mySprite2Move, delay->clone(), etc, etc, nullptr);

someNode->runAction(seq);

#12

I Got it, thank you guys!


#13

Hey,
check out this solution:

auto mySprite1 = Sprite::create("mysprite.png");
auto mySprite2 = Sprite::create("mysprite.png");
auto mySprite3 = Sprite::create("mysprite.png");

auto action = <the action you want to be performed by each sprite>
auto action1 = TargetedAction::create(mySprite1, action);
auto action2 = TargetedAction::create(mySprite2, action->clone());
auto action3 = TargetedAction::create(mySprite3, action->clone());

this->runAction(Sequence::create(action1, action2, action3, nullptr));

(You can do that also inside a for loop.)


#14

I know this is from some time ago but i wanted to create my own action because i should fadeOut three objects at the same time and then i wanted to make a sequence with a delay of 0.5f and then the custom action, so i run this code(took an image so you can see the error too):


How would you do something like add an object to the scene after an action has been completed?

Thanks!!!


#15

change []() { ... } to [&]() { ... }


#16

Correct. You need the & in order to access the ‘this’ variable.

There is also a Spawn action that groups many actions together.
So you can use a Spawn action combined with TargetedAction to group the three FadeOut actions.
Then you can use this spawn action inside your sequence.


#17

auto scaleTo = ScaleTo::create(0.75f, 1.0f);
auto move_ease_in_out = EaseElasticOut::create(scaleTo);
auto logoWTargetedAction = TargetedAction::create(logoW, Sequence::create(DelayTime::create(2.0f), move_ease_in_out->clone(), AudioEngine::play2d(“res/sound/tap2.ogg”), nullptr));

logoW->runAction(logoWTargetedAction);

I have a curious case here: The sound is preloaded and it is supposed to be played after 2 or some seconds according to the sequence. But it is played right after scene is loaded.
Anyone has an idea why?


#18

Hey
You are calling AudioEngine::play2d(…) inside the sequence. This is not an action but a function so it is called immediately. You need an CallFunc action to wrap the play2d function.