Programmers Guide
User Manual:
Open the PDF directly: View PDF .
Page Count: 140
Cocos2d-x Programmers Guide v3.12
v2016.08.08
Authors: SlackMoehrle, Ricardo, Justin, Nite, Kai, Minggo, Wenhai, Tony, Yingtao, Rao,
Huabin, Zhe
CSS enhancements: Nico
Contributors/Editors: stevetranby, Maxxx, smitpatel88, IQD, Michael, Meir_yanovich,
catch_up, kidproquo, EMebane, reyanthonyrenacia, Fradow, pabitrapadhy, Manny_Dev,
ZippoLag, kubas121, bjared, grimfate, DarioDP
Special Thanks: To our users! Without you there is no reason to even write this guide.
PDF Version
eBook Version
Please provide feedback for this guide on GitHub
You can download the samples for this guide on GitHub
What is Cocos2d-x?
About Cocos2d-x
Started in 2010, Cocos2d-x is an open source, cross-platform game engine. It is loaded with
powerful features that allows developers to create spectacular games with ease.
Why choose Cocos2d-x
Why would you want to choose Cocos2d-x over other available game engines?
• Modern C++ API (please refer to the modernizing done in version 3.0)
• Cross-platform - desktop and mobile
• Capability to test and debug your game on the desktop and then push it to a mobile or
desktop target
• A vast API of functionality including sprites, actions, animations, particles, transitions,
timers, events (touch, keyboard, accelerometer, mouse), sound, file IO, persistence,
skeletal animations, 3D
1
Where to get Cocos2d-x and what do I get?
You can clone the GitHub Repo and follow the steps in the README. You can also download
as part of the Cocos package on our download page. No matter if you choose to develop in
C++, JavaScript or Lua, everything you need is in one package. The Cocos family of products
has a few different pieces.
• Cocos2d-x - this is the game engine, itself. It includes the engine and the cocos
command-line tool. You can download a production release or stay bleeding edge by
cloning our GitHub Repo.
• Cocos Creator - is a unified game development tool. You can create your entire game,
from start to finish, using this tool. It uses JavaScript. Lua and C++ support are being
added. Read more about Cocos Creator.
• Cocos Launcher - is a graphical tool to create and manage your projects. This is also
an easy way to add SDKBOX plugins to your project. Documentaion is available.
• Coco Studio - is EOL’d and has been replaced by Cocos Creator. Documentation is
still available.
• Code IDE - is EOL’d. Common text editors and IDE’s can be used instead.
Conventions used in this book
•
•
•
•
auto is used for creating local variables.
using namespace cocos2d; is used to shorten types.
each chapter has a compilable source code sample to demonstrate concepts.
class names, methods names and other API components are rendered using fixed fonts.
eg: Sprite
• italics are used to notate concepts and keywords
Learning Resources
•
•
•
•
•
This very guide! You can also get it as a PDF and ePub
Sonar Systems Videos
Android Fundamentals
Make School Tutorials
Game From Scratch
Spreading the word!
You can help us spread the word about Cocos2d-x! We would surely appreciate it!
• Talk about us on Facebook! Our Facebook Page
• Tweet, Tweet! Our Twitter
• Read our Blog and promote it on your social media.
2
• Become a Regional Coordinator
Where to get help
•
•
•
•
Forums
Bug Tracker
IRC. We are in Freenode in the #cocos2d channel
cpp-tests project. This project is our basis for testing. Use this project to learn
how we implement the functionality of the engine. This project is located in Cocos2dx_root/build.
• API Reference.
Basic Cocos2d-x Concepts
This chapter assumes you’ve just gotten started with Cocos2d-x, and are ready to start working
on the game of your dreams. Don’t worry, it will be fun!
Let’s get started!
Cocos2d-x is a cross-platform game engine. A game engine is a piece of software that provides
common functionality that all games need. You might have heard this referred to as an API or
framework but in this guide, we’ll be calling it a ‘game engine’.
Game engines include many components that when used together will help speed up development time, and often perform better than homemade engines. A game engine is usually
comprised of some or all of the following components: a renderer, 2d/3d graphics, collision
detection, a physics engine, sound, controller support, animations and more. Game engines
usually support multiple platforms thus making it easy to develop your game and then deploy it
to multiple platforms without much overhead at all.
Since Cocos2d-x is a game engine, it provides a simplified API for developing cross-platform
mobile and desktop games. By encapsulating the power inside an easy to use API, you can
focus on developing your games and worry less about the implementation of the technical underpinnings. Cocos2d-x will take care of as much or as little of the heavy lifting as you want.
Cocos2d-x provides Scene, Transition, Sprite, Menu, Sprite3D, Audio objects and
much more. Everything you need to create your games are included.
Main Components
It might seem overwhelming at first, but getting started with Cocos2d-x is simple. Before we
dive into depth we must understand some of the concepts Cocos2d-x utilizes. At the heart of
Cocos2d-x are Scene, Node, Sprite, Menu and Action objects. Look at any of your favorite
games, and you will see all of these components in one form or another!
Let’s have a look. This might look a bit similar to a very popular game you might have played:
3
Let’s take another look, but splitting up the screenshot and identifying the components used to
build it:
4
You can see a menu, some sprites and labels, which all have an equivalent in Cocos2d-x. Take
a look at a few of your own game design documents,and see what components you have, you’ll
probably have a few that match up.
Director
Cocos2d-x uses the concept of a Director, just like in a movie! The Director controls
the flow of operations and tells the necessary recipient what to do. Think of yourself as the
Executive Producer and you tell the Director what to do! One common Director task is to
control Scene replacements and transitions. The Director is a shared singleton (effectively,
there’s only one instance of the class at a time) object that you can call from anywhere in your
code.
Here is an example of a typical game flow. The Director takes care of transitioning through
this as your game criteria decides:
5
You are the director of your game. You decide what happens, when and how. Take charge!
Scene
In your game you probably want a main menu, a few levels and an ending scene. How do you
organize all of these into the separate pieces they are? You guessed it, Scene. When you think
about your favorite movie you can see that it’s distinctly broken down into scenes, or separate
parts of the story line. If we apply this same thought process to games, we should come up with
at least a few scenes no matter how simple the game is.
Taking another look at the familiar image from earlier:
This is a main menu and it is a single Scene. This scene is made up of several pieces that
all fit together to give us the end result. Scenes are drawn by the renderer. The renderer is
responsible for rendering sprites and other objects into the screen. To better understand this
we need to talk a bit about the scene graph.
Scene Graph
A scene graph is a data structure that arranges a graphical scene. A scene graph contains
Node objects in a tree (yes, it is called scene graph, but it is actually represented by a tree)
structure.
6
It sounds and looks complicated. I’m sure you are asking why should you care about this
technical detail if Cocos2d-x does the heavy lifting for you? It really is important to understand
how Scenes are drawn by the renderer.
Once you start adding nodes, sprites and animations to your game, you want to make sure you
are drawing the things you expect. But what if you are not? What if your sprites are hidden in
the background and you want them to be the foremost objects? No big deal, just take a step
back and run through the scene graph on a piece of paper, and I bet you find your mistake
easily.
Since the Scene Graph is a tree; you can walk the tree. Cocos2d-x uses the in-order walk
algorithm. An in-order walk is the left side of the tree being walked, then the root node, then
the right side of the tree. Since the right side of the tree is rendered last, it is displayed first on
the scene graph.
7
The scene graph is easily demonstrated, let’s take a look at our game scene broken down:
8
Would be rendered as a tree, simplified to the following:
Another point to think about is elements with a negative z-order are on the left side of the tree,
while elements with a positive z-order are on the right side. Keep this in consideration when
ordering your elements! Of course, you can add elements in any order, and they’re automatically
sorted based upon a customizable z-order.
9
Building on this concept, we can think of a Scene as a collection of Node objects. Let’s break
the scene above down to see the scene graph uses the z-order to layout the Scene:
10
11
The Scene on the left is actually made up of multiple Node objects that are given a different
z-order to make them “stack” on top of each other.
In Cocos2d-x, you build the scene graph using the addChild() API call:
// Adds a child with the z-order of -2, that means
// it goes to the "left" side of the tree (because it is negative)
scene->addChild(title_node, -2);
// When you don't specify the z-order, it will use 0
scene->addChild(label_node);
// Adds a child with the z-order of 1, that means
// it goes to the "right" side of the tree (because it is positive)
scene->addChild(sprite_node, 1);
// Adds a child with the z-order of -2, that means
// it goes to the "left" side of the tree (because it is negative)
scene.addChild(title_node, -2);
// When you don't specify the z-order, it will use 0
scene.addChild(label_node);
// Adds a child with the z-order of 1, that means
// it goes to the "right" side of the tree (because it is positive)
scene.addChild(sprite_node, 1);
Sprites
All games have Sprite objects, and you may or may not realize what they are. Sprites are
the objects that you move around the screen. You can manipulate them. The main character in
your game is probably a Sprite. I know what you might be thinking - isn’t every graphical object
a Sprite? No! Why? Well a Sprite is only a Sprite if you move it around. If you don’t move it
around it is just a Node.
Taking another look at the image from above, let’s point out what are Sprites and what are
Nodes:
12
Sprites are important in all games. Writing a platformer, you probably have a main character
that is made by using an image of some sort. This is a Sprite.
Sprites are easy to create and they have configurable properties like: position, rotation,
scale, opacity, color and more.
// This is how to create a sprite
auto mySprite = Sprite::create("mysprite.png");
// this is how to change the properties of the sprite
mySprite->setPosition(Vec2(500, 0));
mySprite->setRotation(40);
mySprite->setScale(2.0); // sets both the scale of the X and Y axis uniformly
mySprite->setAnchorPoint(Vec2(0, 0));
// This is how to create a sprite
var mySprite = new cc.Sprite(res.mySprite_png);
// this is how to change the properties of the sprite
mySprite.setPosition(cc._p(500, 0));
13
mySprite.setRotation(40);
mySprite.setScale(2.0); // sets both the scale of the X and Y axis uniformly
mySprite.setAnchorPoint(cc._p(0, 0));
Let’s illustrate each property, consider the following screenshot from the example code for this
chapter:
If we set the position using mySprite->setPosition(Vec2(500, 0));:
14
Note that the Sprite position has changed from its original position to the new position that
we specified.
If we now set a new rotation, using mySprite->setRotation(40);:
15
… you can see that the Sprite has been rotated to the new amount that was specified.
If we now specify a new scale using mySprite->setScale(2.0);:
16
Again, we can see that the Sprite now has changed according to our code changes.
Lastly, all Node objects (since a Sprite is a subclass of Node) have a value for anchor point.
We haven’t talked about this yet, so now is a good time. You can think of anchor point as a
way of specifying what part of the sprite will be used as a base coordinate when setting the
position of it.
Using the character from our example game, and setting the anchor point to 0, 0 using:
mySprite->setAnchorPoint(Vec2(0, 0));
mySprite.setAnchorPoint(cc._p(0, 0));
would result in the lower left corner of our sprite being used as the basis for any setPosition()
call. Let’s see a few of these in action:
17
Take a look at the red dot in each picture. This red dot illustrates where the anchor point is!
As you can see anchor point is very useful when positioning Nodes. You can even adjust the
anchor point dynamically to simulate effects in your game.
We really can tweak just about every aspect of the Sprite. But, what if we wanted to have
these same types of changes occur in an automated, time determined manner? Well, keep
reading…
Actions
Creating a Scene and adding Sprite objects on the screen is only part of what we need to do.
For a game to be a game we need to make things move around! Action objects are an integral
part of every game. Actions allow the transformation of Node objects in time space. Want to
move a Sprite from one Point to another and use a callback when complete? No problem!
You can even create a Sequence of Action items to be performed on a Node. You can change
18
Node properties like position, rotation and scale. Example Actions: MoveBy, Rotate, Scale.
All games use Actions.
Taking a look at the sample code for this chapter, here are Actions in work:
and after 5 seconds the sprite will move to a new position:
19
Action objects are easy to create:
auto mySprite = Sprite::create("Blue_Front1.png");
// Move a sprite 50 pixels to the right, and 10 pixels to the top over 2 seconds.
auto moveBy = MoveBy::create(2, Vec2(50,10));
mySprite->runAction(moveBy);
// Move a sprite to a specific location over 2 seconds.
auto moveTo = MoveTo::create(2, Vec2(50,10));
mySprite->runAction(moveTo);
var mySprite = new cc.Sprite(res.mySprite_png);
// Move a sprite 50 pixels to the right, and 10 pixels to the top over 2 seconds.
var moveBy = new cc.MoveBy(2, cc._p(50,10));
mySprite.runAction(moveBy);
// Move a sprite to a specific location over 2 seconds.
var moveTo = new cc.MoveTo(2, cc._p(50,10));
mySprite.runAction(moveTo);
20
Sequences and Spawns
With moving Sprite objects on the screen we have everything we need to create our game,
right? Not quite. What about running multiple Actions? Yes, Cocos2d-x handles this too in a
few different ways.
Just like it sounds, a Sequence is multiple Action objects run in a specified order. Need to
run the Sequence in reverse? No problem, Cocos2d-x handles this with no additional work.
Take a look at the flow of an example Sequence for moving a Sprite gradually:
This Sequence is easy to make:
auto mySprite = Node::create();
// move to point 50,10 over 2 seconds
auto moveTo1 = MoveTo::create(2, Vec2(50,10));
// move from current position by 100,10 over 2 seconds
auto moveBy1 = MoveBy::create(2, Vec2(100,10));
// move to point 150,10 over 2 seconds
auto moveTo2 = MoveTo::create(2, Vec2(150,10));
// create a delay
auto delay = DelayTime::create(1);
mySprite->runAction(Sequence::create(moveTo1, delay, moveBy1, delay.clone(),
moveTo2, nullptr));
var mySprite = new cc.Node();
// move to point 50,10 over 2 seconds
var moveTo1 = new cc.MoveTo(2, cc._p(50,10));
// move from current position by 100,10 over 2 seconds
var moveBy1 = new cc.MoveBy(2, cc._p(100,10));
// move to point 150,10 over 2 seconds
var moveTo2 = new cc.MoveTo(2, cc._p(150,10));
// create a delay
var delay = new cc.DelayTime(1);
21
mySprite.runAction(Sequence.create(moveTo1, delay, moveBy1, delay.clone(),
moveTo2));
This example runs a Sequence, in order, but what about running all the specified Actions at
the same time? Cocos2d-x supports this too and it is called Spawn. Spawn will take all the
specified Action objects and executes them at the same time. Some might be longer than
others, so they won’t all finish at the same time if this is the case.
auto myNode = Node::create();
auto moveTo1 = MoveTo::create(2, Vec2(50,10));
auto moveBy1 = MoveBy::create(2, Vec2(100,10));
auto moveTo2 = MoveTo::create(2, Vec2(150,10));
myNode->runAction(Spawn::create(moveTo1, moveBy1, moveTo2, nullptr));
var myNode = new cc.Node();
var moveTo1 = new cc.MoveTo(2, cc._p(50,10));
var moveBy1 = new cc.MoveBy(2, cc._p(100,10));
var moveTo2 = new cc.MoveTo(2, cc._p(150,10));
myNode.runAction(Spawn.create(moveTo1, moveBy1, moveTo2));
Why Spawn actions? Is there ever a reason? Sure! What if your main character has multiple
Actions when obtaining a power up? Maybe beating the boss at the end of a level has multiple
Actions that need to happen to end the level.
Parent Child Relationship
Cocos2d-x uses a parent and child relationship. This means that properties and changes to
the parent node are applied to its children. Consider a single Sprite and then a Sprite that
has children:
22
With children, changing the rotation of the parent will also change the rotation to all children:
23
auto myNode = Node::create();
// rotating by setting
myNode->setRotation(50);
var myNode = new cc.Node();
// rotating by setting
myNode.setRotation(50);
Just like with rotation, if you change the scale of the parent the children will also get scaled:
24
auto myNode = Node::create();
// scaling by setting
myNode->setScale(2.0); // scales uniformly by 2.0
var myNode = new cc.Node();
// scaling by setting
myNode.setScale(2.0); // scales uniformly by 2.0
Not all changes to the parent are passed down to its children. Changing the parent anchor
point only affects transform operations (scale, position, rotate, skew, etc…) and does not affect
children positioning. In fact, children will be always added to the bottom-left (0,0) corner of its
parent.
Logging as a way to output messages
Sometimes, when your app is running, you might wish to see messages being written to the
console for informational or debug purposes. This is built into the engine, using log(). Example:
// a simple string
log("This would be outputted to the console");
25
// a string and a variable
string s = "My variable";
log("string is %s", s);
// a double and a variable
double dd = 42;
log("double is %f", dd);
// an integer and a variable
int i = 6;
log("integer is %d", i);
// a float and a variable
float f = 2.0f;
log("float is %f", f);
// a bool and a variable
bool b = true;
if (b == true)
log("bool is true");
else
log("bool is false");
And, as expected, if you prefer you can use std::cout in place of log(), however, log() might
offer easier formatting of complex output.
// a simple string
cc.log("This would be outputted to the console");
// outputting more than a simple string
var pos = cc._p(sender.x, sender.y);
cc.log("Position x: " + pos.x + ' y:' + pos.y);
Conclusion
We have gone through a lot of Cocos2d-x concepts. Take a deep breath. Don’t worry. Just dive
in with your ideas and take it one step at a time. Cocos2d-x and programming in general are
not skills that are learned overnight. These take practice and understanding. Remember that
the forums are also there to help you with questions.
26
Sprites
What are Sprites
A Sprite is a 2D image that can be animated or transformed by changing its properties, including
rotation, position, scale, color, etc.
Creating Sprites
There are different ways to create Sprites depending upon what you need to accomplish. You
can create a Sprite from an image with various graphic formats including: PNG, JPEG, TIFF,
and others. Let’s go through some create methods and talk about each one.
Creating a Sprite
A Sprite can be created by specifying an image file to use.
auto mySprite = Sprite::create("mysprite.png");
var mySprite = new cc.Sprite(res.mySprite_png);
The statement above creates a Sprite using the mysprite.png image. The result is that the
created Sprite uses the whole image. Sprite has the same dimensions of mysprite.png.
If the image file is 200 x 200 the resulting Sprite is 200 x 200.
Creating a Sprite with a Rect
In the previous example, the created Sprite has the same size as the original image file. If you
want to create a Sprite with only a certain portion of the image file, you can do it by specifying
a Rect.
Rect has 4 values: origin x, origin y, width and height.
auto mySprite = Sprite::create("mysprite.png", Rect(0,0,40,40));
var mySprite = new cc.Sprite(res.mySprite_png, cc.rect(0,0,40,40));
27
Rect starts at the top left corner. This is the opposite of what you might be used to when laying
out screen position as it starts from the lower left corner. Thus the resulting Sprite is only a
portion of the image file. In this case the Sprite dimension is 40 x 40 starting at the top left
corner.
If you don’t specify a Rect, Cocos2d-x will automatically use the full width and height of the
image file you specify. Take a look at the example below. If we use an image with dimensions
200 x 200 the following 2 statements would have the same result.
auto mySprite = Sprite::create("mysprite.png");
auto mySprite = Sprite::create("mysprite.png", Rect(0,0,200,200));
var mySprite = new cc.Sprite(res.mySprite_png);
var mySprite = new cc.Sprite(res.mySprite_png, cc.rect(0,0,200,200));
Creating a Sprite from a Sprite Sheet
A sprite sheet is a way to combine sprites into a single file. Using a sprite sheet helps achieve
better performance by batching the draw calls. They can also save disk and video memory in
cases where the sprites can be packed on a sheet more efficiently (generally requires special
tools). You will read more about this in the Advanced Chapter, but it is but it is one of many
standard methods in the industry for increasing game performance.
When using a sprite sheet it is first loaded, in its entirety, into the SpriteFrameCache.
SpriteFrameCache is a caching class that retains the SpriteFrame objects added
to it, for future quicker access. The SpriteFrame is loaded once and retained in the
SpriteFrameCache
Here is an example sprite sheet:
28
It doesn’t look like much but let’s take a closer look at what is happening:
As you can see the sprite sheet, at a minimum it reduces unneeded space and consolidates
all sprites into a single file.
Let’s tie this all together!
Loading a Sprite Sheet
Load your sprite sheet into the SpriteFrameCache, probably in AppDelegate:
// load the Sprite Sheet
auto spritecache = SpriteFrameCache::getInstance();
// the .plist file can be generated with any of the tools mentioned below
spritecache->addSpriteFramesWithFile("sprites.plist");
// load the Sprite Sheet
var spritecache = cc.SpriteFrameCache;
// the .plist file can be generated with any of the tools mentioned below
spritecache.addSpriteFramesWithFile(res.sprites_plist);
Now that we have a sprite sheet loaded into SpriteFrameCache we can create Sprite
objects by utilizing it.
Creating a Sprite from SpriteFrameCache
This creates a Sprite by pulling it from the SpriteFrameCache.
// Our .plist file has names for each of the sprites in it. We'll grab
// the sprite named, "mysprite" from the sprite sheet:
auto mysprite = Sprite::createWithSpriteFrameName("mysprite.png");
29
// Our .plist file has names for each of the sprites in it. We'll grab
// the sprite named, "Blue_Front1" from the sprite sheet:
var mysprite = cc.Sprite.createWithSpriteFrameName(res.mySprite_png);
Creating a Sprite from a SpriteFrame
Another way to create the same Sprite is by fetching the SpriteFrame from the SpriteFrameCache, and then creating the Sprite with the SpriteFrame. Example:
// this is equivalent to the previous example,
// but it is created by retrieving the SpriteFrame from the cache.
auto newspriteFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Blue_Front1.png");
auto newSprite = Sprite::createWithSpriteFrame(newspriteFrame);
// this is equivalent to the previous example,
// but it is created by retrieving the SpriteFrame from the cache.
var newspriteFrame = cc.SpriteFrameCache.getSpriteFrameByName(res.sprites_plist);
var newSprite = cc.Sprite.createWithSpriteFrame(newspriteFrame);
Tools for creating Sprite Sheets
Creating a sprite sheet manually is a tedious process. Fortunately there are tools that can
generate them automatically. These tools can provide even more ways to adjust your sprite
sheet for maximum optimization!
Here are a few tools:
• Cocos Studio
• ShoeBox
• Texture Packer
30
• Zwoptex
Sprite Manipulation
After creating a Sprite you will have access to a variety of properties it has that can be manipulated.
Given:
auto mySprite = Sprite::create("mysprite.png");
var mySprite = new Sprite(res.mysprite_png);
Anchor Point and Position
Anchor Point is a point that you set as a way to specify what part of the Sprite will be used
when setting its position. Anchor Point affects only properties that can be transformed. This
includes scale, rotation, skew. This excludes color and opacity. The anchor point uses a
bottom left coordinate system. This means that when specifying X and Y coordinate values you
need to make sure to start at the bottom left hand corner to do your calculations. By default, all
Node objects have a default anchor point of is (0.5, 0.5).
Setting the anchor point is easy:
// DEFAULT anchor point for all Sprites
mySprite->setAnchorPoint(0.5, 0.5);
// bottom left
mySprite->setAnchorPoint(0, 0);
// top left
mySprite->setAnchorPoint(0, 1);
// bottom right
mySprite->setAnchorPoint(1, 0);
31
// top right
mySprite->setAnchorPoint(1, 1);
// DEFAULT anchor point for all Sprites
mySprite.setAnchorPoint(cc._p(0.5, 0.5));
// bottom left
mySprite.setAnchorPoint(cc._p(0, 0));
// top left
mySprite.setAnchorPoint(cc._p(0, 1));
// bottom right
mySprite.setAnchorPoint(cc._p(1, 0));
// top right
mySprite.setAnchorPoint(cc._p(1, 1));
To represent this visually:
Sprite properties effected by anchor point
Using anchor point effects only properties that can be transformed. This includes scale, rotation, skew.
Position
A sprite’s position is affected by its anchor point as it is this point that is used as a starting point
for positioning. Let’s visually look at how this happens. Notice the colored line and where the
sprite’s position is in relation to it. Notice, as we change the anchor point values, the sprite’s
position changes. It is important to note that all it took was changing the anchor point value.
We did not use a setPosition() statement to achieve this:
32
There are more ways to set position than just anchor point. Sprite objects can also be set
using the setPosition() method.
// position a sprite to a specific position of x = 100, y = 200.
mySprite->setPosition(Vec2(100, 200));
mySprite.setPosition(cc._p(100, 200));
Rotation
Changes the sprite’s rotation, by a positive or negative number of degrees. A positive value
rotates the Sprite object clockwise, while a negative value rotates the Sprite object counterclockwise. The default value is 0.
// rotate sprite by +20 degrees
mySprite->setRotation(20.0f);
// rotate sprite by -20 degrees
mySprite->setRotation(-20.0f);
// rotate sprite by +60 degrees
mySprite->setRotation(60.0f);
// rotate sprite by -60 degrees
mySprite->setRotation(-60.0f);
// rotate sprite by +20 degrees
mySprite.setRotation(cc._p(20.0));
// rotate sprite by -20 degrees
mySprite.setRotation(cc._p(-20.0));
// rotate sprite by +60 degrees
mySprite.setRotation(cc._p(60.0));
// rotate sprite by -60 degrees
mySprite.setRotation(cc._p(-60.0));
33
Scale
Changes the sprite’s scale, either by x, y or uniformly for both x and y. The default value is 1.0
for both x and y.
// increases X and Y size by 2.0 uniformly
mySprite->setScale(2.0);
// increases just X scale by 2.0
mySprite->setScaleX(2.0);
// increases just Y scale by 2.0
mySprite->setScaleY(2.0);
// increases X and Y size by 2.0 uniformly
mySprite.setScale(cc._p(2.0));
// increases just X scale by 2.0
mySprite.setScaleX(cc._p(2.0));
// increases just Y scale by 2.0
mySprite.setScaleY(cc._p(2.0));
Skew
Changes the sprite’s skew, either by x, y or uniformly for both x and y. The default value is 0,0
for both x and y.
// adjusts the X skew by 20.0
mySprite->setSkewX(20.0f);
// adjusts the Y skew by 20.0
mySprite->setSkewY(20.0f);
34
// adjusts the X skew by 20.0
mySprite.setSkewX(cc._p(20.0));
// adjusts the Y skew by 20.0
mySprite.setSkewY(cc._p(20.0));
Sprite properties not affected by anchor point
There are a few properties of Sprite objects that are not affected by anchor point. Why?
Because they only change superficial qualities like color and opacity.
Color
Changes the sprite’s color. This is done by passing in a Color3B object. Color3B objects are
RGB values. We haven’t encountered Color3B yet but it is simply an object that defines an
RGB color. An RGB color is a 3 byte value from 0 - 255. Cocos2d-x also provides pre-defined
colors that you can pick from. Using these will be a bit faster since they are pre-defined. A few
examples: Color3B::White and Color3B::Red.
// set the color by passing in a pre-defined Color3B object.
mySprite->setColor(Color3B::WHITE);
// Set the color by passing in a Color3B object.
mySprite->setColor(Color3B(255, 255, 255)); // Same as Color3B::WHITE
// set the color by passing in a pre-defined Color3B object.
mySprite.setColor(cc.color.WHITE);
// Set the color by passing in a Color3B object.
mySprite.setColor(cc.color(255, 255, 255)); // Same as Color3B::WHITE
35
Opacity
Changes the sprite’s opacity by the specified value. An opaque object is not transparent at
all. This property expects a value from 0 to 255, where 255 means fully opaque and 0 means
fully transparent. Think: zero opacity means invisible, and you’ll always understand how this
works. The default value is 255 (fully opaque).
// Set the opacity to 30, which makes this sprite 11.7% opaque.
// (30 divided by 256 equals 0.1171875...)
mySprite->setOpacity(30);
// Set the opacity to 30, which makes this sprite 11.7% opaque.
// (30 divided by 256 equals 0.1171875...)
mySprite.setOpacity(30);
Polygon Sprite
A Polygon Sprite is also a Sprite, that is used to display a 2d image. However, unlike a
normal Sprite object, which is a rectangle made of just 2 triangles, PolygonSprite objects
are made of a series of triangles.
Why use a Polygon Sprite?
Simple, performance!
There is a lot of technical jargon that we can toss around here about pixel fill rate but the take
home lesson is that a PolygonSprite draws based upon the shape of your Sprite, not a
simple rectangle around the largest width and height. This saves a lot of unnecessary drawing.
Consider this example:
36
Notice the difference between the left and right versions?
On the left, a typical Sprite drawn in rectangular fashion by the use of 2 triangles.
On the right, a PolygonSprite drawn with many smaller triangles.
Whether or not this trade-off is worth it for purely performance reasons depends on a number
of factors (sprite shape/detail, size, quantity drawn on screen, etc.), but in general, vertices are
cheaper than pixels on modern GPUs.
AutoPolygon
AutoPolygon is a helper class. It’s purpose is to process an image into a 2d polygon mesh at
runtime.
There are functions for each step in the process, from tracing all the points, to triangulation. The
result, can be then passed to a Sprite objects create function to create a PolygonSprite.
Example:
// Generate polygon info automatically.
auto pinfo = AutoPolygon::generatePolygon("filename.png");
// Create a sprite with polygon info.
auto sprite = Sprite::create(pinfo);
// Generate polygon info automatically.
var pinfo = cc.autopolygon.generatePolygon(res.mysprite_png);
// Create a sprite with polygon info.
var sprite = new cc.Sprite(pinfo);
Actions
Action objects are just like they sound. They make a Node perform a change to its properties.
Action objects allow the transformation of Node properties in time. Any object with a base
37
class of Node can have Action objects performed on it. As an example, you can move a
Sprite from one position to another and do it over a span of time.
Example of MoveTo and MoveBy action:
// Move sprite to position 50,10 in 2 seconds.
auto moveTo = MoveTo::create(2, Vec2(50, 10));
mySprite1->runAction(moveTo);
// Move sprite 20 points to right in 2 seconds
auto moveBy = MoveBy::create(2, Vec2(20,0));
mySprite2->runAction(moveBy);
// Move sprite to position 50,10 in 2 seconds.
var moveTo = new cc.MoveTo(2, cc._p(50, 10));
mySprite1.runAction(moveTo);
// Move sprite 20 points to right in 2 seconds
var moveBy = new cc.MoveBy(2, cc._p(20,0));
mySprite2.runAction(moveBy);
By and To, what is the difference?
You will notice that each Action has a By and To version. Why? Because they are different in
what they accomplish. A By is relative to the current state of the Node. A To action is absolute,
meaning it doesn’t take into account the current state of the Node. Let’s take a look at a specific
example:
auto mySprite = Sprite::create("mysprite.png");
mySprite->setPosition(Vec2(200, 256));
// MoveBy - lets move the sprite by 500 on the x axis over 2 seconds
// MoveBy is relative - since x = 200 + 200 move = x is now 400 after the move
auto moveBy = MoveBy::create(2, Vec2(500, mySprite->getPositionY()));
// MoveTo - lets move the new sprite to 300 x 256 over 2 seconds
// MoveTo is absolute - The sprite gets moved to 300 x 256 regardless of
// where it is located now.
auto moveTo = MoveTo::create(2, Vec2(300, mySprite->getPositionY()));
// Delay - create a small delay
auto delay = DelayTime::create(1);
auto seq = Sequence::create(moveBy, delay, moveTo, nullptr);
mySprite->runAction(seq);
38
var mySprite = new cc.Sprite(res.mysprite_png);
mySprite.setPosition(cc._p(200, 256));
// MoveBy - lets move the sprite by 500 on the x axis over 2 seconds
// MoveBy is relative - since x = 200 + 200 move = x is now 400 after the move
var moveBy = new cc.MoveBy(2, cc._p(500, mySprite.y));
// MoveTo - lets move the new sprite to 300 x 256 over 2 seconds
// MoveTo is absolute - The sprite gets moved to 300 x 256 regardless of
// where it is located now.
var moveTo = new cc.MoveTo(2, cc._p(300, mySprite.y));
// Delay - create a small delay
var delay = new cc.DelayTime(1);
var seq = new cc.Sequence(moveBy, delay, moveTo);
mySprite.runAction(seq);
Basic Actions and how to run them
Basic actions are usually a singular action, thus accomplishing a single objective. Let’s take a
look at a few examples:
Move
Move a Node over a set period of time.
auto mySprite = Sprite::create("mysprite.png");
// Move a sprite to a specific location over 2 seconds.
auto moveTo = MoveTo::create(2, Vec2(50, 0));
mySprite->runAction(moveTo);
// Move a sprite 50 pixels to the right, and 0 pixels to the top over 2 seconds.
auto moveBy = MoveBy::create(2, Vec2(50, 0));
39
mySprite->runAction(moveBy);
var mySprite = new cc.Sprite(res.mysprite_png);
// Move a sprite to a specific location over 2 seconds.
var moveTo = new cc.MoveTo(2, cc._p(50, 0));
mySprite.runAction(moveTo);
// Move a sprite 50 pixels to the right, and 0 pixels to the top over 2 seconds.
var moveBy = new cc.MoveBy(2, cc._p(50, 0));
mySprite.runAction(moveBy);
Rotate
Rotate a Node clockwise over 2 seconds.
auto mySprite = Sprite::create("mysprite.png");
// Rotates a Node to the specific angle over 2 seconds
auto rotateTo = RotateTo::create(2.0f, 40.0f);
mySprite->runAction(rotateTo);
// Rotates a Node clockwise by 40 degree over 2 seconds
auto rotateBy = RotateBy::create(2.0f, 40.0f);
mySprite->runAction(rotateBy);
var mySprite = new cc.Sprite(res.mysprite_png);
// Rotates a Node to the specific angle over 2 seconds
var rotateTo = new cc.RotateTo(2.0, 40.0);
mySprite.runAction(rotateTo);
// Rotates a Node clockwise by 40 degree over 2 seconds
var rotateBy = new cc.RotateBy(2.0, 40.0);
40
mySprite.runAction(rotateBy);
Scale
Scale a Node by 10 over 2 seconds.
auto mySprite = Sprite::create("mysprite.png");
// Scale uniformly by 3x over 2 seconds
auto scaleBy = ScaleBy::create(2.0f, 3.0f);
mySprite->runAction(scaleBy);
// Scale X by 5 and Y by 3x over 2 seconds
auto scaleBy = ScaleBy::create(2.0f, 3.0f, 3.0f);
mySprite->runAction(scaleBy);
// Scale to uniformly to 3x over 2 seconds
auto scaleTo = ScaleTo::create(2.0f, 3.0f);
mySprite->runAction(scaleTo);
// Scale X to 5 and Y to 3x over 2 seconds
auto scaleTo = ScaleTo::create(2.0f, 3.0f, 3.0f);
mySprite->runAction(scaleTo);
var mySprite = new cc.Sprite(res.mysprite_png);
// Scale uniformly by 3x over 2 seconds
var scaleBy = new cc.ScaleBy(2.0, 3.0);
mySprite.runAction(scaleBy);
// Scale X by 5 and Y by 3x over 2 seconds
var scaleBy = new cc.ScaleBy(2.0, 3.0, 3.0);
mySprite.runAction(scaleBy);
// Scale to uniformly to 3x over 2 seconds
var scaleTo = new cc.ScaleTo(2.0, 3.0);
mySprite.runAction(scaleTo);
// Scale X to 5 and Y to 3x over 2 seconds
41
var scaleTo = new cc.ScaleTo(2.0, 3.0, 3.0);
mySprite.runAction(scaleTo);
Fade In/Out
Fade a Node.
It modifies the opacity from 0 to 255. The reverse of this action is FadeOut
auto mySprite = Sprite::create("mysprite.png");
// fades in the sprite in 1 seconds
auto fadeIn = FadeIn::create(1.0f);
mySprite->runAction(fadeIn);
// fades out the sprite in 2 seconds
auto fadeOut = FadeOut::create(2.0f);
mySprite->runAction(fadeOut);
var mySprite = new cc.Sprite(res.mysprite_png);
// fades in the sprite in 1 seconds
var fadeIn = new cc.FadeIn(1.0);
mySprite.runAction(fadeIn);
// fades out the sprite in 2 seconds
var fadeOut = new cc.FadeOut(2.0);
mySprite.runAction(fadeOut);
42
Tint
Tint a Node that implements the NodeRGB protocol from current the tint to
a custom tine.
auto mySprite = Sprite::create("mysprite.png");
// Tints a node to the specified RGB values
auto tintTo = TintTo::create(2.0f, 120.0f, 232.0f, 254.0f);
mySprite->runAction(tintTo);
// Tints a node BY the delta of the specified RGB values.
auto tintBy = TintBy::create(2.0f, 120.0f, 232.0f, 254.0f);
mySprite->runAction(tintBy);
var mySprite = new cc.Sprite(res.mysprite_png);
// Tints a node to the specified RGB values
var tintTo = new cc.TintTo(2.0, 120.0, 232.0, 254.0);
mySprite.runAction(tintTo);
// Tints a node BY the delta of the specified RGB values.
var tintBy = new cc.TintBy(2.0, 120.0, 232.0, 254.0);
mySprite.runAction(tintBy);
Animate
With Animate it is possible to do simple flipbook animation with your Sprite objects. This
is simply replacing the display frame at set intervals for the duration of the animation. Let’s
consider this example:
auto mySprite = Sprite::create("mysprite.png");
// now lets animate the sprite we moved
Vector animFrames;
animFrames.reserve(12);
animFrames.pushBack(SpriteFrame::create("Blue_Front1.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Front2.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Front3.png", Rect(0,0,65,81)));
43
animFrames.pushBack(SpriteFrame::create("Blue_Left1.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Left2.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Left3.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Back1.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Back2.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Back3.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Right1.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Right2.png", Rect(0,0,65,81)));
animFrames.pushBack(SpriteFrame::create("Blue_Right3.png", Rect(0,0,65,81)));
// create the animation out of the frames
Animation* animation = Animation::createWithSpriteFrames(animFrames, 0.1f);
Animate* animate = Animate::create(animation);
// run it and repeat it forever
mySprite->runAction(RepeatForever::create(animate));
var mySprite = new Sprite(res.mysprite_png);
// now lets animate
var animFrames;
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
animFrames.push(new
the sprite we moved.
cc.SpriteFrame(res.Blue_Front1_png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Front2.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Front3.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Left1.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Left2.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Left3.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Back1.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Back2.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Back3.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Right1.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Right2.png), cc.Rect(0,0,65,81)));
cc.SpriteFrame(res.Blue_Right3.png), cc.Rect(0,0,65,81)));
// create the animation out of the frames
var animation = cc.Animation.createWithSpriteFrames(animFrames, 0.1);
var animate = new cc.Animate(animation);
// run it and repeat it forever
mySprite.runAction(cc.RepeatForever(animate));
It’s hard to show an animation in text, so please run the example Programmer Guide Sample
code to see this in action!
44
Easing
Easing is animating with a specified acceleration to make the animations smooth. A few things
to keep in mind is that regardless of speed, ease actions always start and finish at the same
time. Ease actions are a good way to fake physics in your game! Perhaps you want a few
simulated physics effects but don’t want the overhead and complexity of adding it all for a few
very basic actions. Another good example is to animate menus and buttons.
Here are common easing functions displayed over a graph:
Cocos2d-x supports most of the easing function in the above graph. They are also simple to
implement. Lets look at a specific use case. Lets drop a Sprite object from the top of the
screen and make it bounce.
// create a sprite
auto mySprite = Sprite::create("mysprite.png");
45
// create a MoveBy Action to where we want the sprite to drop from.
auto move = MoveBy::create(2, Vec2(200, dirs->getVisibleSize().height newSprite2->getContentSize().height));
auto move_back = move->reverse();
// create a BounceIn Ease Action
auto move_ease_in = EaseBounceIn::create(move->clone() );
// create a delay that is run in between sequence events
auto delay = DelayTime::create(0.25f);
// create the sequence of actions, in the order we want to run them
auto seq1 = Sequence::create(move_ease_in, delay, move_ease_in_back,
delay->clone(), nullptr);
// run the sequence and repeat forever.
mySprite->runAction(RepeatForever::create(seq1));
Run the example Programmer Guide Sample code to see this in action!
Sequences and how to run them
Sequences are a series of Action objects to be executed sequentially. This can be any number of Action objects, Functions and even another Sequence. Functions? Yes! Cocos2d-x
has a CallFunc object that allows you to create a function() and pass it in to be run in your
Sequence. This allows you to add your own functionality to your Sequence objects besides
just the stock Action objects that Cocos2d-x provides. This is what a Sequence looks like
when executing:
An example sequence
auto mySprite = Sprite::create("mysprite.png");
// create a few actions.
auto jump = JumpBy::create(0.5, Vec2(0, 0), 100, 1);
46
auto rotate = RotateTo::create(2.0f, 10);
// create a few callbacks
auto callbackJump = CallFunc::create([](){
log("Jumped!");
});
auto callbackRotate = CallFunc::create([](){
log("Rotated!");
});
// create a sequence with the actions and callbacks
auto seq = Sequence::create(jump, callbackJump, rotate, callbackRotate, nullptr);
// run it
mySprite->runAction(seq);
So what does this Sequence action do?
It will execute the following actions sequentially:
Jump -> callbackJump() -> Rotate -> callbackRotate()
Run the example Programmer Guide Sample code to see this in action!
Spawn
Spawn is very similar to Sequence, except that all actions will run at the same time. You can
have any number of Action objects and even other Spawn objects!
47
Spawn produces the same result as running multiple consecutive runAction() statements. However, the benefit of spawn is that you can put it in a Sequence to help achieve specific effects
that you cannot otherwise. Combining Spawn and Sequence is a very powerful feature.
Example, given:
// create 2 actions and run a Spawn on a Sprite
auto mySprite = Sprite::create("mysprite.png");
auto moveBy = MoveBy::create(10, Vec2(400,100));
auto fadeTo = FadeTo::create(2.0f, 120.0f);
Using a Spawn:
// running the above Actions with Spawn.
auto mySpawn = Spawn::createWithTwoActions(moveBy, fadeTo);
mySprite->runAction(mySpawn);
and consecutive runAction() statements:
48
// running the above Actions with consecutive runAction() statements.
mySprite->runAction(moveBy);
mySprite->runAction(fadeTo);
Both would produce the same result. However, one can use Spawn in a Sequence. This
flowchart shows how this might look:
// create a Sprite
auto mySprite = Sprite::create("mysprite.png");
// create a few Actions
auto moveBy = MoveBy::create(10, Vec2(400,100));
auto fadeTo = FadeTo::create(2.0f, 120.0f);
auto scaleBy = ScaleBy::create(2.0f, 3.0f);
// create a Spawn to use
auto mySpawn = Spawn::createWithTwoActions(scaleBy, fadeTo);
// tie everything together in a sequence
auto seq = Sequence::create(moveBy, mySpawn, moveBy, nullptr);
// run it
mySprite->runAction(seq);
49
Run the example Programmer Guide Sample code to see this in action!
Clone
Clone is exactly like it sounds. If you have an Action, you can apply it to multiple Node
objects by using clone(). Why do you have to clone? Good question. Action objects have
an internal state. When they run, they are actually changing the Node objects properties.
Without the use of clone() you don’t truly have a unique Action being applied to the Node.
This will produce unexpected results, as you can’t know for sure what the properties of the
Action are currently set at.
Let’s hash through an example, say you have a heroSprite and it has a position of (0,0). If you
run an Action of:
MoveBy::create(10, Vec2(400,100));
This will move heroSprite from (0,0) to (400, 100) over the course of 10 seconds. heroSprite
now has a new position of (400, 100) and more importantly the Action has this position in it’s
internal state. Now, say you have an emenySprite with a position of (200, 200). If you were
to apply this same:
MoveBy::create(10, Vec2(400,100));
to your enemySprite, it would end up at a position of (800, 200) and not where you thought it
would. Do you see why? It is because the Action already had an internal state to start from
when performing the MoveBy. Cloning an Action prevents this. It ensures you get a unique
version Action applied to your Node.
Let’s also see this in code, first, incorrect.
// create our Sprites
auto heroSprite = Sprite::create("herosprite.png");
auto enemySprite = Sprite::create("enemysprite.png");
// create an Action
auto moveBy = MoveBy::create(10, Vec2(400,100));
// run it on our hero
heroSprite->runAction(moveBy);
// run it on our enemy
enemySprite->runAction(moveBy); // oops, this will not be unique!
// uses the Actions current internal state as a starting point.
50
Correctly, using clone()!:
// create our Sprites
auto heroSprite = Sprite::create("herosprite.png");
auto enemySprite = Sprite::create("enemysprite.png");
// create an Action
auto moveBy = MoveBy::create(10, Vec2(400,100));
// run it on our hero
heroSprite->runAction(moveBy);
// run it on our enemy
enemySprite->runAction(moveBy->clone()); // correct! This will be unique
Reverse
Reverse is also exactly like it sounds. If you run a series of actions, you can call reverse()
to run it, in the opposite order. Otherwise known as, backwards. However, it is not just simply
running the Action in reverse order. Calling reverse() is actually manipulating the properties
of the original Sequence or Spawn in reverse too.
Using the Spawn example above, reversing is simple.
// reverse a sequence, spawn or action
mySprite->runAction(mySpawn->reverse());
Most Action and Sequence objects are reversible!
It’s easy to use, but let’s make sure we see what is happening. Given:
// create a Sprite
auto mySprite = Sprite::create("mysprite.png");
mySprite->setPosition(50, 56);
// create a few Actions
auto moveBy = MoveBy::create(2.0f, Vec2(500,0));
auto scaleBy = ScaleBy::create(2.0f, 2.0f);
auto delay = DelayTime::create(2.0f);
// create a sequence
auto delaySequence = Sequence::create(delay, delay->clone(), delay->clone(),
delay->clone(), nullptr);
auto sequence = Sequence::create(moveBy, delay, scaleBy, delaySequence, nullptr);
51
// run it
newSprite2->runAction(sequence);
// reverse it
newSprite2->runAction(sequence->reverse());
What is really happening? If we lay out the steps as a list it might be helpful:
•
•
•
•
•
•
•
•
•
•
•
•
mySprite is created
mySprite position is set to (50, 56)
sequence starts to run
sequence moves mySprite by 500, over 2 seconds, mySprite new position (550, 56)
sequence delays for 2 seconds
sequence scales mySprite by 2x over 2 seconds
sequence delays for 6 more seconds (notice we run another sequence to accomplish
this)
we run a reverse() on the sequence so we re-run each action backwards
sequence is delayed for 6 seconds
sequence scales mySprite by -2x over 2 seconds
sequence delays for 2 seconds
sequence moves mySprite by -500, over 2 seconds, mySprite new position (50, 56)
You can see that a reverse() is simple for you to use, but not so simple in its internal logic.
Cocos2d-x does all the heavy lifting!
Building and Transitioning Scenes
What is a Scene?
A Scene is a container that holds Sprites, Labels, Nodes and other objects that your game
needs. A Scene is responsible for running game logic and rendering the content on a per-frame
basis. You need at least one Scene to start your game. You can think of this like a movie. The
Scene is what is running and users see what is happening in real-time. You can have any
number of Scene objects in your game and transition through them easily. Cocos2d-x provides
scene transitions and you can even have scene transitions with cool effects.
Creating a Scene
It is very easy to create a Scene
auto myScene = Scene::create();
52
Remember the Scene Graph?
In Chapter 2 of this guide we learned about a scene graph and how it affects the drawing of
our game. The important thing to remember is that this defines the drawing order of the GUI
elements. Also remember z-order!
A Simple Scene
Lets’s build a simple Scene. Remember that Cocos2d-x uses a right handed coordinate
system. This means that our 0,0 coordinate is at the bottom left corner of the screen/display.
When you start positioning your game elements this is where you should start your calculations
from. Let’s create a simple Scene and add a few elements to it:
auto dirs = Director::getInstance();
Size visibleSize = dirs->getVisibleSize();
auto myScene = Scene::create();
auto label1 = Label::createWithTTF("My Game", "Marker Felt.ttf", 36);
label1->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
myScene->addChild(label1);
auto sprite1 = Sprite::create("mysprite.png");
sprite1->setPosition(Vec2(100, 100));
myScene->addChild(sprite1);
When we run this code we shall see a simple Scene that contains a Label and a Sprite. It
doesn’t do much but it’s a start.
Transitioning between Scenes
You might need to move between Scene objects in your game. Perhaps starting a new game,
changing levels or even ending your game. Cocos2d-x provides a number of ways to do scene
transitions.
Ways to transition between Scenes
There are many ways to transition through your scenes. Each has specific functionality. Let’s
go through them. Given:
auto myScene = Scene::create();
53
runWithScene() - use this for the first scene only. This is the way to start your games first
Scene.
Director::getInstance()->runWithScene(myScene);
replaceScene() - replace a scene outright.
Director::getInstance()->replaceScene(myScene);
pushScene() - suspends the execution of the running scene, pushing it on the stack of suspended scenes. Only call this if there is a running scene.
Director::getInstance()->pushScene(myScene);
popScene() - This scene will replace the running one. The running scene will be deleted. Only
call this if there is a running scene.
Director::getInstance()->popScene(myScene);
Transition Scenes with effects
You can add visual effects to your Scene transitions
auto myScene = Scene::create();
// Transition Fade
Director::getInstance()->replaceScene(TransitionFade::create(0.5, myScene, Color3B(0,255,255)));
// FlipX
Director::getInstance()->replaceScene(TransitionFlipX::create(2, myScene));
// Transition Slide In
Director::getInstance()->replaceScene(TransitionSlideInT::create(1, myScene) );
UI Components
Taking a look at the common apps you might use, I bet that you can spot UI widgets without
necessarily knowing what they are. They aren’t specific to games, every application probably
uses a few widgets. What does UI stand for? What do UI widgets do? Oh so many questions!
Widgets, oh, my!
UI is an abbreviation that stands for user interface. You know, things that are on the screen.
This include items like: labels, buttons, menus, sliders and views. Cocos2d-x provides a set
of UI widgets to make it simple to add these controls to your projects. It may sound trivial, but
a lot goes in to creating a core class like a Label. There are so many aspects of just this one.
54
Could you imagine having to write your own custom widget set? Don’t worry, your needs are
covered!
Label
Cocos2d-x provides a Label object that can create labels using true type, bitmap or the built-in
system font. This single class can handle all your Label needs.
Label BMFont
BMFont is a label type that uses a bitmap font. The characters in a bitmap font are made up of
a matrix of dots. It is very fast and easy to use, but not scalable as it requires a separate font
for each size character. Each character in a Label is a separate Sprite. This means that
each character can be rotated, scaled, tinted, have a different anchor point and/or most any
other property changed.
Creating a BMFont label requires two files: a .fnt file and an image representation of each
character in .png format. If you are using a tool like Glyph Designer these files are created
automatically for you. Creating a Label object from a bitmap font:
auto myLabel = Label::createWithBMFont("bitmapRed.fnt", "Your Text");
All of the characters in the string parameter should be found in the provided .fnt file, otherwise
they won’t be rendered. If you render a Label object and it is missing characters, make sure
they exist in your .fnt file.
Label TTF
True Type Fonts are different from the bitmap fonts we learned about above. With true type
fonts the outline of the font is rendered. This is convenient as you do not need to have a
separate font file for each size and color you might wish to use. Creating a Label object that
55
uses a true type font is easy. To create one you need to specify a .ttf font file name, text string
and a size. Unlike BMFont, TTF can render size changes without the need for a separate font
files. Example, using a true type font:
auto myLabel = Label::createWithTTF("Your Text", "Marker Felt.ttf", 24);
Although it is more flexible than a bitmap font, a true type font is slower to render and changing
properties like the font face and size is an expensive operation.
If you need several Label objects from a true type font that all have the same properties you
can create a TTFConfig object to manage them. A TTFConfig object allows you to set the
properties that all of your labels would have in common. You can think of this like a recipe where
all your Label objects will use the same ingredients.
You can create a TTFConfig object for your Labels in this way:
// create a TTFConfig files for labels to share
TTFConfig labelConfig;
labelConfig.fontFilePath = "myFont.ttf";
labelConfig.fontSize = 16;
labelConfig.glyphs = GlyphCollection::DYNAMIC;
labelConfig.outlineSize = 0;
labelConfig.customGlyphs = nullptr;
labelConfig.distanceFieldEnabled = false;
// create a TTF Label from the TTFConfig file.
auto myLabel = Label::createWithTTF(labelConfig, "My Label Text");
56
A TTFConfig can also be used for displaying Chinese, Japanese and Korean characters.
Label SystemFont
SystemFont is a label type that uses the default system font and font size. This is a font that is
meant not to have its properties changed. You should think of it as system font, system rules.
Creating a SystemFont label:
auto myLabel = Label::createWithSystemFont("My Label Text", "Arial", 16);
Label Effects
After you have your Label objects on screen you might want to make them a bit prettier. Perhaps they look flat or plain. Thankfully you don’t have to create your own custom fonts! Label
57
objects can have effects applied to them. Not all Label objects support all effects. Some effects include shadow, outline and glow. You can apply one or more effects to a Label object
easily:
Label with a shadow effect:
auto myLabel = Label::createWithTTF("myFont.ttf", "My Label Text", 16);
// shadow effect is supported by all Label types
myLabel->enableShadow();
Label with a outline effect:
auto myLabel = Label::createWithTTF("myFont.ttf", "My Label Text", 16);
// outline effect is TTF only, specify the outline color desired
myLabel->enableOutline(Color4B::WHITE, 1));
Label with a glow effect:
58
auto myLabel = Label::createWithTTF("myFont.ttf", "My Label Text", 16);
// glow effect is TTF only, specify the glow color desired.
myLabel->enableGlow(Color4B::YELLOW);
Menu and Menu Items
We are all probably familiar with what a menu is. We see these in every application we use. In
your game you would probably use a Menu object to navigate through game options. Menus
often contain buttons like Play, Quit, Settings and About, but could also contain other Menu
objects for a nested menu system. A Menu object is a special type of Node object. You can
create an empty Menu object as a place holder for your menu items:
auto myMenu = Menu::create();
As we described options above of Play, Quit, Settings and About, these are your menu items.
A Menu without menu items makes little sense. Cocos2d-x offers a variety of ways to create
your menu items including by using a Label object or specifying an image to display. Menu
items usually have two possible states, a normal and a selected state. When you tap or click
on the menu item a callback is triggered. You can think of this as a chain reaction. You tap/click
the menu item and it runs the code you specified. A Menu can have just a single item or many
items.
// creating a menu with a single item
// create a menu item by specifying images
auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
auto menu = Menu::create(closeItem, NULL);
this->addChild(menu, 1);
59
A menu can also be created by using a vector of MenuItem objects:
// creating a Menu from a Vector of items
Vector
Source Exif Data:
File Type : PDF
File Type Extension : pdf
MIME Type : application/pdf
PDF Version : 1.5
Linearized : No
Page Mode : UseOutlines
Page Count : 140
Creator : LaTeX with hyperref package
Producer : XeTeX 0.99996
Create Date : 1969:12:31 23:59:59-00:00
EXIF Metadata provided by EXIF.tools