Search code examples
cocos2d-iphonecocos2d-x

Adding another layer to the scene in the HelloWorld project


In the cocos2d-x HelloWorld project, I am trying to add another layer to the scene and keep a reference to this layer in a data member. Since the function HelloWorld::scene() is static, I cannot add the layer within this function (because I cannot set the data member for the layer).

So I tried getting the scene in the init() function as follows, however this leads to scene = 0x00000000.

What am I doing wrong?

bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {
        CC_BREAK_IF(! CCLayer::init());

        CCScene* scene = NULL;
        scene = CCDirector::sharedDirector()->getRunningScene();

        // add another layer
        HelloWorldHud* layerHud = HelloWorldHud::create();
        CC_BREAK_IF(! layerHud);
        // set data member
        this->layerHud = layerHud;

        // next line crashes (because scene  is 0x00000000)
        scene->addChild(layerHud);

    bRet = true;
    } while (0);
    return bRet;
}

PS: The reason that I want to add the hud layer to the scene, rather than to the current layer, is because I am moving the current layer around and do not want the hud layer to be moved with it.


Edit: Since the accepted answer allowed for multiple options, here's what I did to fix the problem:

1.) Removed the HUD layer from the init() function:

bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {
        CC_BREAK_IF(! CCLayer::init());

    bRet = true;
    } while (0);
    return bRet;
}

2.) And instead added the HUD layer to the scene function (which also is the way its done in cocos2d-iphone):

CCScene* HelloWorld::scene()
{
    CCScene * scene = NULL;
    do 
    {
        // scene
        scene = CCScene::create();
        CC_BREAK_IF(! scene);

        // HelloWorld layer
        HelloWorld *layer = HelloWorld::create();
        CC_BREAK_IF(! layer);
        scene->addChild(layer);

        // HUD layer
        HelloWorldHud* layerHud = HelloWorldHud::create();
        CC_BREAK_IF(! layerHud);
        scene->addChild(layerHud);

        // set data member
        layer->layerHud = layerHud;

    } while (0);

    // return the scene
    return scene;
}

Essentially the problem was that my assumption, "Since the function HelloWorld::scene() is static, I cannot add the layer within this function (because I cannot set the data member for the layer).", was wrong.


Solution

  • The scene is NULL because you call getRunningScene() even before the first scene is constructed.

    And one of your assumption is wrong. HelloWorld::scene() is static, but you still can add the layer within this function (and you can set the data member for the layer)

    the correct way is to create a new public function

    setLeyerHud(HelloWorldHud* hud);
    

    in HelloWorld Class and in the CCScene* HelloWorld::scene() function, add the following lines:

    CCScene * scene = NULL;
    do 
    {
        // 'scene' is an autorelease object
        scene = CCScene::create();
        CC_BREAK_IF(! scene);
    
        // 'layer' is an autorelease object
        HelloWorld *layer = HelloWorld::create();
        CC_BREAK_IF(! layer);
    
        HelloWorldHud* layerHud = HelloWorldHud::create();
        CC_BREAK_IF(! layerHud);
    
        scene->addChild(layer);
    
        scene->addChild(layerHud);
    
        layer->setLayerHud(layerHud);
    
    } while (0);
    

    it depends on weather you want to add the Hud into the HelloWorld Layer or you want to add to the scene.

    I. add new layer to the scene:

    remove code

        CCScene* scene = NULL;
        scene = CCDirector::sharedDirector()->getRunningScene();
    
        // add another layer
        HelloWorldHud* layerHud = HelloWorldHud::create();
        CC_BREAK_IF(! layerHud);
        // set data member
        this->layerHud = layerHud;
    
        // next line crashes (because scene  is 0x00000000)
        scene->addChild(layerHud);
    

    from

    HelloWorld::init()
    

    and change code in

    CCScene* HelloWorld::scene()
    

    to

    CCScene * scene = NULL;
    do 
    {
        // 'scene' is an autorelease object
        scene = CCScene::create();
        CC_BREAK_IF(! scene);
    
        // 'layer' is an autorelease object
        HelloWorld *layer = HelloWorld::create();
        CC_BREAK_IF(! layer);
    
        HelloWorldHud* layerHud = HelloWorldHud::create();
        CC_BREAK_IF(! layerHud);
    
        scene->addChild(layer);
    
        scene->addChild(layerHud);
    } while (0);
    
    // return the scene
    return scene;
    

    II. add new layer to the HelloWorld Layer:

    change the code

        CCScene* scene = NULL;
        scene = CCDirector::sharedDirector()->getRunningScene();
    
        // add another layer
        HelloWorldHud* layerHud = HelloWorldHud::create();
        CC_BREAK_IF(! layerHud);
        // set data member
        this->layerHud = layerHud;
    
        // next line crashes (because scene  is 0x00000000)
        scene->addChild(layerHud);
    

    in

    HelloWorld::init()
    

    to

        // add another layer
        HelloWorldHud* layerHud = HelloWorldHud::create();
        CC_BREAK_IF(! layerHud);
    
        // next line crashes (because scene  is 0x00000000)
        this->addChild(layerHud);