
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][1].
### 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][2] 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][3], one must code in a [procedural][4] 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][5]. 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][6] 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:
[1]: //gamedev.stackexchange.com/questions/11069/competing-with-c-for-games-programming
[2]: //en.wikipedia.org/wiki/Header_file
[3]: //en.wikipedia.org/wiki/C_syntax
[4]: //en.wikipedia.org/wiki/Procedural_programming
[5]: //www.cplusplus.com/doc/tutorial/classes/
[6]: //en.wikipedia.org/wiki/Coupling_(computer_science)
[7]: /cocos2d-x-tutorial/