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???
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.
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.
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;
CCScenepscene = 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
StartGameStartGamelayer = 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;
CCLayerchangeLevelLayer = 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;
CCScenepscene = 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
HelloWorldlayer = 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) );
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();
}
}
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???
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?
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.