Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Cocos2d-X Game Development Blueprints
Cocos2d-X Game Development Blueprints

Cocos2d-X Game Development Blueprints: Build a plethora of games for various genres using one of the most powerful game engines, Cocos2d-x

eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Cocos2d-X Game Development Blueprints

Chapter 1. A Colorful Start

We start the journey of game development in Cocos2d-x with a simple, fun, and colorful game. Let's call it ColourSmash. This will serve as a revision of the basic features of the engine and will get us started with some fun development. We will be using the HTML5 version of Cocos2d for this project—Cocos2d-html5-v2.2.3 to be specific. So all the coding in this chapter, and the next, will be done in JavaScript.

Here's what you'll learn in this chapter:

  • How and where to use cc.Scene and cc.Layer
  • How to optimize rendering with a batch node
  • How to use actions and easing
  • How to get touches
  • How to schedule callbacks

An overview of ColourSmash

The game we will discuss here is one of the many famous puzzle games found online. The basic idea of the game is simple: click on a colored tile and all adjacent tiles of the same color disappear. As you may have guessed, the game world consists of a set of colorful tiles. You keep clicking tiles and they disappear. What makes it fun is a bunch of tiles disappearing together yields you a bonus!

This is a glimpse of what we should have at the end of this chapter:

An overview of ColourSmash

Setting up the environment for Cocos2d-html5

Before we actually begin developing this game, let's spend some time setting up an environment for our HTML5 games. Since these are HTML5 games, they will essentially run in a web browser—be it on a computer or a mobile device. You are free to run these games in a browser of your choice. My personal favorite is Google Chrome!

Since we will be using JavaScript to develop the game, I would definitely recommend brushing up on some basic JavaScript coding principles before diving into the code. You can visit the following URL for some help:

http://jstherightway.org/

Moving on, here is the list of software that you will require to run the tests/samples in the Cocos2d-html5 source as well as the Cocos2d-html5 games we'll develop:

The first software on the list is, of course, the source of the Cocos2d-html5 engine, without which we won't be able to move a single web-based muscle.

The next software on the list is WebStorm, which is a powerful JavaScript editor that provides features such as code completion, code refactoring, debugging, and many others. Of course, this does not impact our chapter in anyway. You can choose to use any editor of your choice.

The last item on the list is WampServer, which is optional and is valid only for developers working on a Windows machine. WampServer provides a web server that can serve files over HTTP. This is especially useful if you want to test your game on wireless devices connected to the same network as your development machine.

Once you've downloaded the above software, move to the next section where we will create a sample project.

Creating a project in Cocos2d-html5

Creating a project in Cocos2d-html5 is as simple as copying a readymade template and renaming it to what you want to call your game. If you've downloaded and extracted the archive of the Cocos2d-html5 source, navigate to the template folder inside it. Your file explorer should show you something like this:

Creating a project in Cocos2d-html5

If you run the index.html file you see in the template folder, you'll realize that it is nothing but a hello world project. This is exactly what we need to get us started. To create a new project in Cocos2d-html5, follow these steps:

  1. Copy all the files within the template folder.
  2. Create a folder in the root directory of the Cocos2d-html5 engine. The engine's root with the folder for ColourSmash is shown in the following screenshot:
    Creating a project in Cocos2d-html5
  3. Now, paste all the files that you copied from the template folder into the folder you just created.

That's it! You have created your first project in Cocos2d-html5. Now, it's time to get acquainted with the different kinds of files located in the project's directory.

Getting acquainted with the project structure

The main backbone files required for any Cocos2d-html5 game are the index.html, main.js, and cocos2d.js files. These are exactly the files you will see in your project's root directory. In addition to these three files, you can also see a file called build.xml and another file called cocos2d-jsb.js. Take a look at the following table for a brief description of what these files are responsible for:

File

Description

index.html

This is the main HTML page that will be displayed on any device's browser. This is where your game will run. This is also the file you must double-click on in order to launch the game in a browser.

main.js

This file could be compared to the AppDelegate class from Cocos2d-x. It is the starting point of our game and is where the director is informed of which the game's first scene should be.

cocos2d.js

This file is the main configuration file and is the only source file that gets linked to your HTML page. This file is responsible for invoking the engine's main loader. Any sources that go into your game need to be listed in this file.

cocos2d-jsb.js

This JavaScript source file is required to boot JavaScript bindings and is not required for Cocos2d-html5. You could delete this file if you don't intend on using JavaScript bindings.

build.xml

You can compress your entire game's source code into a single file using the Google Closure Compiler that is provided under the tools directory of the Cocos2d-html5 source. This file is the input to the Ant build command that invokes the compiler. To run this, you will need Ant and JRE installed on your machine.

resources.js

This file contains a JSON object that lists all the resources that you will need to run the game. You must ensure that each and every resource (image, plist, font, audio, and so on) is included in this file. Not doing so will most certainly crash your application.

The engine will then load all the files listed in this file into the browser's memory. Therefore, you will still need to load the textures, sprite frames and animations into their respective caches.

Now that we have a basic understanding of the structure of a typical Cocos2d-html5 project, it is time to create our very first scene in ColourSmash.

Creating the first scene – the main menu

Our first scene happens to be the opening screen of the game—the main menu. It is what the users will see when the game has finished loading. This scene is defined in mainmenu.js in the source for this project. This is what it looks like:

var MainMenu = cc.Layer.extend({

  init:function () {
    this._super();

    return true;
  }
});

var MainMenuScene = cc.Scene.extend({
  onEnter:function () {
    this._super();
    var layer = new MainMenu();
    layer.init();
    this.addChild(layer);
  }
});

As you can see, we have two entities here; an object called MainMenu, which is of type cc.Layer, and a class called MainMenuScene, which extends the cc.Scene class. Understandably, if you've worked on Cocos2d-x before, this is the way the various screens within a game are structured into scenes and layers. If you do need to brush up on some Cocos2d node graph basics, feel free to pay a visit to the following link:

http://www.cocos2d-x.org/wiki/Scene_Graph

Now that we have created a cc.Scene class and a cc.Layer class, it's time to create some basic UI elements. We add a title and a play button to our main menu and add some color to the background. Hence, the following code is added to the init function of MainMenu:

// create a coloured layer as background
var background = cc.LayerColor.create(cc.c4b(25, 0, 51, 255), this.screenSize.width, this.screenSize.height);
this.addChild(background);
 
// create a label to display the name of the game
var titleLabel = cc.LabelTTF.create("ColourSmash", "Comic Sans MS", 64);
titleLabel.setPosition(cc.p(this.screenSize.width * 0.5, this.screenSize.height * 0.8));
this.addChild(titleLabel, 1);
 
// create a play button to move to the game world
var playButton = cc.MenuItemSprite.create(cc.Sprite.create(s_Play));
playButton.setCallback(this.onPlayClicked, this);
playButton.setPosition(cc.p(this.screenSize.width * 0.5, this.screenSize.height * 0.5));
 
// create a menu that will contain the button above
var menu = cc.Menu.create(playButton);
menu.setPosition(0,0);
this.addChild(menu, 1);

Notice how the callback is set for the play button. In Cocos2d-html5, we need not specify the kind of function pointer that we're setting into the callback. Since all functions are objects in JavaScript, we need to pass the handler function, and the class it belongs to, as parameters to the setCallback function. The handler function that will take us to the GameWorld is given as follows:

onPlayClicked:function(){
  // ask the director to change the running scene
  cc.Director.getInstance().replaceScene(cc.TransitionFade.create(0.5, new GameWorldScene()));
}

Note

An important difference in the API of Cocos2d-x and Cocos2d-html5 is the absence of selector types in the latter. Whether a function has to be passed as a schedule_selector, a callfunc_selector, or a menu_selector, the API requires only the reference to the function.

The code for the play button's callback is pretty straightforward. It just tells the director to replace the current scene with GameWorldScene and include a smooth fade transition.

That completes a simple version of our MainMenu, but how will this scene be displayed in the first place? To answer that question, we navigate to the bottom of the main.js file and pass an object of our MainMenuScene class as an argument to the cocos2dApp class' constructor:

var myApp = new cocos2dApp(MainMenuScene);

This will set MainMenuScene as the first scene that will be displayed when the web application has loaded.

Tip

Downloading the example code

You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Moving on to the game world

We will add another scene to represent the actual game play, which will contain its own cc.Layer called GameWorld. This class is defined in the gameworld.js file in the source bundle for this chapter. Every scene that you define must be added to the list of sources in cocos2d.js and build.xml if you plan on using the closure compiler to compress your source files.

For this game, all we need is a small, white, square-shaped image like this:

Moving on to the game world

We will use this white image and manually set different RGB values for the sprites to create our grid of colorful tiles. Don't forget to add this to the resources.js file so that it is preloaded and can be used in the game.

Now that we have our sprites, we can actually start building our grid. Let's define a few constants before we do that. You're right, JavaScript does not have a concept of constants, however, for the purposes of our understanding, we will name and consider these quantities as constants. Here is the declaration of the constants in the gameworld.js file:

var MAX_COLOURS = 4;
// maximum number of colours we can use
var TILE_SIZE = 32;
// size in points of each tile (same as tile.png)
var NUM_COLS = 14;
// maximum number of columns
var NUM_ROWS = 20;
// maximum number of rows
var GAMEPLAY_OFFSET = cc.p(TILE_SIZE/2, TILE_SIZE);
// offset so that game is not stuck to the bottom-left
var SCORE_PER_TILE = 10;
// score when a tile is cleared
var BONUS = [50, 40, 30, 20, 10];
// number of tiles used to trigger bonuses eg. Bonus if 50 tiles collected in one shot
 
// define an object that we can use an enumeration for our colour types
var E_COLOUR_TYPE = {
  E_COLOUR_NONE:0,
  E_COLOUR_RED:1,
  E_COLOUR_GREEN:2,
  E_COLOUR_BLUE:3,
  E_COLOUR_YELLOW:4
};

We have defined a constant GAMEPLAY_OFFSET. This is a convenient variable that specifies how many points should be added to our grid so that it appears in the center of the game world. We have also defined another quantity E_COLOUR_TYPE, which will act as enum to represent our color types. Since JavaScript is a weak-typed language, we cannot really create enumerations like in C++, which is a strong-typed language. The best we can do is to simulate a normal JavaScript object so that we can have the convenience of an enum, as done in the preceding code snippet.

Declaring and initializing the variables

Let's declare the members of the GameWorld class and define the init method that will be called when this scene is created:

// member variable declarations
// save screenSize for fast access
screenSize:null,
// array to represent the colour type for each tile
tileData:null,
// array to hold each tile's sprite
tileSprites:null,
// batch rendering
spriteBatchNode:null,
// arrays to support game logic
tilesToRemove:null,
tilesToShift:null,
// score and time
score:0,
scoreLabel:null,
time:0,
timeLabel:null,
// buttons and popups
pauseButton:null,
popup:null,
isGameOver:false,

init:function () {
  this._super();

  this.screenSize = cc.Director.getInstance().getWinSize();

  this.tilesToRemove = [];
  this.tilesToShift = [];
  this.createBackground();
  this.createTileData();
  this.createTileSprites();
  this.createHUD();
  this.doCountdownAnimation();

  return true;
},

Right on top, we have two arrays named tileData and tileSprites to hold our data and sprites respectively. Then, we have our sprite batch node that will be used for optimized rendering. Next, you can see arrays that we will use to find and remove tiles when a user makes a move. Last but not the least, we have our HUD elements and menu buttons.

Creating the background

Let's begin filling up the GameWorld by creating the background, which will contain the play area for the game, the title of the game, and a pause button. The code is as follows:

createBackground:function(){
  // same as main menu
  var background = cc.LayerColor.create(cc.c4b(25, 0, 51, 255), this.screenSize.width, this.screenSize.height);
  this.addChild(background);
 
  // generate vertices for the gameplay frame
  var vertices = [];
  vertices[0] = cc.pAdd(GAMEPLAY_OFFSET, cc.p(-1, -1));
  vertices[1] = cc.pAdd(GAMEPLAY_OFFSET, cc.p(-1, (NUM_ROWS * TILE_SIZE)+1));
  vertices[2] = cc.pAdd(GAMEPLAY_OFFSET, cc.p((NUM_COLS * TILE_SIZE)+1, (NUM_ROWS * TILE_SIZE)+1));
  vertices[3] = cc.pAdd(GAMEPLAY_OFFSET, cc.p((NUM_COLS * TILE_SIZE)+1, -1));
  // use new DrawingPrimitive class
  var gamePlayFrame = cc.DrawNode.create();
  // pass vertices, fill colour, border width and border colour to get a nice bordered, coloured rectangle
  gamePlayFrame.drawPoly(vertices, cc.c4f(0.375, 0.375, 0.375, 1), 2, cc.c4f(0.4, 0, 0, 1));
  // must add the DrawNode else it won't be drawn at all
  this.addChild(gamePlayFrame);
 
  // label to show the title of the game
  var titleLabel = cc.LabelTTF.create("ColourSmash", "Comic Sans MS", 52);
  titleLabel.setPosition(cc.p(this.screenSize.width * 0.5, this.screenSize.height * 0.95));
  this.addChild(titleLabel);
 
  // menu containing a button to pause the game
  this.pauseButton = cc.MenuItemSprite.create(cc.Sprite.create(s_Pause));
  this.pauseButton.setCallback(this.onPauseClicked, this);
  this.pauseButton.setPosition(cc.p(this.screenSize.width * 0.9, this.screenSize.height * 0.95));
  this.pauseButton.setEnabled(false);
  var pauseMenu = cc.Menu.create(this.pauseButton);
  pauseMenu.setPosition(cc.POINT_ZERO);
  this.addChild(pauseMenu,1);
},

We've used a cc.LayerColor class to create a simple, colored background that is of the same size as the screen. Next, we make use of the new primitive drawing class called cc.DrawNode. This class is much faster and simpler than the cc.DrawingPrimitive class. We will use it to draw a filled rectangle with a colored border of some thickness. This rectangle will act as a visual container for our tiles.

To do this, we generate an array of vertices to represent the four points that compose a rectangle and pass it to the drawPoly function along with the color to fill, border width, and border color. The cc.DrawNode object is added to GameWorld just like any other cc.Node. This is one of the major differences between the cc.DrawNode and the older cc.DrawingPrimitives. We don't need to manually draw our primitives on every frame inside the draw function either. This is handled by the cc.DrawNode class. In addition, we can run most kinds of cc.Action objects the cc.DrawNode. We will discuss more on actions later. For now, all that's left is to add a label for the game's title and a pause button to launch the pause menu.

Creating the tiles

Now that we have defined the background and play area, let's create the tiles and their respective sprites. The code is as follows:

createTileData:function(){
        this.tileData = [];
        // generate tile data randomly
        for(var i = 0; i < (NUM_COLS * NUM_ROWS); ++i){
            this.tileData[i] = 1 + Math.floor(Math.random() * MAX_COLOURS);
        }
    },

Based on a random value, one of the four predefined color types are chosen from the E_COLOUR_TYPE enum and saved into the tileData array. The code is as follows:

createTileSprites:function(){
  // create the batch node passing in path to the texture & initial capacity
  // initial capacity is slightly more than maximum number of sprites
  // this is because new tiles may be added before old tiles are removed
  this.spriteBatchNode = cc.SpriteBatchNode.create(s_Tile, NUM_COLS * NUM_ROWS + NUM_ROWS);
  this.addChild(this.spriteBatchNode);
 
  this.tileSprites = [];
  for(var i = 0; i < (NUM_COLS * NUM_ROWS); ++i){
  this.createTileSprite(i);
  }
},

Looking at the createTileSprites function, we have created a cc.SpriteBatchNode object and added it to the game world. The cc.SpriteBatchNode class offers a great way to optimize rendering, as it renders all its child sprites in one single draw call. For a game like ours where the grid is composed of 280 sprites, we save on 279 draw calls! The only prerequisite of the cc.SpriteBatchNode class is that all its children sprites use the same texture. Since all our tile sprites use the same image, we fulfill this criterion.

We create the sprite batch node and pass in the path to the image and the initial capacity as parameters. You can see that the initial capacity is slightly more than the maximum number of tiles in the grid. This is done to prevent unnecessary resizing of the batch node later in the game.

Tip

It's a good idea to create a sprite batch node with a predefined capacity. If you fail to do this, the sprite batch node class will have to allocate more memory at runtime. This is computationally expensive, since the texture coordinates will have to be computed again for all existing child sprites.

Great! Let's write the createTileSprite function where we will create each sprite object, give them a color, and give them a position:

createTileSprite:function(tileId){
  // create sprite with the image
  this.tileSprites[tileId] = cc.Sprite.create(s_Tile);
  // set colour based on the tile's data
  this.tileSprites[tileId].setColor(this.getColourForTile(this.tileData[tileId]));
  // set colour based on the tile's index
  this.tileSprites[tileId].setPosition(this.getPositionForTile(tileId));
  // save the index of the tile as user data
  this.tileSprites[tileId].setUserData(tileId);
  // add the sprite to the batch node
  this.spriteBatchNode.addChild(this.tileSprites[tileId]);
},

The createTileSprite function, which is called in a loop, creates a sprite and sets the respective position and color. The position is calculated based on the tile's ID within the grid, in the function getPositionForTile. The color is decided based on the E_COLOUR_TYPE value of the corresponding cell in the tileData array in the getColourForTile function.

Please refer to the code bundle for this chapter for the implementation of these two functions. Notice how the tileId value for each tile sprite is saved as user data. We will make good use of this data a little later in the chapter.

Creating the Heads-Up Display

A Heads-Up Display (HUD) is the part of the game's user interface that delivers information to the user. For this game, we have just two pieces of information that we need to tell the user about, that is, the score and the time left. As such, we initialize these variables and create respective labels and add them to GameWorld. The code is as follows:

createHUD:function(){
  // initialise score and time
  this.score = 0;
  this.time = 60;
 
  // create labels for score and time
  this.scoreLabel = cc.LabelTTF.create("Score:" + this.score, "Comic Sans MS", 18);
  this.scoreLabel.setPosition(cc.p(this.screenSize.width * 0.33, this.screenSize.height * 0.875));
  this.addChild(this.scoreLabel);
  this.timeLabel = cc.LabelTTF.create("Time:" + this.time, "Comic Sans MS", 18);
  this.timeLabel.setPosition(cc.p(this.screenSize.width * 0.66, this.screenSize.height * 0.875));
  this.addChild(this.timeLabel);
},

The countdown timer

A countdown timer is quite common in many time-based games. It serves the purpose of getting the user charged-up to tackle the level, and it also prevents the user from losing any time because the level started before the user could get ready.

Let's take a look at the following code:

doCountdownAnimation:function(){
  // create the four labels
  var labels = [];
  for(var i = 0; i < 4; ++i)
  {
    labels[i] = cc.LabelTTF.create("", "Comic Sans MS", 52);
    // position the label at the centre of the screen
    labels[i].setPosition(cc.p(this.screenSize.width/2, this.screenSize.height/2));
    // reduce opacity so that the label is invisible
    labels[i].setOpacity(0);
    // enlarge the label
    labels[i].setScale(3);
    this.addChild(labels[i]);
  }
 
  // assign strings
  labels[0].setString("3");
  labels[1].setString("2");
  labels[2].setString("1");
  labels[3].setString("Start");
 
  // fade in and scale down at the same time
  var fadeInScaleDown = cc.Spawn.create(cc.FadeIn.create(0.25), cc.EaseBackOut.create(cc.ScaleTo.create(0.25, 1)));
  // stay on screen for a bit
  var waitOnScreen = cc.DelayTime.create(0.75);
  // remove label and cleanup
  var removeSelf = cc.RemoveSelf.create(true);
 
  for(var i = 0; i < 4; ++i)
  {
    // since the labels should appear one after the other,
    // we give them increasing delays before they appear
    var delayBeforeAppearing = cc.DelayTime.create(i);
    var countdownAnimation = cc.Sequence.create(delayBeforeAppearing, fadeInScaleDown, waitOnScreen, removeSelf);
    labels[i].runAction(countdownAnimation);
  }
 
  // after the animation has finished, start the game
  var waitForAnimation = cc.DelayTime.create(4);
  var finishCountdownAnimation = cc.CallFunc.create(this.finishCountdownAnimation, this);
  this.runAction(cc.Sequence.create(waitForAnimation, finishCountdownAnimation));
},
 
finishCountdownAnimation:function(){
  // start executing the game timer
  this.schedule(this.updateTimer, 1);
  // finally allow the user to touch
  this.setTouchEnabled(true);
  this.pauseButton.setEnabled(true);
},

We declare an array to hold the labels and run a loop to create the four labels. In this loop, the position, opacity, and scale for each label is set. Notice how the scale of the label is set to 3 and opacity is set to 0. This is because we want the text to scale down from large to small and fade in while entering the screen. Finally, add the label to GameWorld. Now that the labels are created and added the way we want, we need to dramatize their entry and exit. We do this using one of the most powerful features of the Cocos2d-x engine—actions!

Note

Actions are lightweight classes that you can run on a node to transform it. Actions allow you to move, scale, rotate, fade, tint, and do much more to a node. Since actions can run on any node, we can use them with everything from sprites to labels and from layers to even scenes!

We use the cc.Spawn class to create our first action, fadeInScaleDown. The cc.Spawn class allows us to run multiple finite time actions at the same time on a given node. In this case, the two actions that need to be run simultaneously are cc.FadeIn and cc.ScaleTo. Notice how the cc.ScaleTo object is wrapped by a cc.EaseBackOut action. The cc.EaseBackOut class is inherited from cc.ActionEase. It will basically add a special easing effect to the cc.ActionInterval object that is passed into it.

Tip

Easing actions are a great way to make transformations in the game much more aesthetically appealing and fun. They can be used to make simple actions look elastic or bouncy, or give them a sinusoidal effect or just a simple easing effect. To best understand what cc.EaseBackOut and other cc.ActionEase actions do, I suggest that you check out the Cocos2d-x or Cocos2d-html5 test cases.

Next, we create a cc.DelayTime action called waitOnScreen. This is because we want the text to stay there for a bit so the user can read it. The last and final action to be run will be a cc.RemoveSelf action. As the name suggests, this action will remove the node it is being run on from its parent and clean it up. Notice how we have created the array as a function variable and not a member variable. Since we use cc.RemoveSelf, we don't need to maintain a reference and manually delete these labels.

Tip

The cc.RemoveSelf action is great for special effects in the game. Special effects may include simple animations or labels that are added, animate for a bit, and then need to be removed. In this way, you can create a node, run an action on it, and forget about it!

Examples may include simple explosion animations that appear when a character collides in the game, bonus score animations, and so on.

These form our three basic actions, but we need the labels to appear and disappear one after another. In a loop, we create another cc.DelayTime action and pass an incremental value so that each label has to wait just the right amount of time before its fadeInScaleDown animation begins. Finally, we chain these actions together into a cc.Sequence object named countdownAnimation so that each action is run one after another on each of the labels. The cc.Sequence class allows us to run multiple finite time actions one after the other on a given node.

The countdown animation that has just been implemented can be achieved in a far more efficient way using just a single label with some well designed actions. I will leave this for you as an exercise (hint: make use of the cc.Repeat action).

Once our countdown animation has finished, the user is ready to play the game, but we need to be notified when the countdown animation has ended. Thus, we add a delay of 4 seconds and a callback to the finishCountdownAnimation function. This is where we schedule the updateTimer function to run every second and enable touch on the game world.

Let's get touchy...

Touch events are broadcasted to all cc.Layers in the scene graph that have registered for touch events by calling setTouchEnabled(true). The engine provides various functions that offer different kinds of touch information.

For our game, all we need is a single touch. So, we shall override just the onTouchesBegan function that provides us with a set of touches. Notice the difference in the name of the function versus Cocos2d-x API. Here is the onTouchesBegan function from the gameworld.js file:

onTouchesBegan:function (touches, event) {
  // get touch coordinates
  var touch = cc.p(touches[0].getLocation().x, touches[0].getLocation().y);
  // calculate touch within the grid
  var touchWithinGrid = cc.pSub(touch, GAMEPLAY_OFFSET);
  // calculate the column touched
  var col = Math.floor(touchWithinGrid.x / TILE_SIZE);
  // calculate the row touched
  var row = Math.floor(touchWithinGrid.y / TILE_SIZE);
  // calculate the id of the touched tile
  var touchedTile = row * NUM_COLS + col;
 
  // simple bounds checking to ignore touches outside of the grid
  if(col < 0 || col >= NUM_COLS || row < 0 || row >= NUM_ROWS)
  return;
 
  // disable touch so that the subsequent functions have time to execute
  this.setTouchEnabled(false);
  this.findTilesToRemove(col, row, this.tileData[touchedTile]);
  this.updateScore(touch);
  this.removeTilesWithAnimation();
  this.findTilesToShift();
},

Once we have got the point of touch, we calculate exactly where the touch has occurred within the grid of tiles and subsequently the column, row, and exact tile that has been touched. Equipped with this information, we can actually go ahead and begin coding the core gameplay.

An important thing to notice is how touch is disabled here. This is done so that the subsequent animations are given enough time to finish. Not doing this would result in a few of the tiles staying on screen and leaving blank spaces. You are encouraged to comment this line to see exactly what happens in this case.

The core gameplay

The core gameplay will consist of the following steps:

  1. Finding the tile/s to be removed
  2. Removing the tile/s with an awesome effect
  3. Finding and shifting the tiles above into the recently vacated space with an awesome effect
  4. Adding new tiles
  5. Adding score and bonus
  6. Ending the game when the time has finished

We will go over each of these separately and in sufficient detail, starting with the recursive logic to find which tiles to remove. To make it easy to understand what each function is actually doing, there are screenshots after each stage.

Finding the tiles

The first step in our gameplay is finding the tiles that should be cleared based on the tile that the user has touched. This is done in the findTilesToRemove function as follows:

findTilesToRemove:function(col, row, tileColour){
  // first do bounds checking
  if(col < 0 || col >= NUM_COLS || row < 0 || row >= NUM_ROWS)
  return;
 
  // calculate the ID of the tile using col & row
  var tileId = row * NUM_COLS + col;
 
  // now check if tile is of required colour
  if(this.tileData[tileId] != tileColour)
  return;
 
  // check if tile is already saved
  if(this.tilesToRemove.indexOf(tileId) >= 0)
  return;
 
  // save the tile to be removed
  this.tilesToRemove.push(tileId);
 
  // check up
  this.findTilesToRemove(col, row+1, tileColour);
 
  // check down
  this.findTilesToRemove(col, row-1, tileColour);
 
  // check left
  this.findTilesToRemove(col-1, row, tileColour);
 
  // check right
  this.findTilesToRemove(col+1, row, tileColour);
},

The findTilesToRemove function is a recursive function that takes a column, row, and target color (the color of the tile that the user touched). The initial call to this function is executed in the onTouchesBegan function.

A simple bounds validation is performed on the input parameters and control is returned in case of any invalidation. Once the bounds have been validated, the ID for the given tile is calculated based on the row and column the tile belongs to. This is the index of the specific tile's data in the tileData array. The tile is then pushed into the tilesToRemove array if its color matches the target color and if it hasn't already been pushed. What follows then are the recursive calls that check for matching tiles in the four directions: up, down, left, and right.

Before we proceed to the next step in our gameplay, let's see what we have so far. The red dot is the point the user touched and the tiles highlighted are the ones that the findTilesToRemove function has found for us.

Finding the tiles

Removing the tiles

The next logical step after finding the tiles that need to be removed is actually removing them. This happens in the removeTilesWithAnimation function from the gameworld.js file:

removeTilesWithAnimation:function(){
  for(var i = 0; i < this.tilesToRemove.length; ++i)
  {
    // first clear the tile's data
    this.tileData[this.tilesToRemove[i]] = E_COLOUR_TYPE.E_COLOUR_NONE;
    // the tile should scale down with easing and then remove itself
    this.tileSprites[this.tilesToRemove[i]].runAction(cc.Sequence.create(cc.EaseBackIn.create(cc.ScaleTo.create(0.25, 0.0)), cc.RemoveSelf.create(true)));
    // nullify the tile's sprite
    this.tileSprites[this.tilesToRemove[i]] = null;
  }
  // wait for the scale down animation to finish then bring down the tiles from above
  this.spriteBatchNode.runAction(cc.Sequence.create(cc.DelayTime.create(0.25), cc.CallFunc.create(this.bringDownTiles, this)));
},

The first order of business in this function would be to clear the data used to represent the tile, so we set it to E_COLOUR_NONE. Now comes the fun part—creating a nice animation sequence for the exit of the tile. This will consist of a scale-down animation wrapped by a neat cc.EaseBackIn ease effect.

Now, all we need to do is nullify the tile's sprite since the engine will take care of removing and cleaning up the sprite for us by virtue of the cc.RemoveSelf action. This animation will take time to finish, and we must wait, so we create a sequence consisting of a delay (with a duration the same as the scale-down animation) and a callback to the bringDownTiles function. We run this action on the spriteBatchNode object.

Let's see what the game looks like after the removeTilesWithAnimation function has executed:

Removing the tiles

Finding and shifting tiles from above

As you can see in the preceding screenshot, we're left with a big hole in our gameplay. We now need the tiles above to fall down and fill this hole. This happens in the findTilesToShift function from the gameworld.js file:

findTilesToShift:function(){
  // first sort the tiles to be removed, in descending order
  this.tilesToRemove.sort(function(a, b){return b-a});

  // for each tile, bring down all the tiles belonging to the same column that are above the current tile
  for(var i = 0; i < this.tilesToRemove.length; ++i)
  {
    // calculate column and row for the current tile to be removed
    var col = Math.floor(this.tilesToRemove[i] % NUM_COLS);
    var row = Math.floor(this.tilesToRemove[i] / NUM_COLS);

    // iterate through each row above the current tile
    for(var j = row+1; j < NUM_ROWS; ++j)
    {
      // each tile gets the data of the tile exactly above it
      this.tileData[(j-1) * NUM_COLS + col] = this.tileData[j * NUM_COLS + col];
      // each tile now refers to the sprite of the tile exactly above it
      this.tileSprites[(j-1) * NUM_COLS + col] = this.tileSprites[j * NUM_COLS + col];
      // null checking...this sprite may have already been nullified by removeTilesWithAnimation
      if(this.tileSprites[(j-1) * NUM_COLS + col])
      {
        // save the new index as user data
        this.tileSprites[(j-1) * NUM_COLS + col].setUserData((j-1) * NUM_COLS + col);
        // save this tile's sprite so that it is animated, but only if it hasn't already been saved
        if(this.tilesToShift.indexOf(this.tileSprites[(j-1) * NUM_COLS + col]) == -1)
        this.tilesToShift.push(this.tileSprites[(j-1) * NUM_COLS + col]);
      }
    }
    // after shifting the whole column down, the tile at the top of the column will be empty
    // set the data to -1...-1 means empty
    this.tileData[(NUM_ROWS-1) * NUM_COLS + col] = -1;
    // nullify the sprite's reference
    this.tileSprites[(NUM_ROWS-1) * NUM_COLS + col] = null;
  }
},

Before actually shifting anything, we use some JavaScript trickery to quickly sort the tiles in descending order. Now within a loop, we find out exactly which column and row the current tile belongs to. Then, we iterate through every tile above the current tile and assign the data and sprite of the above tile to the data and sprite of the current tile.

Before saving this tile's sprite into the tilesToShift array, we check to see if the sprite hasn't already been nullified by the removeTilesWithAnimation function. Notice how we set the user data of the tile's sprite to reflect its new index. Finally, we push this sprite into the tilesToShift array, if it hasn't already been pushed.

Once this is done, we will have a single tile right at the top of the grid that is now empty. For this empty tile, we set the data to -1 and nullify the sprite's reference. This same set of instructions continues for each of the tiles within the tilesToRemove array until all tiles have been filled with tiles from above. Now, we need to actually communicate this shift of tiles to the user through a smooth bounce animation. This happens in the bringDownTiles function in the gameworld.js file as follows:

bringDownTiles:function(){
  for(var i = 0; i < this.tilesToShift.length; ++i)
  {
    // the tiles should move to their new positions with an awesome looking bounce
    this.tilesToShift[i].runAction(cc.EaseBounceOut.create(cc.MoveTo.create(0.25, this.getPositionForTile(this.tilesToShift[i].getUserData()))));
  }
  // wait for the movement to finish then add new tiles
  this.spriteBatchNode.runAction(cc.Sequence.create(cc.DelayTime.create(0.25), cc.CallFunc.create(this.addNewTiles, this)));
},

In the bringDownTiles function, we loop over the tilesToShift array and run a cc.MoveTo action wrapped by a cc.EaseBounceOut ease action. Notice how we use the user data to get the new position for the tile's sprite. The tile's index is stored as user data into the sprite so that we could use it at any time to calculate the tile's correct position.

Once again, we wait for the animation to finish before moving forward to the next set of instructions. Let's take a look at what the game world looks like at this point. Don't be surprised by the +60 text there, we will get to it soon.

Finding and shifting tiles from above

Adding new tiles

We have successfully managed to find and remove the tiles the user has cleverly targeted, and we have also shifted tiles from above to fill in the gaps. Now we need to add new tiles so the game can continue such that there are no gaps left. This happens in the addNewTiles function in the gameworld.js file as follows:

addNewTiles:function(){
  // first search for all tiles having value -1...-1 means empty
  var emptyTileIndices = [], i = -1;
  while( (i = this.tileData.indexOf(-1, i+1)) != -1){
  emptyTileIndices.push(i);
  }
 
  // now create tile data and sprites
  for(var i = 0; i < emptyTileIndices.length; ++i)
  {
  // generate tile data randomly
  this.tileData[emptyTileIndices[i]] = 1 + Math.floor(Math.random() * MAX_COLOURS);
  // create tile sprite based on tile data
  this.createTileSprite(emptyTileIndices[i]);
  }
 
  // animate the entry of the sprites
  for(var i = 0; i < emptyTileIndices.length; ++i)
  {
    // set the scale to 0
    this.tileSprites[emptyTileIndices[i]].setScale(0);
    // scale the sprite up with a neat easing effect
    this.tileSprites[emptyTileIndices[i]].runAction(cc.EaseBackOut.create(cc.ScaleTo.create(0.125, 1)));
  }
 
  // the move has finally finished, do some cleanup
  this.cleanUpAfterMove();
},

We start by finding the indices where new tiles are required. We use some JavaScript trickery to quickly find all the tiles having data -1 in our tileData array and push them into the emptyTileIndices array.

Now we need to simply loop over this array and randomly generate the tile's data and the tile's sprite. However, this is not enough. We need to animate the entry of the tiles we just created. So, we scale them down completely and then run a scale-up action with an ease effect.

We have now completed a single move that the user has made and it is time for some cleanup. Here is the cleanUpAfterMove function of gameworld.js:

cleanUpAfterMove:function(){
  // empty the arrays
  this.tilesToRemove = [];
  this.tilesToShift = [];
  // enable touch so the user can continue playing, but only if the game isn't over
  if(this.isGameOver == false)
  this.setTouchEnabled(true);
},

In the cleanup function, we simply empty the tilesToRemove and tilesToShift arrays. We enable the touch so that the user can continue playing. Remember that we had disabled touch in the onTouchesBegan function. Of course, touch should only be enabled if the game has not ended.

This is what the game world looks like after we've added new tiles:

Adding new tiles

Adding score and bonus

So the user has taken the effort to make a move, the tiles have gone, and new ones have arrived, but the user hasn't been rewarded for this at all. So let's give the user some positive feedback in terms of their score and check if the user has made a move good enough to earn a bonus.

All this magic happens in the updateScore function in the gameworld.js file as follows:

updateScore:function(point){
  // count the number of tiles the user just removed
  var numTiles = this.tilesToRemove.length;
 
  // calculate score for this move
  var scoreToAdd = numTiles * SCORE_PER_TILE;
 
  // check if a bonus has been achieved
  for(var i = 0; i < BONUS.length; ++i)
  {
    if(numTiles >= BONUS[i])
    {
      // add the bonus to the score for this move
      scoreToAdd += BONUS[i] * 20;
      break;
    }
  }
 
  // display the score for this move
  this.showScoreText(scoreToAdd, point);
  // add the score for this move to the total score
  this.score += scoreToAdd;
  // update the total score label
  this.scoreLabel.setString("Score:" + this.score);
  // run a simple action so the user knows the score is being added
  // use the ease functions to create a heart beat effect
  this.scoreLabel.runAction(cc.Sequence.create(cc.EaseSineIn.create(cc.ScaleTo.create(0.125, 1.1)), cc.EaseSineOut.create(cc.ScaleTo.create(0.125, 1))));
},

We calculate the score for the last move by counting the number of tiles removed in the last move. Remember that this function is called right after the findTilesToRemove function in onTouchesBegan, so tilesRemoved still has its data. We now compare the number of tiles removed with our bonus array BONUS, and add the respective score if the user managed to remove more than the predefined tiles to achieve a bonus.

This score value is added to the total score and the corresponding label's string is updated. However, merely setting the string to reflect the new score is not enough in today's games. It is very vital to get the users' attention and remind them that they did something cool or earned something awesome. Thus, we run a simple and subtle scale-up/scale-down animation on the score label. Notice how the ease actions are used here. This results in a heartbeat effect on the otherwise simple scaling animation.

We notify the score achieved in each move to the user using the showScoreText function:

// this function can be used to display any message to the user
// but we will use it to display the score for each move
showScoreText:function(scoreToAdd, point){
  // create the label with the score & place it at the respective point
  var bonusLabel = cc.LabelTTF.create("+" + scoreToAdd, "Comic Sans MS", 32);
  bonusLabel.setPosition(point);
  // initially scale it down completely
  bonusLabel.setScale(0);
  // give it a yellow colour
  bonusLabel.setColor(cc.YELLOW);
  this.addChild(bonusLabel, 10);
 
  // animate the bonus label so that it scales up with a nice easing effect
  bonusLabel.runAction( cc.Sequence.create(cc.EaseBackOut.create(cc.ScaleTo.create(0.125, 1)),
  cc.DelayTime.create(1),
  // it should stay on screen so the user can read it
  cc.EaseBackIn.create(cc.ScaleTo.create(0.125, 0))
  // scale it back down with a nice easing effect
  cc.RemoveSelf.create(true) ));
  // its task is finished, so remove it with cleanup
},

The preceding function can be used to display any kind of text notification to the user. For the purpose of our game, we will use it only to display the score in each move. The function is quite simple and precise. It creates a label with the string passed as a parameter and places it at the position passed as a parameter. This function also animates the text so it scales up with some easing, stays for some time so the user registers it, scales down again with easing, and finally removes the text.

It seems as if we have almost finished our first game, but there is still a vital aspect of this game that is missing—the timer. What was the point of running a scheduler every second? Well let's take a look.

Updating the timer

We scheduled the timer as soon as the countdown animation had finished by calling the updateTimer function every second, but what exactly are we doing with this updateTimer function?

Let's take a look at the code:

updateTimer:function(){
  // this is called every second so reduce the time left by 1
  this.time --;
  // update the time left label
  this.timeLabel.setString("Time:" + this.time);
 
  // the user's time is up
  if(this.time<= 0)
  {
    // game is now over
    this.isGameOver = true;
    // unschedule the timer
    this.unschedule(this.updateTimer);
    // stop animating the time label
    this.timeLabel.stopAllActions();
    // disable touch
    this.setTouchEnabled(false);
    // disable the pause button
    this.pauseButton.setEnabled(false);
    // display the game over popup
    this.showGameOverPopup();
  }
  else if(this.time == 5)
  {
    // get the user's attention...there are only 5 seconds left
    // make the timer label scale up and down so the user knows the game is about to end
    // use the ease functions to create a heart beat effect
    var timeUp = cc.Sequence.create(cc.EaseSineIn.create(cc.ScaleTo.create(0.125, 1.1)), cc.EaseSineOut.create(cc.ScaleTo.create(0.125, 1)));
    // repeat this action forever
    this.timeLabel.runAction(cc.RepeatForever.create(timeUp));
  }
},

At the start of the function, the time variable is decremented and the respective label's string is updated. Once the time is up, the isGameOver flag is enabled. We don't need the scheduler to call the updateTimer function anymore, so we unschedule it. We disable touch on the GameWorld layer and disable the pause button. Finally, we show a game-over popup.

We add a little more fun into the game by rapidly scaling up and down the time label when there are 5 seconds or less left in the game. Again, the ease actions are used cleverly to create a heartbeat effect. This will not only inform the users that the game is about to end, but also get them to hurry up and score as many points as possible.

This completes the flow of the game. The only thing missing is the pause popup, which is created in the showPausePopup function that gets called when the handler for the pauseButton object is executed. Both the pause and game-over popups contain two or more buttons that serve to restart the game or navigate to the main menu. The logic for creating these popups is pretty simplistic, so we won't spend time going over the details. Also, there are a few cool things to look at in the code for the MainMenu class in the mainmenu.js file. Some liveliness and dynamics have been added to an otherwise static screen. You should refer to your code bundle for the implementation.

Summary

You've learned a lot in this chapter by building ColourSmash. By now, you should be familiar with the structure and relationship of the cc.Scene and cc.Layer. This same structure will be used in the forthcoming projects, both in Cocos2d-html5 and Cocos2d-x.

We also made extensive use of a wide variety of actions, thereby understanding how powerful they make the Cocos2d-x engine. You have also understood the importance of easing while using actions. You learned how to register touches and how to run simple schedulers. There is still a lot to learn and a lot more fun ahead.

Our next game is similar to an extremely famous game that took the world by storm. You're surely in for a treat!

Left arrow icon Right arrow icon

Description

If you are a proficient Cocos2d game developer who wants to enhance his or her game development skill set using Cocos2d-x to build different types of games, this book is for you.

Who is this book for?

If you are a proficient Cocos2d game developer who wants to enhance his or her game development skill set using Cocos2d-x to build different types of games, this book is for you.

What you will learn

  • Take advantage of the open source nature of Cocos2dx by extending the engine to customize and add your own features to it
  • Design games with levelbased and timebased difficulty progression, which are very addictive and keeps users engaged
  • Maximize user interaction by implementing intuitive gestures and tilt controls
  • Implement advanced physics engine features such as PreSolve and PostSolve events
  • Add realism to your game by using a touch event, and use it to control a game
  • Implement circletocircle collision detection in your games
  • Build the same project on multiple platforms, such as Android and Windows, effortlessly
Estimated delivery fee Deliver to Lithuania

Premium delivery 7 - 10 business days

€25.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Jul 27, 2015
Length: 392 pages
Edition : 1st
Language : English
ISBN-13 : 9781783985265
Vendor :
Apple
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Lithuania

Premium delivery 7 - 10 business days

€25.95
(Includes tracking information)

Product Details

Publication date : Jul 27, 2015
Length: 392 pages
Edition : 1st
Language : English
ISBN-13 : 9781783985265
Vendor :
Apple
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 115.97
Cocos2d-x cookbook
€36.99
Cocos2d-X Game Development Blueprints
€41.99
Cocos2d-x by example (update)
€36.99
Total 115.97 Stars icon
Banner background image

Table of Contents

11 Chapters
1. A Colorful Start Chevron down icon Chevron up icon
2. How to Fly a Dragon! Chevron down icon Chevron up icon
3. Not Just a Space Game Chevron down icon Chevron up icon
4. Back to the Drawing Board Chevron down icon Chevron up icon
5. Let's Get Physical! Chevron down icon Chevron up icon
6. Creativity with Textures Chevron down icon Chevron up icon
7. Old is Gold! Chevron down icon Chevron up icon
8. Box2D Meets RUBE Chevron down icon Chevron up icon
9. The Two Towers Chevron down icon Chevron up icon
10. Cross-platform Building Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.2
(5 Ratings)
5 star 40%
4 star 40%
3 star 20%
2 star 0%
1 star 0%
Hugo Oct 12, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is awesome, it teaches me a lot, in an elegant way the author bring so many techniques to make simple clones of many successful mobile games, he has created a very useful introduction to not so simple games like in other books, this book can give you a really good base to make almost any kind of game. Ok could be better if he has used Cocos2d-x v3, but I don't know why he decides to do this in version 2, maybe in the time he has written the book, or he has more confidence in v2, whatever, isn't so difficult to use his techniques in the newest version of the engine, he did not simple show the tools, but he shows how to use the tools and what kind of result the tool makes you achieve. I think this book is the best book for Cocos2d-x, because isn't just introductory, this is a huge step for me as beginner, I really recommend this book!
Amazon Verified review Amazon
Jaime Sierra Silva (Consignment) Sep 08, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is useful for learning to program in framework Cocos2d-html5, many practical examples of game development of all types to see the versatility of programming Cocos2d-x offer games for Android, iOS, Windows Phone 8. Web and also teaches to use various complementary tools for your future developments such as, among others WebStorm and Eclipse. Finally, a book that complements knowledge to develop robust and unrivaled gaming experience for your future customers of your games.It is recommended to have some experience in Cocos2d-x and JavaScript.
Amazon Verified review Amazon
aseem gupta Jul 31, 2015
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
Finally some intermediate-advance level cocos2d-x book has been published.And if you liked "cocos2d-x:by example beginner’s guide", then you will surely love this book more in terms of concepts covered.Giving 4 stars because concepts covered are good otherwise 3 stars.PROS:1. Games covered are not just bare bones like in almost all other books. Author has truly kept in mind that games covered should be having functionality that professional games have like progressive difficulty levels, XML level design for scalability, etc.2. Two basic games(similar to diamond digger saga but basic version and other is flappy birds clone) and rest games covered are either intermediate-advanced or approach to develop them is professional like XML levels, DrawNode API based games, etc3. Thanks for covering XML parsing which is needed for writing levels outside the code otherwise writing levels in arrays is inconvenient.3. How to add progression and difficulty levels is covered in later chapter.4. A big thanks for covering textures programatiCally for cocos2d-x which was used in famous game Tiny Wings. I don’t know Obj-C(cocos2d) because I don’t like it and was being lazy to understand this difficult tutorial at Raywenderlich’s website. Author’s have given link for those tutorials in the book, in case someone wants to see. And yes, this tutorial is difficult for me to understand. And not sure how to port it to v3.x of cocos2d-x because of draw APIs used are of version 2.x.5. I liked the last chapter which is a tower defense game and how XML levels designing and tile map is used. Also, there is no other better place to use fast and forward(scheduler API) than this kind of a game. Tile Based games has endless possibilities and you can have a great start with 2 games covered in the book.CONS:1. Old version of cocos2d-x (v2.2.x) use, so there can be difficulty in porting draw APIs to newer ones. Also, how to handle Box2D in v3.x is slight different but concepts are same. Concepts for touch listeners have changed but i think that won’t be much of a problem for old cocos2d-x programmers.2. I felt 'catapult string' thing missing that is originally present in angry birds game. But concepts of Box2D(like ray casts) are good. And sadly RUBE is paid(trial) software which is used for designing the levels.3. Some APIs are not covered like Parallax API, and few others though they are not required in majority of games.I still have to read the cross platform chapter!This would have been a great resource if cocos2d-x version used was 3.x but it’s must read book for programmers whose prime motto is to learn more concepts.And btw, cocos2d-x v2.x have also helped many programmers to make amazing cocos2d-x games so there is no question on the engine as such but obviously latest version can reduce the pain of writing code at certain places and APIs are somewhat better though engine is overall the same.Hope the book will be updated to latest cocos2d-x version.
Amazon Verified review Amazon
Francis Aug 02, 2015
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
Even though this book is based on Cocos2d-x-2.2.5, its main concepts still apply for the latest 3.7 version. Several game examples are provided that demonstrate the core concepts of cocos2d-x.I am familiar with C++ version of Cocos2d-x, this book focuses on using JavaScript and Cocos2d-html5 in the first couple of chapters which provided me a good understanding of implementing a web based game using Cocos2d-html5.The code is well documented in the book and shown in small snippets to make it easier to understand. The Flappy Bird clone (DragonDash) demonstrates using sprite sheets and building an infinitely long castle in 20 lines of code. The author does a good job at breaking down core gameplay and showing how to implement this in JavaScript.By the chapter 3, the author has moved on to C++ version of the cocos2d-x engine to implement a space invaders type game. Some of the code presented would have to be updated for the latest 3.7 version but this is well documented on the cocos2d-x website. What the chapter does best is to show how to develop a game, the cocos2d-x is just the tool used to build the game.In chapter 5 the author demonstrates the basics of the popular physics engine, Box2D. The code is in C++ and would be familiar to any other implementation of Box2D, which there are many examples on internet.Tile-based games are popular and powerful in that there are many tile based editors that make it easy to develop levels for your game. Chapter 7 demonstrates making a simple platform game using Tiled Map Editor and Cocos2d-x C++.Chapter 8 the author shows how to implement a Angry Birds type game using RUBE, which is an IDE for designing Box2D physics based games, there are several tools like this available that support Cocos2d-x.The last game implemented in Chapter 9 is a tower defense game, which there are many examples on internet for Cococs2d-x. Using XML to describe the properties of the game is very useful and can be applied to many other type of games.The author closes with Chapter 10, Cross-platform building, which shows how to build Android and Windows Phone 8 projects. Some of this information has changed for the latest version of Cocos2d-x and is available on the official Cocos2d-x website.Many commercial games have been written with Cocos2d-x 2.2.x and some are staying with this version because of stability and a large code base. The newer version of Cocos2d-x 3.7 provides support for 3D and so much more. It would be great if the author provided the same detailed game development that highlights the new features in the latest version of Cocos2d-x.
Amazon Verified review Amazon
Jose M. Jul 29, 2015
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
The book would be great, if we were in 2013... I just don't understand why the author had used an older version of the framework. The book is based on Cocos2d-x-2.2.5, last week the 3.7 version was released. The version 3 of cocos is stable, faster, has c++11 support, new data structures, and it is easier. You could port the code but... is that what a customer want to do?
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela