Director::getInstance()->replaceScene is doesn't work cocos2d-x v4

I am tring to make splash screen to show “loading…” text before main screen loaded. But replaceScene is doesn’t work and getting no errors, splash screen opened but main scene not loaded. How can I make it work? I am using cocos2d-x v4

#include "SplashScene.h"
#include "HelloWorldScene.h"

USING_NS_CC;

Scene* SplashScene::createScene()
{
    auto scene = Scene::create();
    auto layer = SplashScene::create();
    scene->addChild(layer);
    return scene;
}

// on "init" you need to initialize your instance
bool SplashScene::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
 
    auto backgroundSprite = Sprite::create( "loading-text.png" );
    backgroundSprite->setPosition( Vec2( visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y) );
    
    this->addChild( backgroundSprite );
	 
    SplashScene::GoToMainMenuScene();
    return true;
}

void SplashScene::GoToMainMenuScene()
{
    auto scene = HelloWorld::createScene();
    Director::getInstance()->replaceScene(TransitionFade::create(0.5f, scene, Color3B(0,255,255)));

}

I tried without transition but no change.

I think you are trying to replace scene inside init method. Scene replacing while init method not returned. You should call GoToMainMenuScene after delay:

float delay = 2.0f;
this->scheduleOnce(schedule_selector(SplashScene::GoToMainMenuScene), delay);
1 Like

@ toojuice 's post worked for me

If I use this->scheduleOnce … I am getting following error:

Severity	Code	Description	Project	File	Line	Suppression State
Error	C3867	'SplashScene::GoToMainMenuScene': non-standard syntax; use '&' to create a pointer to member	box2dTest	........\SplashScene.cpp	33	

to fix this error I used & sign before SplashScene::GoToMainMenuScene but this time I am getting

'schedule_selector' identifier not found

I guess replaceScene is not working in v4 so I was using same code in v.3.17

Best not to guess. You have access to the source code, so dig in to it and see why it’s not working. I understand the desire to just copy and paste code to get something working quickly, but understanding why it works would be of significant benefit to you, especially in cases like this where it doesn’t work as you expect.

Did you search for schedule_selector to see if it exists in cocos2d-x v4? If I recall correctly, it’s either deprecated or removed entirely from the code, so don’t use it. Use lambdas instead:

auto* delay = DelayTime::create(2.0f);
auto* func = CallFunc::create([this]() {
    GoToMainMenuScene();
});
this->runAction(Sequence::create(delay, func, nullptr));
1 Like

Thanks I used another approach CallFunc::create and runAction from @ toojuice 's post:

I love to dig source code I already have my own custom mario style camera follow edited class.
but this case is different, v4 transition doc doesnt guide well it almost guide wrong direction, there is no mention about delay requirement or usage.

My posted code doesnt contain schedule_selector its offered by another user hexerror, I was already know that identifier doesnt work somehow deprecated or not so didnt included to code and wrote my approach without delay but I wasnt know delay is required.

If replaceScene doesnt work without delay why we explicitly wrote delay lines?

It doesn’t need a delay, and hexerror already mentioned what was actually wrong:

The remark about the delay may have been a bit misleading though. It’s not that you need a delay, you just need to make sure the scene replacement happens on the next frame. The reason for that is if you try to do the transition while you’re still in the middle of the init() method for the current scene, then the resulting behavior is undefined, given the init() method is not the end of the scene creation process. If you’re not sure what I mean by that, then follow the Scene::init() in a debugger when you create a scene, all the way back to the method where you called Scene:create(), and you’ll see why.

Anyway, you don’t need the 2 second delay, but you do need to wait till the next frame, so a good way to handle it is like this:

scheduleOnce([this](float){
    SplashScene::GoToMainMenuScene();
}, 0, "GO_TO_MENU_SCENE");

Note that this has been the same requirement since v3, so it’s not related to v4, and if it was working for you in v3, then it was most likely pure luck.

Well, actually, i think he needs some delay, in case he wants to show SplashScene. If not, then of course, he can replace scene on first Update cycle.

Oh, that’s a fair point! Now I understand why you added the delay.

I didn’t pay attention to what the surrounding code was doing, and just focused on the scene replace, but yes, it would make perfect sense to add a delay for X amount of time to show the splash screen before replacing it.

@R101
@hexerror

thanks for help

Did this code work on older versions ? Cocos2dx 3.17.2 for instance?

In my game I do those replaceScene calls from update. and it works fine.

I mean:

After initializing the scene, scheduleUpdate()

On update, if it reaches a propper condition to change scene, so call replaceScene()

In these types of situations posting your code is the most helpful thing you can do.

And yea. Scene replacement hasn’t changed.

Is it because you
if ( !Layer::init() )
//and not Scene and your trying to changeing Layer not change Scene <---- is a Layer inint()
{
return false;
}

i’ve never done it this way befor?
i’ve alyawys done scene then getParent() to get root.of the HelloWorld.cpp.

No, it’s not, because if you look at this:

Scene* SplashScene::createScene()
{
    auto scene = Scene::create();
    auto layer = SplashScene::create();
    scene->addChild(layer);
    return scene;
}

You will notice that SplashScene is a layer, although it is perhaps not the most ideal name for that object.

1 Like