How to Make a Platformer Game with Cocos2D-X

C++ for Game Development

C Cocos2d-X is a cross-platform C++ port of the popular Cocos2d iPhone project.

You may be coming to the Cocos2d-X game engine and therefore C++ from a background in C-based languages such as Objective C, C#, Java and PHP.

This chapter is meant to be a little C++ refresher. It's not meant to be a completely exhaustive tutorial on C++. It is, rather, a quick overview of the primary expressions and statements that make up one of the world's most popular game programming languages.

C++ is a Compiled Language

C++ is a compiled language as opposed to PHP, which is an interpreted language.

A compiled language like C++ requires a compiler, which takes all the code and interprets it into a binary executable file. The executable can be run over and over again without compiling all the code again. This makes compiled languages pretty fast to execute.

An interpreted language like PHP does not require a compiler. Instead, it interprets the code on the fly, every time you run it (unless you cache). This makes interpreted languages inherently a bit slower than compiled languages because the code has to be parsed and translated into binary commands before the commands can be executed.

When you write games, you need all the speed you can get. Hence the popularity of C++ in the game development community.

Headers and Source

C++ uses header files which basically contain the code's interface. They typically end with .h, for example Guitar.h. Header files can also contain forwardly-declared function prototypes and other identifiers a programmer wishes to share amongst source files.

// Guitar.h

// Declare the Guitar class so any source file
// which includes Guitar.h can create Guitar objects.
class Guitar
{
  // The "pluck" function takes a float parameter
  // and returns an int.
  int pluck(float parameter);
}

Source files contain the code's implementation. They usually end with .cpp, like Guitar.cpp. They take all those object interfaces, function prototypes and other declarations and implement them.

// Guitar.cpp:

// Concretely implement the pluck funciton:
int Guitar::pluck(float parameter)
{
  return parameter * 5.0f;
}

Source files are compiled into object files (.obj) and then linked together with a linker into the final binary executable or library.

Writing Comments

There are two ways to write comments in C++. Method one is the C-style block comment enclosed in a forward slash with asterisk tag: /* */:

/*
  Hi, I'm a C-style block comment. I can write
  whatever I want inside this block including
  gibberish:
  
  ^*&%&@%)(!&
   
  Everything will be considered a comment until
  the compiler encounters a closing asterisk
  and forward slash like so:
*/

Method two is the C++ style comment which makes everything on the same line after a double forward slash (//) a comment:

// Hi, I am a comment and will be until the line ends.

int a = 1; // See, everything after the // is a comment.
a = 0;

Declaring Variables

Another fundamental aspect of C++ is that variables must be declared. Consider the following:

// This will give a compilation error because
// "someVar" is an undeclared identifier.
int a = someVar;

// Compiler error: Use of undeclared identifier 'someVar'.

// Now declare the variable and try again.
int someVar = 0;
int a = someVar; // okay

// Once a variable has been declared, it can be used
// again without declaration.
someVar = 7;
a *= someVar;

C is Procedural

C++ came from the C language.

In the C language, one must code in a procedural fashion. This basically means that procedures (aka "functions") are the primary way of logically grouping code.

A function (or procedure) basically contains a series of statements. Think of a statement kind of like a command. Statements end with a semicolon ";".

The following function simply carries out two commands which result in returning the number one:

// doSomething() takes no parameters and returns an integer:
int doSomething()
{
  int x = 1; // statement 1
  return x; // statement 2
}

C++ is Object-Oriented

C++ evolved the C language and added objects. Objects are an incredibly awesome way to code because an object can limit access to its data and functions.

Have you ever seen a bit of code which resembles spaghetti? You try to follow one end of a noodle and it twists, turns and knots its way through the pile. It's difficult to follow.

By limiting access to an object's data and functions, C++ allows a programmer to write de-coupled code. In essence, this straightens out all the spaghetti noodles so one can clearly see the beginning and end of each path.

Objects help you keep your code compartmentalized, modular, flexible and more readable.

A De-coupled C++ Object

Here's an example of a simple Guitar object, which contains one private integer variable representing its number of strings:

// The Guitar object.
// Note that objects are considered classes
// until they are allocated (aka "instantiated").
class Guitar
{
  private:
    int numberOfStrings;

  public:
    Guitar();
    ~Guitar();
    
    int getNumberOfStrings();
    void setTypeOfGuitar(int type);
};

// Declare a few guitar types.
enum
{
  kGuitarTypeClassical = 1,
  kGuitarTypeElectric,
  kGuitarTypeBanjo
};

// This is a constructor.
// It's called when the object is instantiated.
// (Note also that constructors cannot have a return type.)
Guitar::Guitar()
{
  // Always initialize your variables,
  // else they will initially contain random data!
  numberOfStrings = 0;
}

// This is the destructor.
// It's called when the object is deleted.
// (There's nothing for us to do here in this destructor.)
Guitar::~Guitar()
{
}

// Return the number of strings.
int Guitar::getNumberOfStrings()
{
  return numberOfStrings;
}

// Set the type of guitar.
// This is a good example of de-coupled code.
// Whomever calls this code doesn't have to know
// how a type of guitar translates to the number of strings.
// The guitar class is solely responsible for that
// and that's how it should be!
void Guitar::setTypeOfGuitar(int type)
{
  switch( type )
  {
    case kGuitarTypeClassical:
      numberOfStrings = 6;
    break;
    
    case kGuitarTypeElectric:
      numberOfStrings = 6;
    break;

    case kGuitarTypeBanjo:
      numberOfStrings = 5;
    break;
  }
}

// Create the object.
Guitar guitar;

// Give it a type.
guitar.setTypeOfGuitar( kGuitarTypeBanjo );

// How many strings does it have?
// Resulting output:
// 'This guitar has 5 strings.'
std::cout << "This guitar has "
  << guitar->getNumberOfStrings() << " strings.";

Because Guitar's number of strings variable is declared private, only Guitar has the ability to access it. Other objects or functions can still indirectly read the value via the getNumberOfStrings() function.

The power to set Guitar's number of strings variable is solely in the hands of Guitar. Other objects or functions can indirectly set the number of strings via the setTypeOfGuitar() function. However, it's entirely up to Guitar to determine the way this is handled.

That's why the code is considered to be de-coupled: only a Guitar object should know how many strings a Banjo has.

Can you imagine what would happen if Guitar had a setNumberOfStrings() method? Rampant. Utter. Chaos. You might have unwieldy banjos with forty-seven strings!

Readability Considerations

When writing your C++ code, keep in mind to include plenty of top and bottom margin around your functions and other blocks. This will aid your eye when you are scanning the code.

As well, make sure to indent consistently. Again, this will make it more readable, easier on your eyes and easier for others (or your future self) to understand.

One final suggestion is to never make a function longer than you can see on one screen. When functions get too long, they tend to be overly nested and too complicated. Just look for a pattern that you can simplify and make that pattern its own mini function.

Using This->

One common way to name class member variables is with the m_ prefix:

class Something
{
  private:
    int m_count;
};

The point of using m_ is to make it clear when one is accessing a member variable:

void Something::countDown()
{
  // It's pretty clear that m_count is a member variable.
  while( m_count )
  {
    m_count--;
  }
};

However, the above naming convention doesn't help clarify whether a function call is to a member function:

void Something::caller()
{
  // It's not clear whether doSomething is a member function
  doSomething(1.0f);
};

Therefore, some prefer to name member variables without the m_ prefix. Instead, prefix all access to member variables and all calls to member functions with this->. It makes all that code instantly recognizable whether it's to a member or not.

class Something
{
  private:
    int count;
  
  public:
    Something();
    void countDown();
};

Something::Something()
{
  // We know at a glance that "count" is a member variable
  // and countDown() is a member function.
  this->count = 10; this->countDown();
}

Note that prefixing with this-> does not slow down the execution of your program. For example this->countDown() and countDown() are equivalent in execution speed.

As you code, try to think of more ways you can be an "at-a-glance" programmer. You'll score a whole bunch of points with your peers and your future self.

More C++ Resources

So that's all for this little refresher tutorial on C++ for game development. If you are still new to C++, then here's a few more resources to help you learn all about it:

General C++ Tutorials:

Language-specific Tutorials:

Got questions? Leave a comment below. You can also subscribe to be notified when we release new chapters.

Next Chapter >

Comments


Comments
  1. gameProgrammer45

    Gr8 Work !!! I am following all your lessons and waiting for every week to get the indepth with cocos2d-x.
    I was planning to buy the paralxer but does it contains this ebook already? Are you done with the ebook?

    • Nat Weiss

      It does contain the ebook as a PDF. However, it’s only what has been written so far, which is what you see here on the site.

  2. santosh

    For General C++ video tutorials, antirtfm on youtube is quite resourceful.
    In the process of buying paralxer. Thx