Cocos2d-x Book: Update

moving to version 2.1.5

More changes with the framework! I wanted to add an update to my previous post, this time in relation to version 2.1.5 of Cocos2d-x. I tested the book code with the new version of the framework and everything worked if the steps detailed in this post are followed.

With two exceptions: Victorian Rush Hour and Eskimo. But the fix is minimum: the class Block.cpp should be renamed, or at least the header file should be renamed in Victorian Rush Hour. I renamed the whole thing to BlockSprite, not just the .cpp and .h files but the class as well. Otherwise there is a conflict with another similarly named header.

With Eskimo I had a similar linkage problem, and all Xcode could tell me was that it did not like the overloaded static scene method from GameLayer. So I renamed it to newScene.

It also seems like deep cleans are waaaay more necessary with the new version of Cocos2d-x and XCode. So the shortcut Shift+Option+Command+K is used a lot more this time around.

So if new projects are created with the new framework and the classes and resources files from the book examples are added to the new project, everything should work fine. Remember then to make the necessary changes in AppDelegate and RootViewController. The first should follow the instructions from the rest of this post, the latter should follow the instructions from the book.

[The original post follows…]

As I mentioned before, I wrote a book on Cocos2d-x. That book uses the 2.0.4 version of the framework, which was the latest stable version of the framework when I wrote the book and built the 6 examples used in it. But by the time of publication version 2.1.3 came out. And if you have had any experience with Cocos2d and Cocos2d-x, they loooove to change and rename stuff. So I wanted to add this post to help people who are having problems changing the code to run in the most recent version of the framework.

Most of the changes are done inside one method in AppDelegate.cpp. So I’ll give an example of the code here for that method, with the 2.0.4 version commented out and the newest version below.

Changes to CCFileUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector* pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
 
    pDirector->setOpenGLView(pEGLView);
 
    CCSize screenSize = pEGLView->getFrameSize();
    CCSize designSize = CCSize(320, 480);
 
    pEGLView->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll);
 
    std::vector<std::string> searchPaths;
    if (screenSize.width > 640) {
       	//CCFileUtils::sharedFileUtils()->setResourceDirectory("ipadhd");
       	searchPaths.push_back("ipadhd");
        pDirector->setContentScaleFactor(1280/designSize.width);
    } else if (screenSize.width > 320) {
        //CCFileUtils::sharedFileUtils()->setResourceDirectory("ipad");
        searchPaths.push_back("ipad");
        pDirector->setContentScaleFactor(640/designSize.width);
    } else {
        //CCFileUtils::sharedFileUtils()->setResourceDirectory("iphone");
        searchPaths.push_back("iphone");
        pDirector->setContentScaleFactor(320/designSize.width);
    }
    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
 
    //SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic( CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("background.mp3")); 
    SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(CCFileUtils::sharedFileUtils()->fullPathForFilename("background3.mp3").c_str());
    //SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("button.wav") );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("button.wav").c_str() );
 
    pDirector->setDisplayStats(false);
 
    pDirector->setAnimationInterval(1.0 / 60);
 
    CCScene *pScene = MenuLayer::scene();
 
    pDirector->runWithScene(pScene);
 
    return true;
}

So first, the changes to the way paths are set to different resource folders. The setSearchPaths method from CCFileUtils must receive a vector of strings. Even if only one value is passed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::vector<std::string> searchPaths;
if (screenSize.width > 640) {
	//CCFileUtils::sharedFileUtils()->setResourceDirectory("ipadhd");
	searchPaths.push_back("ipadhd");
	pDirector->setContentScaleFactor(1280/designSize.width);
} else if (screenSize.width > 320) {
	//CCFileUtils::sharedFileUtils()->setResourceDirectory("ipad");
	searchPaths.push_back("ipad");
	pDirector->setContentScaleFactor(640/designSize.width);
} else {
	//CCFileUtils::sharedFileUtils()->setResourceDirectory("iphone");
	searchPaths.push_back("ipadhd");
	pDirector->setContentScaleFactor(320/designSize.width);
}
CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);

You can see how the method can be used to pass a bunch of different folders, and the order in which they are entered into the vector is the order in which the file will be searched for. So pass a vector with folder1, folder2, folder3, and every time you call up a file in your project the framework will look for that file first in folder1, then if it fails it will move on to folder2, and so on.

This allows for different paths being set for different targets, so one for iOS, one for Android, and one for Windows, for instance, as the file structure, particularly in relation to assets may change quite a bit between targets.

The other change is also inside CCFileUtils, and it involves changing the fullPathFromRelativePath method to fullPathForFilename.

1
2
3
4
5
//as it used to be
SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic( CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("background.mp3"));
 
//as it is now
SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(CCFileUtils::sharedFileUtils()->fullPathForFilename("background3.mp3").c_str());

Notice that you need to pass a C string to that method.

Changes to CCNode Property names

In at least two of the games, I refer to some CCNode properties, like the x and y values for position, without using their getters and setters. And these properties also went through a major refactoring. So in the game Victorian Rush Hour this would have to change:

1
2
3
4
5
//as it used to be
m_tPosition.x +=  block->getWidth();
 
//as it is now
m_obPosition.x +=  block->getWidth();

And in the game Rocket Through, the property for rotation was broken down into multiple components:

1
2
3
4
5
//as it used to be
m_fRotation += _vr ;
 
//as it is now
m_fRotationX = m_fRotationY += _vr ;

I hope this helps.

I’ll list here the applicationDidFinishLaunching method for each one of the six games:

Air Hockey

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
    pDirector->setOpenGLView(pEGLView);
 
    CCSize screenSize = pEGLView->getFrameSize();
    CCSize designSize = CCSize(768, 1024);
 
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionExactFit);
 
    std::vector<std::string> searchPaths;
    if (screenSize.width > 768) {
        searchPaths.push_back("hd");
         pDirector->setContentScaleFactor(2);
    } else  {
        searchPaths.push_back("sd");
        pDirector->setContentScaleFactor(1);
    } 
    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
 
 
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("hit.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("score.wav").c_str() );
 
    SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.5f);
    SimpleAudioEngine::sharedEngine()->setEffectsVolume(0.5f);
 
    // turn on display FPS
    pDirector->setDisplayStats(true);
 
    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);
 
    // create a scene. it's an autorelease object
    CCScene *pScene = GameLayer::scene();
 
    // run
    pDirector->runWithScene(pScene);
 
    return true;
}

Sky Defense

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
    pDirector->setOpenGLView(pEGLView);
 
    CCSize screenSize = pEGLView->getFrameSize();
    CCSize designSize = CCSize(2048, 1536);
 
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionExactFit);
 
    std::vector<std::string> searchPaths;
    if (screenSize.height > 768) {
        searchPaths.push_back("ipadhd");
    } else if (screenSize.height > 320) {
        searchPaths.push_back("ipad");
    } else {
        searchPaths.push_back("iphone");
    }
    pDirector->setContentScaleFactor(screenSize.height/designSize.height);
    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
 
 
    SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(CCFileUtils::sharedFileUtils()->fullPathForFilename("background3.mp3").c_str());
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("bombFail.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("bombRelease.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("boom.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("health.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("pew.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("fire_truck.wav").c_str() );
 
    SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.5f);
    SimpleAudioEngine::sharedEngine()->setEffectsVolume(0.5f);
 
 
    // turn on display FPS
    pDirector->setDisplayStats(true);
 
    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);
 
    // create a scene. it's an autorelease object
    CCScene *pScene = GameLayer::scene();
 
    // run
    pDirector->runWithScene(pScene);
 
    return true;
}

Rocket Through

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
    pDirector->setOpenGLView(pEGLView);
 
    CCSize screenSize = pEGLView->getFrameSize();
    CCSize designSize = CCSize(768, 1024);
 
    float screenRatio = screenSize.height / screenSize.width;
 
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionExactFit);
 
    std::vector<std::string> searchPaths;
    if (screenSize.width > 768) {
        searchPaths.push_back("ipadhd");
    } else if (screenSize.width > 320) {
        if (screenRatio >= 1.5f) {
             searchPaths.push_back("iphonehd");
        } else {
             searchPaths.push_back("ipad");
        }
    } else {
        searchPaths.push_back("iphone");
 
    }
    pDirector->setContentScaleFactor(screenSize.height/designSize.height);
    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
 
    SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(CCFileUtils::sharedFileUtils()->fullPathForFilename("background3.mp3").c_str());
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("pickup.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("bombRelease.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("rocket.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("shipBoom.wav").c_str() );
 
    SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.4f);
    SimpleAudioEngine::sharedEngine()->setEffectsVolume(0.5f);
 
 
    // turn on display FPS
    pDirector->setDisplayStats(false);
 
    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);
 
    // create a scene. it's an autorelease object
    CCScene *pScene = GameLayer::scene();
 
    // run
    pDirector->runWithScene(pScene);
 
    return true;
}

Victorian Rush Hour

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
    pDirector->setOpenGLView(pEGLView);
 
    CCSize screenSize = pEGLView->getFrameSize();
    CCSize designSize = CCSize(2048, 1536);
 
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionExactFit);
 
    std::vector<std::string> searchPaths;
    if (screenSize.height > 768) {
        searchPaths.push_back("ipadhd");
        pDirector->setContentScaleFactor(1536/designSize.height);
    } else if (screenSize.height > 320) {
        searchPaths.push_back("ipad");
        pDirector->setContentScaleFactor(768/designSize.height);
    } else {
        searchPaths.push_back("iphone");
        pDirector->setContentScaleFactor(380/designSize.height);
    }
    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
 
 
    SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(CCFileUtils::sharedFileUtils()->fullPathForFilename("background3.mp3").c_str());
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("falling.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("hitBuilding.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("jump.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("crashing.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("start.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("openUmbrella.wav").c_str() );
 
    SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.5f);
    SimpleAudioEngine::sharedEngine()->setEffectsVolume(0.5f);
 
    // turn on display FPS
    pDirector->setDisplayStats(false);
 
    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);
 
    // create a scene. it's an autorelease object
    CCScene *pScene = GameLayer::scene();
 
    // run
    pDirector->runWithScene(pScene);
 
    return true;
}

Mini Pool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
    pDirector->setOpenGLView(pEGLView);
 
    CCSize screenSize = pEGLView->getFrameSize();
    CCSize designSize = CCSize(320, 480);
 
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll);
 
    std::vector<std::string> searchPaths;
    if (screenSize.width > 640) {
        searchPaths.push_back("ipadhd");
        pDirector->setContentScaleFactor(1280/designSize.width);
    } else if (screenSize.width > 320) {
        searchPaths.push_back("ipad");
        pDirector->setContentScaleFactor(640/designSize.width);
    } else {
        searchPaths.push_back("iphone");
        pDirector->setContentScaleFactor(320/designSize.width);
    }
    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
 
 
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("ball.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("drop.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("hit.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("whitedrop.wav").c_str() );
 
 
    // turn on display FPS
    pDirector->setDisplayStats(true);
 
    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);
 
    // create a scene. it's an autorelease object
    CCScene *pScene = GameLayer::scene();
 
    // run
    pDirector->runWithScene(pScene);
 
    return true;
}

Eskimo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
    pDirector->setOpenGLView(pEGLView);
 
    CCSize screenSize = pEGLView->getFrameSize();
    CCSize designSize = CCSize(320, 480);
 
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll);
 
    std::vector<std::string> searchPaths;
 
    if (screenSize.width > 640) {
        searchPaths.push_back("ipadhd");
        pDirector->setContentScaleFactor(1280/designSize.width);
    } else if (screenSize.width > 320) {
        searchPaths.push_back("ipad");
        pDirector->setContentScaleFactor(640/designSize.width);
    } else {
        searchPaths.push_back("iphone");
        pDirector->setContentScaleFactor(320/designSize.width);
    }
    CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
 
 
    SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(CCFileUtils::sharedFileUtils()->fullPathForFilename("background3.mp3").c_str());
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("button.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("cap.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("igloo.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("oops.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("shape.wav").c_str() );
    SimpleAudioEngine::sharedEngine()->preloadEffect( CCFileUtils::sharedFileUtils()->fullPathForFilename("switch.wav").c_str() );
 
    SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.5f);
    SimpleAudioEngine::sharedEngine()->setEffectsVolume(0.5f);
 
    // turn on display FPS
    pDirector->setDisplayStats(true);
 
    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);
 
    // create a scene. it's an autorelease object
    CCScene *pScene = MenuLayer::scene();
 
    // run
    pDirector->runWithScene(pScene);
 
    return true;
}

19 Responses to “Cocos2d-x Book: Update”

  1. Jason said...

    I am trying download the code/resources for the book and It has sent me a link but it doesn’t work

    Can you help me get the code/resources?

  2. Jason said...

    It is a “Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.

  3. zhang said...

    OK,when you login .you can download the code sources,maybe you should select and click about three times to download.
    if you hava any problem,you can send me a email.

  4. si dinh said...

    I am trying download the code for the book and run it but nothing result with error –>
    In EAGLView Incomplete implementation
    Required for direct or indirect protocol ‘UITextInput’

  5. Mikey Aburamadan said...

    I want to purchase your book and I think we are now at version 2.1.4 regarding the newest cocos2d-x framework? Will I be able to follow along or will I run into trouble? Will the code above run in 2.1.4?

  6. roger said...

    So I tested all the book’s source code with 2.1.5 (2.1.4 is no more!) and it all worked. Just make sure to create new projects and then either replace the libs folder in the old project, or, an even safer alternative, move everything related to the game logic to the new project.

  7. Rob Bantin said...

    I keep finding instances of example code checking for a null pointer after a ‘new’ allocation.

    E.g.
    GameSprite* sprite = new GameSprite();

    if (sprite && sprite -> initWithFile(pszFileName)) { …

    If that ‘new’ fails it won’t return a null pointer, it’ll throw a “bad_alloc” exception, and since it’s not being handled the following null check is nonsense. If the program gets that far, that pointer will always be non-zero!

    If you want ‘new’ to return a null pointer on failure (as it did prior to 2003), you need to overload it like this:

    GameSprite* sprite = new(std::nothrow) GameSprite();

    This is discussed in that book you recommend “Professional C++ (Gregiore/Solter/Kleper)”.

  8. Leonard said...

    I’ve been following your book since July. It’s amazing.

    I’m working with cocos 2.1.4, and to migrate the projects what I do is create a new one and copy all the resources and src to the new project. All is working so far.

    I’m a very interested on how you design the art work for your games. I’m trying to learn an easy method for create the assets. I’ll go with vector graphics or pixel art. Which one is the simplest to you?

    Congrats for this excellent book.

  9. Joe said...

    Thanks very much for this book! I’ve been porting your games to android using the 2.2.x cocos framework and my grandson is loving them. Thanks also for this page which is helping me with a few things I couldn’t quite get.

    cheers!

    Joe D

  10. roger said...

    Thanks a lot. Glad you put it to good use then!

  11. siddharth shekar said...

    I am trying to make a hybrid box2d game… it works great on ios/ blackberry but I dont know how to configure for android and I just dont seem to get it to work… could you pls help

  12. roger said...

    Hi. Did you manage to build the hybrid test project following the steps in the book?

  13. annunaki said...

    hey, i was trying to convert the first final/finish project which is skydefense and i can’t seem to convert it. it has an error about GameSprite which can’t be resolved i don’t know why.

    what i did was to create a new proj. for android then i just copied the classes .h and .cpp and then copied the initialization from the appdelegate. am i doing it wrong?

  14. siddharth shekar said...

    I am using version 2.2 now so … Not sure if the steps in the book are still relevant

  15. roger said...

    Are you adding the classes to the make file?

  16. Krake said...

    I purchased this book but I haven’t started to read it yet. Any “cocos2d-x 2.2 book: update” in mind?

    I was also wondering if you are planning to write about Cocos2d-x using C++. I’ve seen you have changed to Lua in your most recent posts, so my real question is… why Lua?

  17. roger said...

    Although the main concepts of the book can still be used and adapted for later versions, the code will not work straight out of the box with recent versions of the framework. Best to wait for a version 3.0 book.
    And I have not “changed” to lua, but I am interested in scripting as a form of data injection for games: levels, boosts and upgrades… that sort of thing. And I prefer Lua to Javascript for that purpose. I hope to post something along those lines soon.

  18. Andrew said...

    Hi

    I am having difficulty with understanding some of the code:

    Using Xcode with the latest COCOS 2d – I cannot find where AppController or RottViewController is if I start the project using the COCOS 2D template. If I search Xcode these files don’t exist

    Should I first create these as Objective C classes?.

    Also the download from Pakt doesn’t work – do you have an alternate link?

    Thank again

  19. roger said...

    Uhmmm.. Packt had some issues with downloading the source, but these have been fixed. You should send them an email. And are you still using the version used in the book?

Leave a Comment