Tuesday, 6 May 2014

Parse JSON file in Coco2dx

I have written a simple wrapper around rapidjson for parsing json file in Cocos2dx-2.3.3. You can not use this wrapper in lower versions of Cocos2dx because they don't have included rapidjon library by default, therefore you have to add rapidjson externally for use.


#ifndef __JSON_READER__
#define __JSON_READER__

#include "cocos2d.h"
#include "cocos-ext.h"

#include <string>


using namespace std;
using namespace rapidjson;

class JsonReader
    static JsonReader* getInstance();
    void read(const char *fileName);
    void purge(void);
    void destroyInstance(void);   
    void moveNext(void);
    int getRowCount(void);
    int getInt(const char* key, int def = 0);
    float getFloat(const char* key, float def = 0.0f);
    string getString(const char* key, const char* def = "");
    bool getBool(const char* key, bool def = false);
    const Value& getSubDict(void);
    static JsonReader* m_pJsonReader;
    Document doc;
    unsigned char* m_pBytes;
    string m_sFileName;
    int m_nRowId;

#include "JsonReader.h"

JsonReader* JsonReader::m_pJsonReader = NULL;

JsonReader::JsonReader() {
    m_pBytes = NULL;
    m_nRowId = -1;

JsonReader::~JsonReader() {

JsonReader* JsonReader::getInstance() {
    if (m_pJsonReader == NULL) {
        m_pJsonReader = new JsonReader();
    return m_pJsonReader;

void JsonReader::read(const char *fileName) {
    unsigned long size = 0;
    m_sFileName = fileName;
    string jsonFile = m_sFileName + ".json";
    string jsonpath = CCFileUtils::sharedFileUtils()->fullPathForFilename(jsonFile.c_str());
    m_pBytes = CCFileUtils::sharedFileUtils()->getFileData(jsonpath.c_str(), "r", &size);
    CCAssert( m_pBytes!= NULL, "JSON file not found");
    CCAssert( strcmp((char*)m_pBytes, "") != 0, "JSON file is empty");
    string load_str((const char*)m_pBytes, size);
    if(doc.HasParseError()) {
        CCLog("Parsing for JSON file failed : %s", jsonFile.c_str());
    CCAssert(!doc.HasParseError(), doc.GetParseError());

void JsonReader::purge(void) {
    if(m_pBytes) {
        delete m_pBytes;
        m_pBytes = NULL;       
        m_nRowId = -1;

void JsonReader::destroyInstance(void) {
    if(m_pJsonReader) {
        delete m_pJsonReader;
        m_pJsonReader = NULL;

void JsonReader::moveNext(void) {   

const Value& JsonReader::getSubDict(void) {
    return DICTOOL->getSubDictionary_json(doc, m_sFileName.c_str(), m_nRowId);

int JsonReader::getRowCount(void) {
    return DICTOOL->getArrayCount_json(doc, m_sFileName.c_str());

int JsonReader::getInt(const char* key, int def /* = 0 */) {
    return DICTOOL->getIntValue_json(getSubDict(), key, def);

float JsonReader::getFloat(const char* key, float def /* = 0.0f */) {
    return DICTOOL->getFloatValue_json(getSubDict(), key, def);

string JsonReader::getString(const char* key, const char* def /* = "" */) {
    return DICTOOL->getStringValue_json(getSubDict(), key, def );

bool JsonReader::getBool(const char* key, bool def /* = false */) {
    return DICTOOL->getBooleanValue_json(getSubDict(), key, def);

Sample JSON file: LEVELS.json

{ "LEVELS" : [ {
        "ID" : 0,
        "LOCK" : false,
        "NAME" : "LEVEL0",
        "SCORE" : 100,
        "SPEED" : 10
      { "ID" : 1,
        "LOCK" : true,
        "NAME" : "LEVEL1",
        "SCORE" : 100,
        "SPEED" : 10
      {"ID" : 2,
        "LOCK" : true,
        "NAME" : "LEVEL2",
        "SCORE" : 100,
        "SPEED" : 10
      {"ID" : 3,
        "LOCK" : true,
        "NAME" : "LEVEL3",
        "SCORE" : 100,
        "SPEED" : 10
      {"ID" : 4,
        "LOCK" : true,
        "NAME" : "LEVEL4",
        "SCORE" : 100,
        "SPEED" : 10
    ] }

Sample function to parse JSON file using JsonReader wrapper class.

void parseJsonFile(void) {
    struct LevelItem {
        int id;
        bool lock;
        int score;
        int velocity;
        std::string name;

        void Print() {
            CCLOG("ID: %d", id);
            CCLOG("LOCK: %s", lock ? "true" : "false");
            CCLOG("SCORE: %d", score);
            CCLOG("VELOCITY: %d", velocity);
            CCLOG("NAME: %s", name.c_str());

    JsonReader* pReader = JsonReader::getInstance();

    int rows = pReader->getRowCount();
    for (int i = 0; i < rows; i++) {

        LevelItem* pLevelItem = new LevelItem();
        pLevelItem->id = pReader->getInt("ID");
        pLevelItem->lock = pReader->getBool("LOCK");
        pLevelItem->score = pReader->getInt("SCORE");
        pLevelItem->velocity = pReader->getInt("VELOCITY");
        pLevelItem->name = pReader->getString("NAME");


Sunday, 13 April 2014

Run Cocos2dx Android Project on Windows

I assume you have already created Android project using template provided with Cocos2dx and imported it in your Eclipse workspace using from existing Android project option and converted it to C/C++ nature.

Also I assume you have installed Android NDK and set up correct path in Eclipse and your workspace location is Cocos2dx default directory.

Note:This method does not require either cygwin or python to run Android project on Windows.

Software's: Cocos2d-x-2.2.2, Windows 8.1 64-Bit and Eclipse 4.4

Step 1: Add Environment Variables

Go to Eclipse -> Window -> Preferences -> C/C++ -> Build -> Environment

And add NDK_ROOT and NDK_MODULE_PATH in Environment variables:


* Note:
If you are using version Cocos2dx-2.2.3 then you don't need to add path for prebuilt modules in NDK_MODULE_PATH. You can only use path F:\Coco2dx\cocos2d-x-2.2.3;

Step 2: Link Resources

Now in your project you have to link your Resources and Classes folders to your eclipse project:

You have to create two folder link named classes and assets If assets folder already exist then delete and recreate it.

To create folder link :
Select Project -> Right Click -> New -> Folder -> Advanced

Linking Classes :
Type classes in folder name and select Link to alternate location (Linked Folder) and type PARENT-1-PROJECT_LOC/Classes

Linking Resources :
Type assets in folder name and select Link to alternate location (Linked Folder) and type PARENT-1-PROJECT_LOC/Resources

Step 3: Setting  C/C++ Builder

Select Project -> Right-Click -> Properties -> C/C++ Build -> Builder-Settings
Uncheck Use default build command option and enter ndk-build.cmd in Build-Command and then click Apply and then click Ok. 

Now eclipse will start building your whole Cocos2dx Android project.

This method build projects faster than Cygwin because Cygwin runs under emulated environment and usually it takes longer time to copy resources to assets directory when you build and run your projects.

Monday, 20 January 2014

Handle back key event in Cocos2dx 2.2.2 Windows Phone 8 XAML and C++

Cocos2d-x-2.2.2 version has introduced new project template based on XAML and C++ Component  for Windows Phone 8 platform which allows you to develop games with C# and C++ mixed. You can use XAML components using this template but it's missing BACK key event handling which is primary key for Windows Phone application navigation. However there is a work around which allows you to handle BACK key in your C++ Component based game.

Open CocosRenderer.cpp and change the OnBackKeyPress() method as following:

bool Cocos2dRenderer::OnBackKeyPress()
    //return false;
    return true;

You can override virtual void keyBackClicked();  method in your Game Layer and handle back key event.