Tuesday, May 15, 2012

Video Tutorial: Scrollable layer with Parallax (LevelHelper + Cocos2d-X)

A nice game level selection mechanism, particularly for "world" selection, is a scrollable layer that snaps to specific points. Also, I want to mix this with a parallax effect.

I've created a video tutorial that shows how to create this effect using LevelHelper, SpriteHelper and Cocos2d-x. Don't mind the sucky minimalistic "art" :)

It's my first video tutorial ever, so keep your expectations moderated :P

The process, as described in the video is:
  • Create a Cocos2d-x project
  • Create a Project in LevelHelper
  • Use SpriteHelper to create the sprites
  • Create the parallax layer in LevelHelper, using the new sprites
  • Place the billboard sprites in LevelHelper, assigning them a special tag
  • Export the Cocos2d-X code (would also work the same with Cocos2D)
  • In XCode, handle both the touchmove and touchend events
  • On touchmove move the parallax on a ratio of 1:1 with the gesture
  • On touchend try to find the nearest snapping point, and trigger an animation to move the parallax to that point.

The source-code used in the tutorial is:

inside the private section
LevelHelperLoader* loader;
LHParallaxNode* myParallax;

loader = new LevelHelperLoader("ScrollableParalax.plhs");
myParallax = loader->paralaxNodeWithUniqueName("Parallax_1");

CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++) 
    touch = (CCTouch*)(*it);


    CCPoint location = touch->locationInView();
    location = CCDirector::sharedDirector()->convertToGL(location);
    CCPoint prevLocation = touch->previousLocationInView();
    prevLocation = CCDirector::sharedDirector()->convertToGL(prevLocation);

    CCPoint touchDelta = ccpSub(location,prevLocation);

    if(NULL != myParallax)
        CCPoint parallaxPosition = myParallax->getPosition();
        myParallax->setPosition(ccp(parallaxPosition.x + touchDelta.x, parallaxPosition.y + touchDelta.y));

//find nearest selector

CCArray* sprTag = loader->spritesWithTag(SELECTOR);    

if(sprTag->count() == 0)

float minOffset = MAXFLOAT;

for(int i =0; i< sprTag->count(); ++i)
    LHSprite* curSprite = (LHSprite*)sprTag->objectAtIndex(i);
    float spritePosition = curSprite->getPositionX();
    CCSize screenSize = CCDirector::sharedDirector()->getWinSize();

    float centerPosition = screenSize.width/2 - 
        curSprite->getRealScale().width / 2;
    float offset = centerPosition - spritePosition;

    if(abs(offset) < abs(minOffset))
        minOffset = offset;

CCPoint parallaxPosition = myParallax->getPosition();

//if less than a threshold snap directly without any animation

if(abs(minOffset) < 50)
        ccp(parallaxPosition.x + minOffset, parallaxPosition.y));
        CCMoveBy::actionWithDuration(0.3f, ccp(minOffset, 0)));

delete myParallax;
myParallax = NULL;


  1. Hey Pedro,

    Thanks for the post and the video! It's making me seriously consider learning cocos2d and levelhelper. I'm still not sure if it's overkill for my app though. I was wondering if I could get your opinion on whether or not it's a good move for me considering the performance issues I'm getting in my Core Animation parallax effect right now. I recorded a 90 second video of it here - http://youtu.be/ZN2pSk8N3lc

    I'd appreciate any insight you have! Thanks!

  2. I really love the art-style you got there, great stuff man. Regarding performance (and mostly everything else) it's, IMHO, a great move to learn Cocos2D. Cocos2D uses OpenGL ES do handle the drawing, which is much faster than Core Animation.

    Also, it handles most of the fuss, and creating a parallax effect is incredibly easy, even without LevelHelper. My suggestion, go to http://www.raywenderlich.com and check the Cocos2D tutorials. You won't regret it.

  3. I'm looking his stuff up now. Thanks Pedro!

  4. LevelHelper does not support Cocos2dx version 3 now unfortunately