How can I use a background layer in multiple scenes??

How can I share a background layer in multiple scenes? My background layer contains a background image and I do not want to unload and reload it in every scene change. I want it to be untouched and continue although scene changes.
Because I use transitions between scenes and when one scene change to other then background image would same between all scene transition.
So how can i achieve this functionality???

Thanks for any help……

You can use retain and release to share layer.
Use addChild() to add a layer into a scene when needed.

Thanks Minggo,

But you are sure on replace the scenes this layer was not removed…Because When we replace the scene then it removeAllChildren from scene. Then how this layer remain exist while scene replacing??
I have no idea about that so please more specify how to do it???

removeAllChildren just call release for its children, but if you retain the layer in your scene,
it won’t be destroyed, because its reference count is greater than 0.

So what you should do just add the layer into your scene when it enters foreground.

Ok, I will try it.
If I got any problem then let you know.

Hi Minggo,

I put all my efforts to do it but finally I got nothing.
After replacing the scene all children are gone disappear and i saw a blank screen while replacing scene.
So please give me some reference to do this or example or some piece of code to do it
Thank you very much.

Before you replacing scene, you should add the background layer.
May be you should paste your codes.

Code is given below, I just paste only the required function and terms in a flow not the whole code

//This is my AppDelegate.cpp

bool AppDelegate::applicationDidFinishLaunching()
{
LevelManager levelManager = LevelManager::instance;
levelManager~~>loadLevel;
}
//This is my LevelManager.cpp
LevelManager* LevelManager::pinstance = NULL;// initialize pointer
LevelManager* LevelManager::instance
{
if // is it the first call?
{
pinstance = new LevelManager; // create sole instance
}
return pinstance; // address of sole instance
}
void LevelManager::loadLevel
{
CCLog;
CCDirector pDirector = CCDirector::sharedDirector;
CCScene
pscene = StartGame::sceneStartGame;
pDirector~~>runWithScene; //This is my First scene
}
//This is my StartGame.cpp
CCScene
StartGame::sceneStartGame()
{
// ‘scene’ is an autorelease object
CCScene scene = CCScene::node;
// ‘layer’ is an autorelease object
StartGame
StartGamelayer = StartGame::node();
// add layer as a child to scene
scene~~>addChild;
// return the scene
return scene;
}
bool StartGame::init
{
CCLog;
// 1. super init first
if )
{
CCLog;
return false;
}
CCSize windowSize = CCDirector::sharedDirector~~>getWinSize;
CCSprite backImage = CCSprite::spriteWithFile;
backImage~~>setPosition);
this~~>addChild;
this~~>setIsTouchEnabled;
—————
———— //A bit piece of code which work fine
—————
this~~>schedule, 0.5f);
return true;
}
void StartGame::changeScene
{
//CCLog;
this~~>unscheduleAllSelectors;
this~~>stopAllActions;
CCLayer
changeLevelLayer = CCLayer::node;//Here I add a layer as u told me and add a background in this layer
CCSprite backGroundImage = CCSprite::spriteWithFile;
backGroundImage >setPosition);
changeLevelLayer
>addChild;//add a backGroundImage to a newly created layer
this~~>addChild;
CCDirector pDirector = CCDirector::sharedDirector;
CCScene
pscene = HelloWorld::scene;
pDirector~~>replaceScene);//Here scene replaceing where I want a background while transition
}
//This is my HelloWorld.cpp
CCScene
HelloWorld::scene
{
CCLog;
// ‘scene’ is an autorelease object
CCScene scene = CCScene::node;
// ‘layer’ is an autorelease object
HelloWorld
layer = HelloWorld::node;
// add layer as a child to scene
scene~~>addChild;
// return the scene
return scene;
}
bool HelloWorld::init
{
//////////////////////////////
// 1. super init first
if ) )
{
CCLog;
return false;
}
//CCLog;
CCMenuItemImage *pCloseItem = CCMenuItemImage::itemFromNormalImage );
pCloseItem~~>setPosition( ccp(CCDirector::sharedDirector()>getWinSize.width 20, 20) );

// create menu, it’s an autorelease object
CCMenu* pMenu = CCMenu::menuWithItems(pCloseItem, NULL);
pMenu~~>setPosition;
this~~>addChild(pMenu, 1);
this~~>currentLevel = LevelManager::instance~~>levels;
this~~>currentLifes = LevelManager::instance~~>lifes;
this~~>currentScore = LevelManager::instance~~>scores;
this~~>currentBullet = LevelManager::instance~~>bullets;
this~~>batchMaxSize = currentLevel + 1;
//CCLog;
windowSize = CCDirector::sharedDirector~~>getWinSize;
CCSprite *backImage = CCSprite::spriteWithFile;
backImage~~>setPosition);
this~~>addChild(backImage);
this->setIsTouchEnabled(true);
———————
———————
return true;
}

Now I did all things whatever you said, now it’s your turn….Time start now…
Really it’s create a big trouble for me…Now all it in your hands

I don’t see you share layer in multiple scenes, you created a new layer object every time.
What I said like this

// create and run first scene
CCScene *pMyScene = MyScene::node();
CCLayer *pLayer = MyLayer::node(); // layer should add background sprite
pMyScene->setLayer(pLayer);
CCDirector::sharedDirector()->runWithScene(pMyScene);


// replace scene
CCScene *pMyAnotherScene = MyAnotherScene::node();
pScene->setLayer(pMyScene->getLayer());

// setLayer may like this
void xxx::setLayer(CCLayer *pLayer)
{
    if (m_pLayer)
    {
        m_pLayer->release();
    }

    m_pLayer = pLayer;

   if (m_pLayer)
   {
      m_pLayer->retain();
   }
}

Sorry, But What is “m_pLayer” and “pScene” in your code, it is correct or by mistake…….it create confusion for me…
Thanks a Lot…

It is just a simple, not real code.

Minggo Zhang wrote:

It is just a sample, not real code.

Ok, I will check it, then let you know…
But after seeing your code, I think When we replace scenes normally then I saw the same background(share layer)…. but when scenes are replace with transition effect then this layer no more exist…….
Are you Sure this share layer remain exist between first scene about to go and before the second scene come into pictures???

Hello,

I know this is an old thread, but I am having a similar issue. I have a background that I want to share between scenes and I have the following code.

CCScene* MainMenu::scene(Background* bg)
{
    CCLOG("[MainMenu::scene]");

    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();

    // 'layer' is an autorelease object
    MainMenu *layer = MainMenu::create();
    if(bg){
        layer->addBackground(bg);
    } else
        CCLOG("MainMenu::scene bg is NULL");

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

void MainMenu::addBackground(Background* bg)
{
    if(mLayer && mLayer != bg)
        mLayer->release();

    mLayer = bg;

    if(mLayer)
        mLayer->retain();
}

bool MainMenu::init()
{
    //////////////////////////////
    // 1. super init first
    if (!CCLayer::init())
    {
        return false;
    }

    CCLOG("[MainMenu::init]");
    if(mLayer == NULL) {
        mLayer = Background::create();
        mLayer->retain();
    }
        // Segfault here - when switching to a new scene with a passed Background
    this->addChild(mLayer);

        // Rest of init code
}

void MainMenu::menuCallback(CCObject* pSender)
{
    CCLOG("[LevelBase::menuCloseCallback]");
    switch(((CCMenuItemImage*)pSender)->getTag()){
    case START_TAG:
    {
        // TODO start level select.
        removeChild(mLayer);
        CCDirector::sharedDirector()->replaceScene(LevelBase::scene(mLayer));
        break;
    }
    case INFO_TAG: ; break; // TODO start info.
    case EXIT_TAG: CCDirector::sharedDirector()->end();; break;
    }

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

This code is common throughout my scene’s that share the background.

When CCDirector::sharedDirector()->replaceScene(LevelBase::scene(mLayer)); is called, the code gets a segmentation fault in LevelBase::init when trying add the Background layer as a child. Does anyone know why this is happening?

Note: cocos2d-x-2.1.4

Ok, there is a race condition (I think, not sure if its multi threaded or not, but it sometimes worked) doing it the way I said above. Init can be called before addBackground

Instead I am now doing it like this.

CCScene* MainMenu::scene()
{
    CCLOG("[MainMenu::scene]");

    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();

    // 'layer' is an autorelease object
    MainMenu *layer = MainMenu::create();
    layer->setTag(MAIN_LAYER);

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

void MainMenu::addBackground(Background* bg)
{
    CCLOG("[MainMenu::addBackground]");
    if(mLayer && mLayer != bg)
        mLayer->release();

    mLayer = bg;

    if(mLayer == NULL) {
        mLayer = Background::create();
    }
    if(mLayer){
        mLayer->retain();
        mLayer->schedule(schedule_selector(Background::update)); // Need to do it here else the scrolling stops.
        this->addChild(mLayer, -1);
    }
}

void MainMenu::menuCallback(CCObject* pSender)
{
    CCLOG("[LevelBase::menuCloseCallback]");
    switch(((CCMenuItemImage*)pSender)->getTag()){
    case START_TAG:
    {
        // TODO start level select.
        removeChild(mLayer);
        CCScene* lb = LevelBase::scene();
        ((LevelBase*)lb->getChildByTag(MAIN_LAYER))->addBackground(mLayer);
        CCDirector::sharedDirector()->replaceScene(lb);
        break;
    }
    case INFO_TAG: ; break; // TODO start info.
    case EXIT_TAG: CCDirector::sharedDirector()->end();; break;
    }

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

This seems to work nicely, thanks to the OP and Minggo Zhang for helping me out.