Implement the PauseScene using push and pop scene error

Hi every one.
I create a pause scene to display when the player click pause button.
In the HelloWorld class (main scene) i have a static variable to store the main scene

static cocos2d::Scene* scene;

and below is the createScene method

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    //auto scene = Scene::create();
    HelloWorld::scene = Scene::create();
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

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

    // return the scene
    return HelloWorld::scene;
}

When the player click on paused button i push the main scene and show the pause scene

void HelloWorld::menuPauseCallback(cocos2d::Ref* pSender)
{
    Director::getInstance()->pushScene(HelloWorld::scene);
    Director::getInstance()->replaceScene(Pause::createScene());
}

at the pause scene, when the player click the resume button i pop the main scene back

void Pause::menuResumeCallback(Ref* pSender)
{
    Director::getInstance()->popScene();
}

My problem are:
When the player click the resume button the main scene pop out, but the Sprite actions on the main scene not resume. And if i click on the pause button again the application crash.

Any one can help me?

Change your callback to this.

void HelloWorld::menuPauseCallback(cocos2d::Ref* pSender)
{
    Director::getInstance()->pushScene(Pause::createScene());
}

I’ve change the callback as you guide, but it just run on the firt time when I click pause button the pause scene show, and when i click resume button on the Pause scene the main game scene resume.

but after the game resume, i click pause button again, the game crash.

Create pause node instead…

Create a node with all pause staff like resume and quit buttons

If clicked resume , remove the pause node from parent (scene)

No need for new scene…

Give it a try

What’s you’re Pause::createScene() method look like. It shouldn’t crash, and pushing and popping the scene should keep the HelloWorld scene intact. And how are you setting up your callback / touch listeners for the two buttons that call menuPauseCallback and menuResumeCallback?

Below is my Pause::createScene() method

Scene* Pause::createScene()
{
    // 'scene' is an autorelease object
    Scene *scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = Pause::create();

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

    // return the scene
    return scene;
}

and this is the menuResumeCallback method

void Pause::menuResumeCallback(Ref* pSender)
{
    Director::getInstance()->popScene();
}

I don’t have any settings the touch listeners for the two button that call menuPauseCallback and menuResumeCallback.

The button that call menuPauseCallback method was put on the main game Scene, and the button that call the menuResumeCallback method was put on the Pause Scene…

This works for me, not sure what’s causing the crash in your code? Let us know if you solve it using Node overlay or push/pop scene.
.h

class HelloWorld : public cocos2d::Layer {
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    void menuPauseCallback(cocos2d::Ref* pSender);
    CREATE_FUNC(HelloWorld);
};
class Pause : public cocos2d::Layer {
public:
    static cocos2d::Scene* createScene();
    void menuResumeCallback(cocos2d::Ref* pSender);
    CREATE_FUNC(Pause);
};

.cpp

Scene* HelloWorld::createScene() {
    auto scene = Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}
bool HelloWorld::init() {
    if ( !Layer::init() ) { return false; }
    auto mitem = MenuItemFont::create("Pause", CC_CALLBACK_1(HelloWorld::menuPauseCallback, this));
    auto menu = Menu::create(mitem, nullptr);
    menu->setNormalizedPosition(Vec2(.15f,.3f));
    addChild(menu);
    return true;
}
void HelloWorld::menuPauseCallback(Ref* pSender) {
    Director::getInstance()->pushScene(Pause::createScene());
}
Scene* Pause::createScene() {
    auto scene = Scene::create();
    auto layer = Pause::create();
    auto mitem = MenuItemFont::create("Resume", CC_CALLBACK_1(Pause::menuResumeCallback, layer));
    auto menu = Menu::create(mitem, nullptr);
    menu->setNormalizedPosition(Vec2(0.5f,0.4f));
    layer->addChild(menu);
    scene->addChild(layer);
    return scene;
}
void Pause::menuResumeCallback(Ref* pSender) {
    Director::getInstance()->popScene();
}

I still get crash, it strange, the first time when click pause the Pause sence run Ok, but when i resume and then click pause again it crash.

What platform are you running it on? I’m testing on OSX 10.10. I can move the pause button to the same position as resume and click them as fast as my mouse will allow without crash, so I’m not sure what’s up. Try creating a brand new project and see if the code I posted runs well. Unless you post some error logs or something I’m not sure what else to help fix the issue.

What is in your debug log when it crashes?
Have you tried running it on iOS or Mac in Xcode? Xcode can often give useful information about a crash.

Just a guess, but I have seen that behavior before with pushing and popping scenes that was related to memory management. I was accidentally capturing the scene by value in a lambda method… a rookie c++11 mistake :open_mouth: It could be that or a similar memory management issue.

Try commenting out all code in your pushed scene until you just have a basic scene with a layer and a button to pop that scene. If you can then push and pop multiple times successfully, then re-add your scene code little by little to isolate the rogue code that is likely causing your headache. If that does not work, then you need to isolate where in your base scene that pushes the “pushed scene” there is something likely messing with your apps memory creation/destruction.

An easy test is to add a breakpoint in the destructor of the scene that is being pushed (add the destructor if it does not already exist). You want to make sure that the scene you are pushing is being destroyed properly. You can also do a CCLOG(“My Scene:%p”, myPushedScene); to log the pointer of the scene. Then in your init method you can log created scene %p and in your destructor you can add destroyed scene %p.

In Xcode you can also add a symbolic breakpoint for malloc_error_break that might help to reveal more about what is causing the crash.

I am test on the Windows Phone 8.1, and in the main game scene I’ve preload some resources and sound for game.

// preload resources for game
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(kSpriteFile);
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(kSpriteFile2);

    SimpleAudioEngine::getInstance()->preloadBackgroundMusic(KBackGroundSound);
    SimpleAudioEngine::getInstance()->preloadEffect(kApplauseSound);
    SimpleAudioEngine::getInstance()->preloadEffect(kHugeThumbsUpSound);
    SimpleAudioEngine::getInstance()->preloadEffect(kAwsomeSound);
    SimpleAudioEngine::getInstance()->preloadEffect(kCryingSound);
    SimpleAudioEngine::getInstance()->preloadEffect(kBigTearsSound);

I have two spritesheet files, the first one contain the background image and some sptitesheet for the game. and the second file contain buttons sprite frame and sprite for animations.

And in the Pause scene I’ve also preload the two spritesheet files.

// preload resources for game
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(kSpriteFile);
SpriteFrameCache::getInstance()->addSpriteFramesWithFile(kSpriteFile2);

I am also comment my code in the Pause scene, just put simple code to create a simple MenuItemFont button to allow the player to resume the game. It still crash.

Try creating a new scene with a layer and a button to pop the scene.
Try using that new scene as your pause menu. If that one still crashes, then post the code of that scene and I will take a look.

Right now you need to isolate where the problem is coming from. Either scene could contain the issue and unfortunately the information you posted so far does not reveal what the problem might be.

I try to create a new game Test with two simple scene, The HelloWorldSence with two button, a Close button and a Pause button, and the PauseScene with one resume button. I test the game run ok. It not crash.

But i got that simple Pause Scene to my current game, when i resume and then click pause again it crash.

I look the memory information it show Memory: 52 ,64453 MB Peak: 70,42578MB.

The game play without pause and resume it run smoothly. So it difficult to identify the crash.
My laptop is old, so it not support SLAT, so i can’t debug, I just can run the the smartphone to see if the game run or not, and comment code to identify the bug and fix the bug. But this bug is difficult.

If you zip the .h and .cpp files for your main scene and pause scene and then use the button to upload the zip to this forum, I will take a look at them to see if I can find a problem.

from your original post

Director::getInstance()->replaceScene(Pause::createScene());

This line will trash your current scene. just use push and pop,

I comment all code, and then un comment line by line to identify the bug, I recognize that in the code to create the menu buttons for game. It have a MenuItemToggle that I’ve add the the Menu it cause the error. Below is the code to add the menu

//  add a close menu, which is clicked to quit the program
    auto closeItem = MenuItemSprite::create(
        Sprite::createWithSpriteFrameName(kClose),
        Sprite::createWithSpriteFrameName(kClose1),
        CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

    closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
        origin.y + visibleSize.height  - closeItem->getContentSize().height / 2));
    closeItem->setZOrder(1);
    closeItem->setTag(ExitGame);

    // add sound button to allow people option turn on or turn off the sound
    
    auto on = MenuItemSprite::create(
        Sprite::createWithSpriteFrameName(kSoundon),
        Sprite::createWithSpriteFrameName(kSoundon), NULL);
    
    auto off = MenuItemSprite::create(
        Sprite::createWithSpriteFrameName(kSoundoff),
        Sprite::createWithSpriteFrameName(kSoundoff), NULL);

    auto  toggleSoundItem = MenuItemToggle::createWithTarget(this, menu_selector(HelloWorld::menuToggleSoundCallback), on, off, NULL);

    toggleSoundItem->setPosition(Vec2(closeItem->getPosition().x - toggleSoundItem->getContentSize().width - kDistance/2,
        closeItem->getPosition().y));

    toggleSoundItem->setSelectedIndex(soundMode == 1 ? 0 : 1);
    toggleSoundItem->setZOrder(1);

    auto optionItem = MenuItemSprite::create(
        Sprite::createWithSpriteFrameName(kOption),
        Sprite::createWithSpriteFrameName(kOption1),
        CC_CALLBACK_1(HelloWorld::menuOptionCallback, this));

    optionItem->setPosition(Vec2(toggleSoundItem->getPosition().x - optionItem->getContentSize().width - kDistance / 2,
        closeItem->getPosition().y));
    optionItem->setZOrder(1);
    
    // add pause button to allow the player pause the game

    auto pauseItem = MenuItemSprite::create(
        Sprite::createWithSpriteFrameName(kPause),
        Sprite::createWithSpriteFrameName(kPause1), 
        CC_CALLBACK_1(HelloWorld::menuPauseCallback, this));

    pauseItem->setPosition(Vec2(optionItem->getPosition().x - pauseItem->getContentSize().width - kDistance / 2,
        closeItem->getPosition().y));
    pauseItem->setZOrder(1);

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, toggleSoundItem, optionItem, pauseItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 2);

The menuToggleSoundCallback callback method

void HelloWorld::menuToggleSoundCallback(Ref* pSender)
{
    auto pToggleItem = (MenuItemToggle *)(pSender);
    
    if (pToggleItem->getSelectedIndex() == 0) // sound on
    {
        soundMode = 1;
        SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
    }
    else // sound off
    {
        soundMode = 0;
        SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
    }
}

When i click the pause button at second time, it cause crash, when i remove the toggleSoundItem from menu, the pause and resume run ok.

//auto menu = Menu::create(closeItem, toggleSoundItem, optionItem, pauseItem, NULL);
auto menu = Menu::create(closeItem,  optionItem, pauseItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 2);
auto menu = Menu::create(closeItem,  optionItem, pauseItem, NULL);

And one more code that cause error, after I remove the MenuItemToggle, I’ve add a sprite tree.png image that i put to a spritesheet file. When i add this sprite to the the game when I click pause at the second time it also cause crash. Below is the code that I’ve add to the game.

// add the Tree 1
    tree1 = Sprite::createWithSpriteFrameName(kTree);
    tree1->setPosition(Vec2(origin.x + 60 * scaleX, origin.y + visibleSize.height / 2 + kGroundHeight*1.75f*scaleY));
    tree1->setScale(0.65f);
    tree1->setZOrder(2);
    this->addChild(tree1);

The tree1 variable type Sprite that I’ve declare at the HelloWorldScene.h file

cocos2d::Sprite* tree1;

kTree is a constant that is the name of the sprite.
The attach .png file name tree.png is the sprite that i add the the spritesheet file. It 36KB.

I don’t know what happen with this sptite, and what cause crash when i add the MenuItemToggle to the menu

I dont see anything obvious that should be causing a crash.
If you zip your main scene and your pause scene and upload them to this thread, then I will try running them and see if I can reproduce your issue.

Finally I am not use Pause Scene, i using a LayerColor to create a Pause Dialog to show the Pause when the player click on the pause button. I’ve published the game to Windows Phone Store at
https://www.windowsphone.com/en-us/store/app/savethekoala/9005543b-b411-4d3e-8a1d-78b4b92c3df5

I would like to make the water effect to a diamic water stream. But until now i got error when implement the water shader. I’ve post topic at this link How to create Water flow effect?