Cocos2d Tips: Scrolling, Parallax and wider levels

Wider Levels & Scrolling

When you create a game in Cocos2d, your screen measures 960 pixels wide on iPhone4+ and 2048 on iPad. If we want him to move farther to the right then we need to make the level bigger.  Normally we set:

levelSize = screenSize;

But now we basically wish to make:

levelSize = CGSizeMake(screenSize.width * 2.0f, screenSize.height); // levelSize code

What we are doing is changing our scene levelSize to 2x the screenSize.

Our level is now twice as big and we have a GameScene, which contains a GameplayLayer & a BackgroundLayer with some background image.  We want to add a layer that will scroll in the opposite direction as our player moves.  To do this we will need to add a method a method called adjustLayer:

-(void)adjustLayer {

Player *player = (Player*)[sceneSpriteBatchNode getChildByTag:kPlayerSpriteTagValue];

float playerXPosition = player.position.x;

CGSize screenSize = [[CCDirector sharedDirector] winSize];

float halfOfTheScreen = screenSize.width/2.0f;

CGSize levelSize = [[GameManager sharedGameManager] getDimensionsOfCurrentScene];//1

if ((playerXPosition > halfOfTheScreen) && (playerXPosition < (levelSize.width – halfOfTheScreen))) {

// then scroll background

float newXPosition = halfOfTheScreen – playerXPosition;

[self setPosition:ccp(newXPosition,self.position.y)];      // 2 self is the game layer

}

}

Here comment //1 is a call to a method which returns the desired levelSize.  Or you can simply hard code it in this case by replacing this line with the //levelSize code line from above.  Remember we are running this method in the GameplayLayer, which is self in this code.  This needs to be called constantly so you must add this line to your update layer.  What we are doing here is keeping the screen centered on the player.  Now in the update method add this code:

//1. Get the list of objects on the layer & loop through them

CCArray *listOfGameObjects = [sceneSpriteBatchNode children];

for (GameCharacter *tempChar in listOfGameObjects) {

[tempChar updateStateWithDeltaTime:dt andListOfGameObjects:listOfGameObjects];

}

//2. Call the adjustLayer method

[self adjustLayer];

Perfect!  Now let’s add the image that is actually going to scroll.  Add this method to your GameplayLayer.m:

-(void)addScrollingBackground {

CGSize screenSize = [[CCDirector sharedDirector] winSize];

CGSize levelSize = [[GameManager sharedGameManager] getDimensionsOfCurrentScene];

CCSprite *scrollingBackground;

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

// Indicates game is running on iPad

scrollingBackground = [CCSprite spriteWithFile:@”mars_landscape2x.png”];

} else {

scrollingBackground = [CCSprite spriteWithFile:@”mars_landscape2x.png”];

}

[scrollingBackground setPosition:ccp(levelSize.width/2.0f,screenSize.height/2.0f)];

[self addChild:scrollingBackground z:1];

}

In order for this to appear, we need to call it from the init method by adding this line:

[self addScrollingBackground];

Let’s review.  addScrollingBackground adds a new image to the GameplayLayer.  (This image is positioned over the true background, which is in the BackgroundLayer.)  Therefore, the new image you add here should be a sort of rocky ground floor that will slide sideways as the player moves.

Make sure the image is twice as big as the screen so there will be enough of it to scroll through as the player moves.

Now Build & Run and watch your ground scroll differently as your background as your player moves left or right.

Parallax

Parallax makes one layer scroll faster or slower than the other.  It’s quite easy to achieve this effect.  First add a new instance variable to your GameplayLayer.m file like so:

@implementation GameplayLayer {

CCParallaxNode *parallaxNode;

}

NOTE: We are extending the @implementation line to include an ivar.  No need to declare it in the @interface file.  Remember .h files (header files) only need to include what properties or methods you want your object to expose to other calling objects.

And now replace your addScrollingBackground method with this one:

// Scrolling 3 Parallax backgrounds

-(void)addScrollingBackgroundWithParallax {

CGSize screenSize = [[CCDirector sharedDirector] winSize];

CGSize levelSize = [[GameManager sharedGameManager]

getDimensionsOfCurrentScene];

CCSprite *BGLayer1;

CCSprite *BGLayer2;

CCSprite *BGLayer3;

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

// Indicates game is running on iPad

BGLayer1 = [CCSprite spriteWithFile:@”mars_landscape2x.png”];

BGLayer2 = [CCSprite spriteWithFile:@”some_rocks.png”];

BGLayer3 = [CCSprite spriteWithFile:@”some_pillars.png”];

} else {

BGLayer1 = [CCSprite spriteWithFile:@” mars_landscape2x.png”];

BGLayer2 = [CCSprite spriteWithFile:@” some_rocks.png”];

BGLayer3 = [CCSprite spriteWithFile:@” some_pillars.png”];

}

parallaxNode = [CCParallaxNode node];

[parallaxNode setPosition:ccp(levelSize.width/2.0f,screenSize.height/2.0f)];

float xOffset = 0;

// Ground moves at ratio 1,1

[parallaxNode addChild:BGLayer1 z:40 parallaxRatio:ccp(1.0f,1.0f) positionOffset:ccp(0.0f,0.0f)];

xOffset = (levelSize.width/2) * 0.3f;

[parallaxNode addChild:BGLayer2 z:20 parallaxRatio:ccp(0.2f,1.0f) positionOffset:ccp(xOffset, 0)];

xOffset = (levelSize.width/2) * 0.8f;

[parallaxNode addChild:BGLayer3 z:30 parallaxRatio:ccp(0.7f,1.0f) positionOffset:ccp(xOffset, 0)];

[self addChild:parallaxNode z:10];

}

Don’t forget to change the GameplayLayer’s init method call to:

[self addScrollingBackgroundWithParallax];

What we are doing now is adding more layers and offsetting their center positions.  Thus when they move, they will move at different rates.  Build & run the app.

You can use scrolling to add clouds or stars or alien birds to make some eyecandy for your users.  If you choose to scroll many objects on the screen though, you might want to look into reusing them.  This is a very popular technique used to improve performance of a game.  You create one instance of the object at a time and add it to an array for tracking.  When that instance moves offscreen, you remove it from that array.  This saves you a lot of memory.

How Cocos2d taught me iOS and OOP

How Cocos2d taught me iOS
How Cocos2d taught me iOS

I started studying iOS in 2009, started studying Cocos2d in 2011.  I never understood how to do things in code for iOS.   It was all a big mystery to me.

What do you mean create a button programmatically and add it to the subview and position it and change its attributes?  I can just drag one from the Object Library onto the canvas and put it wherever I want and change its color etc…

After a year of using Cocos2d, I know cherish its teachings as I find myself trying to make an app which requires objects such as UIPageControl and UIScrollView and UIImageViews with UIImages.  In doing this you run into the situation of:

How do I position a view, or rather a bunch of UIImageViews that are not on the canvas but will be when the UIPageControl’s value changes!?

EPIPHANY!

Cool Image Transparency Gradient Effect

So the other day I was trying to figure out how to do something in Pixelmator (Im pretty sure it works for Photoshop) and I accidentally stumbled into this effect.

First, I opened up an image that I wanted to spruce up.

Second, I Added a Layer Mask in the Layer Menu

Then, I used a Transparent to Black Gradient and got this:

Gradient Transparency
Gradient Transparency

 

Why is this cool?  Well, now you can add a nice background color or even another image in the background to make some very professional looking artwork! 🙂

 

Transparency Gradient
Transparency Gradient

 

The original idea I was after was from a tutorial I found online which took a picture, such as this one.  You take a picture such as this:

beyonce_smile_face_lips_hair_5905_1920x1080

 

Add a Layer Mask as before but this time choose Brush 100 with a black foreground color.  Eliminate everything around her by painting with the brush to get this:

Screen Shot 2013-03-02 at 11.40.03 AM

Cute huh!

Now create a new layer and Add a Gradient, preferrably one with 2 pastel colors and move it over this one:

Finally change Blending to Screen and voila!

Screen Shot 2013-03-02 at 11.42.23 AM