cocos2d tutorial: Using CCSequence and CCActions

cocos2d

A while back we did some cocos2d for iPhone tutorials on creating a simple menu and creating a button using CCMenuItemToggle. This time, we'll take a look at cocos2d's powerful CCSequence, and how you can use it in combination with CCActions and your own methods.

A very common series of events you'll do in any game is:

  • Add a sprite to your scene
  • Move it to a certain location
  • Do some other actions
  • Release the sprite when you're finished with it

Luckily, cocos2d for iPhone makes doing this very easy, so let's get started!

Note: If you don't have cocos2d installed, you'll want to take a look here first: cocos2d for iPhone

Create your project

First, create a new cocos2d application and call it MoveIt.

We'll need a sprite to perform these actions on, so let's use this one (made in about 45 seconds with the great and free web-based pixel art tool piq):

Save this file to your computer and to your project's Resources group (be sure to copy it to your destination's group folder.)

Add the sprite to your scene

At this point you'd want to create your own GameLayer or GameScene class, but for the purpose of this tutorial we'll just modify the existing HelloWorldLayer included in the cocos2d template. First we'll want to remove the stuff in the init method we don't need. Select the HelloWorldLayer.m file and delete everything in your init method EXCEPT the CGSize variable, so it looks like this:

  1. // on "init" you need to initialize your instance
  2. -(id) init
  3. {
  4. // always call "super" init
  5. // Apple recommends to re-assign "self" with the "super" return value
  6. if( (self=[super init])) {
  7.  
  8. // ask director the the window size
  9. CGSize size = [[CCDirector sharedDirector] winSize];
  10. }
  11. return self;
  12. }

Now, let's add our sprite to the scene:

  1. // on "init" you need to initialize your instance
  2. -(id) init
  3. {
  4. // always call "super" init
  5. // Apple recommends to re-assign "self" with the "super" return value
  6. if( (self=[super init])) {
  7.  
  8. // ask director the the window size
  9. CGSize size = [[CCDirector sharedDirector] winSize];
  10.  
  11. // add our sprite to the scene
  12. CCSprite *mySprite = [CCSprite spriteWithFile:@"sprite.png"];
  13. mySprite.position = ccp(size.width/4, size.height/2);
  14. [self addChild:mySprite];
  15.  
  16. }
  17. return self;
  18. }

Build and run your project, and if all is well, it should look something like this:

If you run into any errors, check your syntax or if you're really stuck, let me know in the comments.

I LIKE TO MOVE IT MOVE IT

This is great and all, but kinda boring. To get this sprite moving, we're going to run a sequence (CCSequence) of actions (CCActions) on this bad boy. First, let's move it a bit. After adding your sprite to the scene, add the following code:

  1. id moveAction = [CCMoveBy actionWithDuration:2 position:ccp(size.width/2,0)];
  2.  
  3. [mySprite runAction:
  4. [CCSequence actions:
  5. moveAction,
  6. nil]];

First, we're creating our move action which will run for 2 seconds, and move the sprite by the distance we specify.

Then, we're running a CCSequence with this action on our sprite.

Build and run again, and your sprite should move to the right side of the screen.

A sequence with only one action?

The point of using a CCSequence is to run a series of actions - if you're only performing one action on your sprite, it's not necessary. So let's create some more actions and add them to our sequence!

  1. id moveAction = [CCMoveBy actionWithDuration:2 position:ccp(size.width/2,0)];
  2. id rotateAction = [CCRotateBy actionWithDuration:2 angle:180];
  3. id tintAction = [CCTintTo actionWithDuration:1 red:255 green:0 blue:0];
  4.  
  5. [mySprite runAction:
  6. [CCSequence actions:
  7. moveAction, rotateAction, tintAction,
  8. nil]];

Build and run again. Now the sprite should move to the right and then rotate by 180 degrees. And since our sprite is embarrassed about being upside down, the tintAction turns it red.

What about me?

So actions are great, but what if during a sequence you want to call some of your own methods or do something else? Luckily cocos2d has CCCallFunc for just this purpose. Let's create a method of our own in the HelloWorldLayer class that turns the screen blue. Underneath your init method, add the following:

  1. -(void) setBgColor
  2. {
  3. //Turn the background blue!
  4. CCLayerColor *layer = [CCLayerColor layerWithColor:ccc4(0,0,255,255)];
  5. [self addChild:layer z:-1];
  6. }

This method just adds a blue CCLayerColor to the scene, to make the background blue. Now let's call this method from our CCSequence:

  1. id moveAction = [CCMoveBy actionWithDuration:2 position:ccp(size.width/2,0)];
  2. id rotateAction = [CCRotateBy actionWithDuration:2 angle:180];
  3. id tintAction = [CCTintTo actionWithDuration:1 red:255 green:0 blue:0];
  4. id myCallFunc = [CCCallFunc actionWithTarget:self selector:@selector(setBgColor)]; // to call our method
  5.  
  6. [mySprite runAction:
  7. [CCSequence actions:
  8. moveAction, rotateAction, tintAction, myCallFunc,
  9. nil]];

Bye bye sprite!

A very common task you'll want to do is remove a sprite from your scene at the end of a sequence. For example, if the sprite were an enemy that moved offscreen and is no longer needed, you'd want to remove it. To illustrate this, we'll remove our sprite from the end of the sequence, but keep it onscreen so you can see that it's really removed! Let's add two more actions: a delay so that after the screen turns blue, nothing happens for one second, and the action to remove our sprite from the scene:

  1. id moveAction = [CCMoveBy actionWithDuration:2 position:ccp(size.width/2,0)];
  2. id rotateAction = [CCRotateBy actionWithDuration:2 angle:180];
  3. id tintAction = [CCTintTo actionWithDuration:1 red:255 green:0 blue:0];
  4. id myCallFunc = [CCCallFunc actionWithTarget:self selector:@selector(setBgColor)];
  5. id delayTimeAction = [CCDelayTime actionWithDuration:1];
  6. id removeMySprite = [CCCallFuncND actionWithTarget:mySprite
  7. selector:@selector(removeFromParentAndCleanup:)
  8. data:(void*)NO];
  9.  
  10. [mySprite runAction:
  11. [CCSequence actions:
  12. moveAction, rotateAction, tintAction, myCallFunc, delayTimeAction, removeMySprite,
  13. nil]];

The delayTimeAction is pretty self explanatory, but note the removeMySprite. We're using a CCCallFuncND (which lets us specify arguments) to call cocos2d's removeFromParentAndCleanup: method. An important thing to note is that the target we're specifying is our mySprite - if we used self here, EVERYTHING would get removed from the layer!

Build and run again, and you should see our sprite:

  • move to the right
  • turn on its head
  • turn red
  • call a method we created which turns the background blue
  • pause for one second
  • removes itself from the scene

As you can see, cocos2d actions are powerful, simple, and can be a lot of fun to use! If you'd like to see examples of other actions or things to put in a CCSequences, let us know in the comments. Also keep an eye out for our upcoming cocos2d game, Flockwork. ;)

And in case you got lost along the way, you can download the Xcode project here: MoveIt

4 Comments

  1. Arden Stewart | December 30th, 2012

    When i first run cocos2d I get the Hello World in the portrait mode on the simulator. I don’t see a root controller just an app delegate .h and .m and the
    HelloWorldLayer .h and .m In the AppDelegate .m the return UIInterfaceOrientationIsLandscape is used
    but even if I go and change the orientation in the target properties the simulator becomes a landscape but the Hello World is still in portrait and any code is in portrait? What to do?
    thank you , Arden

  2. WorldRecords.com | January 12th, 2013

    I like that you put 5 or more actions in one sequence! Makes a good template. I’ve already added CCFadeOut. Thanks for the easy reminder on how it’s done.

  3. Rene E | February 15th, 2013

    What if want to put two move actions (first move to the right side of the screen then move to the left side)

  4. pankaj | July 4th, 2013

    my sprite is moving along x-Axis in one direction and
    moving out of the window but i don’t want that i want like it
    should move forward and backward along x-axis at any point of
    time… so tell me how to do that…

Post a Comment