Cocos2d Cross-Platform Game Development Cookbook - Second Edition - Sample Chapter
Cocos2d Cross-Platform Game Development Cookbook - Second Edition - Sample Chapter
ee
The book starts by implementing sprites and animations. You will learn how to add scenes to a game, such
as the Gameplay Scene and the options scene, and create menus and buttons in these scenes as well
as creating transitions and program user interactions such as tapping, holding, and swiping. You'll then
add accelerometer inputs and physics to the scene and make objects respond to the input. You will also
learn how to add dynamic lighting to your game and use industry-wide tools, such as TexturePacker, Glyph
Designer, PhysicsEditor, Particle Designer, and Sprite Illuminator, to create more visually appealing and
performance-optimized games.
and problems
problems efficiently
real-world problems
$ 49.99 US
31.99 UK
P U B L I S H I N G
P U B L I S H I N G
Siddharth Shekar
Cocos2d is the world's leading game development framework for developing iOS games. With the introduction
of Swift and SpriteBuilder, it has become easier to develop the games of your dreams without effort.
Sa
pl
e
Siddharth Shekar
Preface
Since its inception in 2007, the Apple App Store is still going strong with an average of almost
500 apps added on a daily basis. Out of them, almost 80% of the apps are games. Part of
the reason for this is the amazing eco-system created by Apple to make the operating system
and IDE available free of charge, making it easy to access for the average developer. The
other part is Cocos2d, which is still one of the most widely-used free iOS game-development
frameworks that makes games and app development very convenient.
With SpriteBuilder integrating Cocos2d into it, this makes it even more awesome, as now
it is even easier to develop a simple prototype of a game without any code. Moreover, with
minimum effort the same app or game can be run on a varied number of resolutions.
Furthermore, we can now also port these games to Android without any need to rewrite the
code. Cross-platform iOS game development, which was a dream for so many years, has now
finally become a reality.
As Cocos2d itself has been there since the beginning of the first iOS device, the community
is strong and helpful. There are also great tools that have been developed by third-party
developers that make Cocos2d, an already awesome framework, even more awesome.
This book takes you through the recipes that are required to make any game. The chapters
are laid out in a logical manner so that by following each recipe you will get closer to finishing
and porting your game by the end of this book.
Hope to see your creations in the App Store soon.
Preface
Chapter 2, Scenes and Menus, will cover how to add scenes to the game, such as a gameplay
scene, how to create buttons and labels in the scene, and how to create transitions between
the scenes using various transition effects.
Chapter 3, Gestures, Touches, and the Accelerometer, will discuss various methods of user
interaction, such as tapping, holding, swiping along with adding accelerometer inputs and
gestures to the scene.
Chapter 4, Physics, will provide examples of how to add physics to the scene and make
objects respond to physics. This chapter will also look at different body types and body
properties, adding sprites to a body, applying force and impulse to a body, detecting collision
responses, and building objects, such as a vehicle, by adding physics bodies together.
Chapter 5, Audio, will show you how to edit audio tracks to create music and sound effects,
add the background music and audio effects to the game, add a pause and resume button to
the game, and add a volume slider to control the volume of audio to the options menu.
Chapter 6, AI and A* Pathfinding, will include ways to add Artificial Intelligence to enemies in
the game. This chapter will also look at creating patrolling, chasing, and projectile shooting
enemies. It will cover a pathfinding to create more advanced AI logic for enemies using grids.
Chapter 7, Data Storage and Retrieval, will teach you how to save and load game progress on
the device using NSUserDefault, create and access files using JSON, Plist, and XML files, for
custom storage and retrieval of data.
Chapter 8, Effects, teaches you to add dynamic lighting to your game, manipulate the position
and color of the light source dynamically using touch controls, and add 2D shadows to the
game created by the light source. You will learn to add effects to the game using the CCEffects
class of Cocos2d to create interesting effects in the game.
Chapter 9, Game Tools, provides insights to using industry standard tools, such as
TexturePacker, Glyph Designer, PhysicsEditor, Particle Designer, and Sprite Illuminator, to
create more visually appealing and performance-optimized games.
Chapter 10, Swift/SpriteBuilder Basics, shows you how to develop games in Apple's latest
programming language, Swift. We will see the differences between Objective-C and Swift
in this chapter. We will also see how to import Objective-C classes into Swift to reduce the
redundancy of code. This chapter will also provide insight into using SpriteBuilder to develop
more robust games.
Chapter 11, Porting to Android, will take a look at how to take your existing game developed
for iOS and port it to Android. We will learn how to install the Android Xcode plugin, prepare
the device for deployment, and finally run the project on an Android device.
Animating sprites
Drawing glPrimitives
Introduction
In the first chapter, we will cover some basics of the Cocos2d framework so that everyone is
up to speed on the concepts. We will go through the process of downloading and installing
SpriteBuilder/Cocos2d. Then we will cover the 2D coordinate system that Cocos2d uses.
Getting ready
To download and install Cocos2d, go to http://cocos2d.spritebuilder.com/
download.
SpriteBuilder is the official installer of Cocos2d now. To install, click on the Cocos2dSpriteBuilder installer link. This will open the Mac App Store Preview page.
If you would like to download an older version of Cocos2d, you can go through the links in the
archive section of the page and download it from there as well.
Chapter 1
Click on the View in Mac App Store link and then click on Launch Application when
prompted.
Once the App Store opens, click on Install to start the installation process. You will need to
sign in to an account to download the file.
Once the application starts, you will be asked to join the SpriteBuilder mailing list. Add your
e-mail address and click on Continue or select Sign Up Later.
We will go through how to create a small project using SpriteBuilder later in the book. For now,
we are ready to create a new project to work with. Navigate to File | New Project and select a
location to create the project folder.
You can also select the primary language for coding. As we will use Objective-C, make sure
that it is selected at the bottom.
Chapter 1
Once you have selected the location for the project, in the Save As box at the top, give the
project a name. Remember the name and the location of the project folder as we will need it
to open the project in Xcode.
Next, we need to open the project in Xcode. We will first understand how to code using Xcode
as it is essential to make more complex games. In later chapters, we will consider how to use
SpriteBuilder to simplify our game development process.
You can close the SpriteBuilder project as it is not required anymore.
How to do it
Perform the following steps:
1. Once you install Xcode, go the to the project folder in the directory you stored the
project in and double-click on projectname.xcodeproj. Here, I named the project
Sprite, so I will double-click on Sprite.xcodeproj:
Chapter 1
2. Once it is open, you should see the interface as follows:
How it works
Click on the play button in the upper-left corner to run the project.
This will run and show the default project running on the simulator. Congrats! You have
Cocos2d running successfully.
7
Chapter 1
Getting ready
As of now, both the MainScene.h and MainScene.m files have nothing in them. So, open
them up and add the following code in them.
How to do it
First, open up MainScene.h and add the following highlighted code:
@interface MainScene :CCNode{
CGSizewinSize;
}
+(CCScene*)scene;
@end
Then, navigate to the AppDelegate.m file, which is in the iOS group under Source/
Platforms, as shown in the following screenshot:
10
Chapter 1
If you build and run the project now, you will see nothing but a black screen. To make
sure that we are actually ready to draw something and that it will get displayed onscreen,
let's add some basic code to change the background color.
Add the following code to the init function of the MainScene.m file:
-(id)init{
if(self = [super init]){
winSize = [[CCDirectorsharedDirector]viewSize];
CGPoint center = CGPointMake(winSize.width/2,
winSize.height/2);
//Background
CCNode* backgroundColorNode = [CCNodeColor
nodeWithColor:[CCColor
colorWithRed:0.0f
green:1.0
blue:0.0]];
[selfaddChild:backgroundColorNode];
}
return self;
}
In the init function, after initializing the super init file, we will first get the screen size of
the current device. Then, we will have a helper CGPoint variable, which is used to calculate
the center of the screen.
Then, we will create a new CCNode and call it backgroundColorNode and call the
CCNodeColor class and the nodeWithColor function. In it, we will pass the red, green, and
blue values. As I wanted a green background, I have the value of green as 1 and the rest are 0.
Then, we will add backgroundColorNode to the scene.
11
How it works
Run the project to see the changes.
You will just see a green screen, which is the node that was just added to the scene. This can
be used if you want to have a plain background, and instead of importing an image into the
project, this is a quick way of having any colored background.
Getting ready
To add sprites to the scene, we will first import the background image in to our project.
12
Chapter 1
How to do it
Add the following code to the init function right below where we added
backgroundColorNode:
//Basic CCSprite - Background Image
CCSprite* backgroundImage = [CCSpritespriteWithImageNamed:@"Bg.png"];
backgroundImage.position = CGPointMake(winSize.width/2,
winSize.height/2);
[selfaddChild:backgroundImage];
Here, we will take the Bg image and add it as a child to the current scene. From the
Resources folder of the chapter, we will drag the Bg-ipad.png and Bg-ipadhd.png files
into the Resources/Published-iOS folder of the project.
We still have to make a small change in the CCBReader.m file. In the Search
inspector, search for the CCFileUtilsSearchMode text, and in place of
CCFileUtilsSearchModeDirectory, make the text CCFileUtilsSearchModeSuffix.
This will change the searchmode file from the folder to suffix mode.
13
How it works
If you build and run now, you will see an image similar to the following screenshot. This way,
we can display sprites on the scene.
Getting ready
To create the RenderTexture sprite, we will create a new function, and this function will
return a sprite when we provide the size and color of the sprite to be produced.
14
Chapter 1
How to do it
In the MainScene.h file, we will add the following highlighted line right under the scene
function we created earlier:
+(CCScene*)scene;
-(CCSprite *)spriteWithColor:(ccColor4F)bgColor
textureWidth:(float)textureWidth
textureHeight:(float)textureHeight;
@end
This function will return CCSprite and take in the color, width, and height that the sprite
should be of.
In the MainScene.m file, we will add the definition of the preceding function below the init
function, as follows:
-(CCSprite *)spriteWithColor:(ccColor4F)bgColor
textureWidth:(float)textureWidth
textureHeight:(float)textureHeight {
CCRenderTexture *rt =
[CCRenderTexture
renderTextureWithWidth:textureWidth
height:textureHeight];
[rtbeginWithClear:bgColor.r
g:bgColor.g
b:bgColor.b
a:bgColor.a];
[rt end];
return [CCSpritespriteWithTexture:rt.sprite.texture];
}
In the function, we will create a new variable called rt of the CCRenderTexture type, and to
it, we will pass the width and height that is passed to the function.
15
How it works
To use the RenderTexture function, we will add the following code right after where we
added the background to the scene:
//rtSprite
CCSprite* rtSprite = [self spriteWithColor:ccc4f(1.0, 1.0, 0.0, 1.0)
textureWidth:150textureHeight:150];
rtSprite.position = CGPointMake(winSize.width/2,
winSize.height/2);
[selfaddChild:rtSprite];
We will create a new variable called rtSprite of the CCSprite type and assign the sprite
that will be created by calling our function to it.
While calling the function, we will create a color of the ccc4f type and pass in the r, g, b, and
a values. For yellow, we will pass 1 for red and green. We will provide a width and height value
of 150 each.
Then, the sprite will be positioned at the center and added to the scene. Run the scene to see
the result.
16
Chapter 1
There's more
The color of the sprite can be changed by changing the rgba color value.
For example, here, I changed the value to (1.0, 0.0, 1.0, 1.0) for yellow, and you can see
the result as follows:
//rtSprite
CCSprite* rtSprite = [self spriteWithColor:ccc4f(1.0, 0.0, 1.0, 1.0)
textureWidth:150textureHeight:150];
rtSprite.position = CGPointMake(winSize.width/2, winSize.height/2);
[selfaddChild:rtSprite];
17
Getting ready
Let's take a look at how to create a custom sprite class so that it can have its own movement
and update the function later.
For this, we will have to create new files.
1. Go to File | New | File. Under iOS | Source, select Cocoa Touch Class. Click on
Next.
2. Next, we will give it a class name. We will select CCSprite as Subclass of and
ObjectiveC as Language. Click on Next.
18
Chapter 1
19
How to do it
Now that the files are created, let's make some changes to them so that it can take a string as
the filename and create the sprite from the file.
In the Hero.h file, we make the following changes:
#import "CCSprite.h"
@interface Hero :CCSprite{
CGSizewinSize;
}
-(id)initWithFilename:(NSString *) filename;
@end
How it works
To create an instance of the newly created custom sprite class, we will go to MainScene.h,
import the Hero.h file, and create a new instance of the Hero type called hero with the
following code:
#import "Hero.h"
@interface MainScene :CCNode{
20
Chapter 1
CGSizewinSize;
Hero* hero;
}
In the MainScene.m file, we will add the following code right after the place we added
rtSprite:
hero = [[Hero alloc]initWithFilename:@"hero.png"];
hero.position = CGPointMake(center.x - winSize.width/4,
winSize.height/2);
[selfaddChild:hero];
Here, we initialized hero with the hero.png file. In the Resources folder, we have to import
the hero-ipad.png and hero-ipadhd.png files into the project in a similar way to how we
added the Bg image files.
We will place hero at one-quarter the width of the screen, to the left of the center of the
screen, and place it at half the height of the screen. Lastly, we will add the hero object to
the scene.
21
Animating sprites
In this section, we will discuss how to animate a sprite. We will change our custom sprite class
to make the character animate. This can be done by providing Cocos2d with a number of
images and asking it to cycle through these images to create the animation.
Getting ready
To animate the sprites, we will add four frames of animation that we will apply to the hero
sprite class and cycle through the images using the repeatForever action. In the next
section, we will cover the actions in detail.
How to do it
In the Resources folder for this chapter, there will be normal, ipad, and ipadhd versions
of the frames for hero. We will import all the files into the project.
22
Chapter 1
In the Hero.m file, we will change the initWithFilename function, as follows:
-(id)initWithFilename:(NSString *)filename
{
if (self = [super initWithImageNamed:filename]) {
First, we will create a new variable called animFramesArray of the NSMutableArray type.
We will then create a for loop starting from index 1 and going to 4, as there are four images.
We will save the frames in the array by passing in the names of the four images that we would
like to loop through.
Next, we create a variable called animation of the CCAnimation type and pass it in the
four frames; also add the delay with which the animation should be played with.
23
How it works
Now, you should be able to see the character blinking. The speed with which the animation is
played is controlled by the delay in the CCAnimation class.
We will see that without making any changes to the instance in MainScene, the custom sprite
animates the character.
24
Chapter 1
Getting started
Let's first take a look at a simple action in which we will move the hero along the x axis by half
the width of the screen, and move it down by one-quarter the height of the screen from the
center in the y direction.
How to do it
After we have added the hero to MainScene, we will add the following code:
CGPointfinalPos = CGPointMake(center.x + winSize.width/4, center.y winSize.height/4);
CCActionFiniteTime* actionMove = [CCActionMoveToactionWithDuration
:1.0position:finalPos];
[herorunAction:actionMove];
For convenience, I created a CGPoint called finalPos and stored the final position in it.
Then, I created a variable called actionMove of the CCFiniteAction type, called the
CCMoveTo function, gave it a duration of 1.0 seconds, and specified the position that I
wanted to move the hero to. Finally, I called the runAction function on hero and passed
in the action.
25
How it works
When you run the project, the hero will be to the left of the yellow render sprite and will slowly
start moving towards the lower-right corner if the render sprite is over a period of 1 second.
After 1 second, when the destination location is reached, the action will stop, and the hero will
be stationary again.
There's more
Let's next create a more elaborate action and add a whole bunch of actions in a sequence
and play them one after the other. Therefore, we will remove the previous code and add the
following code instead:
//Actions
CGPointinitPos = hero.position;
CGPointfinalPos = CGPointMake(center.x + winSize.width/4, center.y winSize.height/4);
CCActionFiniteTime* actionMove = [CCActionMoveToactionWithDuration:
1.0position:finalPos];
CCAction *rotateBy = [CCActionRotateByactionWithDuration:2.0 angle:
180];
26
Chapter 1
CCAction *tintTo= [CCActionTintToactionWithDuration:1.0
color:[CCColorcolorWithRed:0.0fgreen:1.0blue:0.0]];
CCAction *delay = [CCActionDelayactionWithDuration:1.0];
CCAction *moveToInit = [CCActionMoveToactionWithDuration:
1.0position:initPos];
CCAction *rotateBack = [CCActionRotateByactionWithDuration:2.0 angle:
180];
CCAction *tintBlue= [CCActionTintToactionWithDuration:1.0
color:[CCColorcolorWithRed:0.0fgreen:0.0blue:1.0]];
CCAction *sequence = [CCActionSequenceactions:actionMove,
rotateBy,tintTo, moveToInit, delay, rotateBack, tintBlue, nil];
[herorunAction:sequence];
Here, as I stored the final position in a variable, I will also store the initial position in a
CGPoint variable called initPos, which we will use later.
The first action is the same moveTo action with which we will move the player.
Next, we will use the rotateBy action; here, we will give the duration and angle in degrees by
which the object should be rotated.
After this, we will use the tintTo action, which will change the color of the object. Once
again, we will give it the duration and color to which we want to the object to change. Here, we
will change the color to green.
We will then call the delay action, which is used to perform an action after a delay. We will
create a delay of 1 second.
Then, we will move the object back to its initial position, change the object color to blue, and
rotate the object again by another 180 degrees.
We will create the CCSequence action and pass in all the actions in the order we want them
to be played; at the end, we will add nil to say that is the end of the list.
At the end, we will call run the sequence action on hero.
Now, the hero will start at the initial position, but when he gets back, he will be blue in color.
27
Drawing glPrimitives
Cocos2d uses openGLES, which is a graphics library that enables objects to be displayed
onscreen. In fact, all the drawing that we have done until now uses this library. Cocos2d also
gives you basic access to glPrimitives, which can be used to create basic shapes, such as
circles, squares, rectangles, and so on.
Getting ready
Let's take a look at a few of the examples now. We will begin by creating a simple circle.
28
Chapter 1
How to do it
Right after adding the hero node, we will add the following code:
//drawDotNode
CCDrawNode* dotNode = [CCDrawNode node];
CCColor* red = [CCColorcolorWithRed:1.0fgreen:0.0fblue:0.0f];
[dotNodedrawDot:CGPointMake(winSize.width/2, winSize.height/2) radius:
10.0fcolor:red];
[selfaddChild:dotNode];
glPrimitives are created using the CCDrawNode class. Here, we will create a new instance of
CCDrawNode and call it DotNode. We will create a new CCColor variable called red and
assign the RGBA value of red.
We will then call the drawDot function on CCDrawNode and pass in the location where we
would like to create the circle. We will also pass in the radius and color. In the end, we will add
dotNode to the scene.
How it works
When you run the project, you will see a red dot at the center of the screen.
Here, as we provided the center of the circle and radius, Cocos2d creates the circle and paints
the area inside this region with the color that you specified.
The circle is one example; there are other shapes that can also be created this way.
29
There's more
Next, we will take a look at how to create polygons of any shape with the drawWithPolyVert
function of the CCDrawNode class. Add the following code and replace or comment the
DrawDot node:
// DrawSquareNode
CCDrawNode *squareNode = [CCDrawNode node];
CGPointsquareVerts[4] =
{
CGPointMake(center.x - 50, center.y - 50),
CGPointMake(center.x - 50, center.y + 50),
CGPointMake(center.x + 50, center.y + 50),
CGPointMake(center.x + 50, center.y - 50)
};
CCColor* green = [CCColorcolorWithRed:0.0fgreen:1.0fblue:0.0f];
[squareNodedrawPolyWithVerts:squareVerts
count:4
fillColor:red
borderWidth:1
borderColor:green];
[selfaddChild:squareNode];
We will create a new node of the CCDrawNode type. Next, we will create an array of CGPoint
by calling in squareVerts, which will take in the location of the vertices of the square. We will
then create a new CCColor called green and assign it a green color using the RGBA value.
Then, we will call drawPolyLineWithVerts, pass in the vertices array, give the number
of vertices to draw, pass in the fill color as red, and assign a border width of 1. In the end,
we will pass in the border color as green, which we specified earlier.
30
Chapter 1
Then, we will add squareNode to the scene.
We can simply run the project to see the final result.
We can also make a triangle with the same code. Instead of drawing four nodes, if we just ask
the function to draw three nodes, a triangle will be drawn instead of a square.
We can change the code as follows, in which we will change the count to 3 instead of 4. There
is no need to change the verts array:
CCColor* green = [CCColorcolorWithRed:0.0fgreen:1.0fblue:0.0f];
[squareNodedrawPolyWithVerts:squareVerts
count: 3
fillColor:red
borderWidth:1
borderColor:green];
[selfaddChild:squareNode];
31
Using the CCDrawNode class, we can also create line segments between two points.
For this, we will add the following code right after adding the polyline code:
//segment node
CCColor* blue = [CCColorcolorWithRed:0.0fgreen:0.0fblue:1.0f];
CCDrawNode* segmentNode = [CCDrawNode node];
[segmentNodedrawSegmentFrom:center
to:CGPointMake(center.x + 40, center.y + 40)
radius: 2.0
color: blue];
[selfaddChild:segmentNode];
32
Chapter 1
We will define a new CCColor called blue so that we can color the line blue. Next, we will
create a new CCDrawNode class and call it segmentNode.
On segmentNode, we will call the drawSegment function and provide the center of the
screen as the start point and the second point is 40 units in the x direction and 40 units in
the y direction from the center. We will then pass in the radius, which is the thickness of the
line, and the color blue.
The node is then added to the scene.
Note that in the following screenshot, I changed the polyline to draw a square instead of a
triangle:
33
Getting ready
Recall the movies of yesteryear in which the hero or subject remains stationary and acts as if
they are galloping on a horse, and the background is looped to give the illusion that the hero
is actually moving forward in the scene.
34
Chapter 1
We will implement a very simple parallax effect in which all the objects in the background,
such as the trees, bushes, and grass, move at the same speed. So, we will just take the
background image and make it move in a loop.
The parallax effect will be achieved thus: instead of a single sprite of the background image,
we will use two sprites and place them adjacent to each other horizontally at the start of the
game, as seen in the first preceding image. The first sprite will be visible, but the second
sprite will be offscreen and won't be visible to the player initially.
When the game starts, both the sprites will be moved with a certain speed in the negative x
directionthat is toward the left of the screen. Both the sprites will move at the same speed.
So, once the game starts, sprite 1 will slowly go offscreen bit by bit, and the second sprite will
start to get visible.
Once the first sprite goes completely offscreen, it is quickly moved to the end of the second
sprite, which is at the same position that the second sprite was at the start of the game.
Thus, the process continues in a loop. Both the sprites always move toward the left of the
screen. After each sprite goes off screen on the left-hand side, it is placed off screen on the
right-hand side of the screen, and it continues to move left.
There are a couple of things that need to be kept in mind while creating assets for parallax
scrolling and coding a parallax effect. The first is that when creating assets for a parallax
effect, the art needs to be continuous. This means, for example, if you look at the second
image in the preceding section, you will see that the mountains look like a continuous
mountain range. Even though Sprite1 and Sprite2 are two different images, when put
together, they appear as one single image. This can again be seen in the light green bush
below the mountain. The left-hand part of the bush is in Sprite1, and the right-hand part is
in Sprite2, yet when the two sprites are kept adjacent to each other, they give a seamless
illusion of being part of a single bush.
The second aspect to keep in mind is image gap. Even if you make the images seamless and
make the sprites move at the same speed, sometimes you might encounter gaps between the
sprites. This is not a very common problem, but in some frameworks, this problem might exist.
So, to counter this, you can either stretch the images just by a bit so that the sprites overlap
each other and it is not very obvious to the player. The other method is to make sure that
you manually place the sprites at the end of the onscreen sprite and also make necessary
adjustments if required to bridge the gap between the sprites.
This is the main theory behind parallax scrolling. Let's take a look at it in practice in code in
the next section.
35
How to do it
In a similar way to how we created the Hero class, we will create a file of the
CocosTouchClass type and name it ParallaxSprite.
Open the ParallaxSprite.h file and add the following code:
#import "CCSprite.h"
@interface ParallaxSprite :CCSprite{
CGSize _winSize;
CGPoint _center;
CCSprite *_sprite1, *_sprite2;
float _speed;
}
We will create a few variables that we will use later, such as _winSize and _center,
which will get the size of the screen resolution of the device that the game is running on and
calculate the center of the screen.
We will create two sprite variables to hold the two images which will be cycled during the
parallax effect.
We will also add a _speed variable. This is the speed with which we will move and loop the
images.
In a similar way to the Hero class, we will create an initWithFilename function that will
initiate the class with the filename provided. Additionally, we will also take a float, which will
be the speed of the sprite.
We will also need an update function that will be called 60 times in a second and will update
the position of the two sprites in the class.
This is all for the ParallaxSprite.h file. We will now move on to the ParallaxSprite.m
file.
36
Chapter 1
In the file, we will add the following code:
#import "ParallaxSprite.h"
@implementation ParallaxSprite
-(id)initWithFilename:(NSString *)filename Speed:(float)speed;{
if(self = [super init]){
NSLog(@"[parallaxSprite] (init) ");
_winSize = [[CCDirectorsharedDirector]viewSize];
_center = CGPointMake(_winSize.width/2, _winSize.height/2);
_speed = speed;
_sprite1 = [CCSpritespriteWithImageNamed:filename];
_sprite1.position = _center;
[selfaddChild:_sprite1];
_sprite2 = [CCSpritespriteWithImageNamed:filename];
_sprite2.position = CGPointMake(_sprite1.position.x + _winSize.
width
, _center.y);
[selfaddChild:_sprite2];
}
return self;
}
We will first add the initWithFilename function. In this, we will initialize the super class
and get _winSize.
Next, we will calculate the center of the screen by dividing the width and height by two.
The speed value is assigned to the _speed variable classes.
We will then create the _sprite1 and _sprite2 variables. In spriteWithImageNames,
we will pass the filename variable that will hold the string of the filename.
Note that _sprite1 is placed at the center of the screen, and _sprite2 is placed off screen
by the width of the screen, but at the same height as _sprite1.
37
@end
Here, we will calculate the new positions of the individual sprites in the x axis by getting the
current x position of the sprites and then subtracting the speed. We will subtract because we
want the sprites to move in the negative x direction in each update call.
In the next step, we will assign the x position calculated on both the sprites. We will use the
same y position as the value does not change in the y direction.
Next, we will check whether the right-hand edge of the image is visible to the player any more
and has gone beyond the left-hand side of the screen. If this is the case, we will place the
sprite at the offscreen position, the width of the screen from the center of the other sprite, so
that there are no gaps between the sprites.
We will use an "if else" statement here as only one sprite will go beyond the bounds on the
left-hand side of the screen.
38
Chapter 1
How it works
Let's take a look at how to implement this class now. In the MainScene.h class, we will
import the ParallaxSprite.h file and create a new variable called pSprite of the
ParallaxSprite type, as follows:
#import "Hero.h"
#import "ParallaxSprite.h"
@interface MainScene :CCNode{
CGSizewinSize;
Hero* hero;
ParallaxSprite* pSprite;
}
Next, in the MainScene.m file, we will remove the code that was used to add the background
sprite at the start of the chapter and replace it with the following code:
//Basic CCSprite - Background Image - REMOVE
//CCSprite* backgroundImage = [CCSpritespriteWithImageNamed:@"Bg.
png"];
//backgroundImage.position = CGPointMake(winSize.width/2,
winSize.height/2);
//[self addChild:backgroundImage];
//Parallax Background Sprite - ADD
pSprite = [[ParallaxSpritealloc]initWithFilename:@"Bg.png" Speed:5];
[selfaddChild:pSprite];
Here, we will assign the same Bg.png file as we did earlier; however, additionally, we will also
provide a speed value of 5.
Note that we will not call the update function of the ParallaxSprite class as it is called
automatically every frame. Further, you also don't have to schedule it as you did previously
because the function is initialized automatically at the start.
39
40
www.PacktPub.com
Stay Connected: