Cocos2d-x crash due to ccLayer->schedule(schedule_selector(...), ...);

1.8k views Asked by At

I have Android development background. A few days ago, I started to learn Cocos2d-x for game development. I was creating a simple splash screen and some menu screen but got stuck on some app crash issue. I want Splash Scene to stay for 3 seconds and to load MenuScene after that. So I tried to use schedule method to replace the scenes. But I am getting crash when it comes to execute the scheduled task. Here are my simple classes;

Splash.h class:

#ifndef SPLASHSCREEN_H_
#define SPLASHSCREEN_H_

#include <layers_scenes_transitions_nodes/CCLayer.h>
#include <cocos2d.h>

/**
 * Splash Screen for the game
 *
 */

USING_NS_CC;

class SplashScreen: public cocos2d::CCLayer {
public:
    SplashScreen();
    virtual ~SplashScreen();
    virtual bool init();
    static cocos2d::CCScene* newInstance();
    void endSplash(float dt);

    // implement the "static node()" method manually
    CREATE_FUNC(SplashScreen);


};

#endif

SplashScreen.cpp:

    #define COCOS2D_DEBUG 1

#include "SplashScreen.h"
#include "GeneralMenuScreen.h"


USING_NS_CC;

SplashScreen::SplashScreen() {
    // TODO Auto-generated constructor stub

}

SplashScreen::~SplashScreen() {
    // TODO Auto-generated destructor stub
}

bool SplashScreen::init() {

    if(! CCLayer::init() ) {
        return false;
    }
    CCSize windowSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    CCSprite* background = CCSprite::create("background.png");
    background->setPosition(ccp(origin.x + windowSize.width/2, origin.y + windowSize.height/2));
    this->addChild(background);

    CCLabelTTF* loadingText = CCLabelTTF::create("Loading...", "Arial", 36);
    loadingText->setAnchorPoint(ccp(0,0));
    loadingText->setPosition(ccp(origin.x + windowSize.width/2 - loadingText->getContentSize().width/2, origin.y + windowSize.height/2 - loadingText->getContentSize().height/2));
    this->addChild(loadingText);

    /*  this->schedule(schedule_selector(SplashScreen::endSplash), 5.0);        */
CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(SplashScreen::endSplash), this , 5, false, 0, 0 );

/*   CCTimer* ccTimer = CCTimer::timerWithTarget(this, schedule_selector(SplashScreen::endSplash), 5.0f);
ccTimer->update(1.0);       */


/* CCDelayTime* startDelay = CCDelayTime::create(5.0);
CCCallFunc *showHearts = CCCallFunc::create(this, callfunc_selector(SplashScreen::endSplash));
CCSequence* seq = CCSequence::create(startDelay, showHearts);
background->runAction(seq);*/

    return true;

}


CCScene* SplashScreen::newInstance() {

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

    // 'layer' is an autorelease object
    SplashScreen* splashScreen = SplashScreen::create();

    scene->addChild(splashScreen);

    return scene;

}

void SplashScreen::endSplash(float dt) {

    //CCLOG("FilePath = %f", dt);
    CCScene* menuScreen = GeneralMenuScreen::newInstance();
    CCDirector::sharedDirector()->replaceScene(menuScreen);

}

GeneralMenuScreen.cpp:

#include "GeneralMenuScreen.h"

USING_NS_CC;

GeneralMenuScreen::GeneralMenuScreen() {

}

GeneralMenuScreen::~GeneralMenuScreen() {

}

CCScene* GeneralMenuScreen::newInstance() {

    CCScene* scene = CCScene::create();
    GeneralMenuScreen* layer = GeneralMenuScreen::create();
    scene->addChild(layer);

    return scene;

}

bool GeneralMenuScreen::init() {

    if( ! CCLayer::init()) {
        return false;
    }

    CCSize windowSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    CCSprite* background = CCSprite::create("background.png");
    background->setPosition(ccp(origin.x + windowSize.width/2, origin.y + windowSize.height/2));
    this->addChild(background);

    int margin = 10;

    CCLabelTTF* playLabel = CCLabelTTF::create("PLAY", "Arial", 36);
    CCMenuItemLabel* menuPlay = CCMenuItemLabel::create(playLabel);
    menuPlay->setPosition(origin.x + windowSize.width/2 - menuPlay->getContentSize().width/2, origin.y + windowSize.height/2 + menuPlay->getContentSize().height + margin/2 );

    CCMenu* menu = CCMenu::create(menuPlay);
    menu->setPosition(CCPointZero);
    this->addChild(menu);


    return true;


}

The splash screen runs but after 3 secods, the endSplash method is not being called and app crashed. I have never programmed in C/C++. Any idea where I am going wrong? And also, is there any way to debug the cocos2d-x apps using some debugger like we have in android/ios?

4

There are 4 answers

3
kuhar On BEST ANSWER

You can use gdb for debugging.

What are you writing those getInstance methods for? Pair of create + init should suffice in most cases.

Maybe try using CCDirector::sharedDirector()->getScheduler()->scheduleSelector or just run action calling some method on your object: http://www.cocos2d-x.org/reference/native-cpp/V3.0alpha0/d3/d32/classcocos2d_1_1_call_func.html . It is easier to manager actions running on your objects than to deal with a scheduler IMO.

When having such errors you may want to try placing some asserts checking if objects aren't dead (check if not nullptr and retaincount). And off course run it with debugger to see where the explosion happens. Right now I cannot find errors in your code, I'll try to run it later at home.

0
kuhar On

So after a little investigation:

  • constructor of a CCObject should be private (read as: pretty much always must be)
  • in CCObject.h it is a good idea to replace defualt c-like castring with static_cast --> you'll avoid many hours of debugging selectors
  • your code works for me under VC12 (but I used pushScene instead of replaceScene) --> are you using master branch of cocos?
0
Jain On

Instead of this...

CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(SplashScreen::endSplash), this , 5, false, 0, 0 );

Try this..

this->scheduleOnce(schedule_selector(SplashScreen::endSplash),delayTime);

where delayTime =3 or anything.

2
Singhak On

Use this it will work for you

schedule(SEL_SCHEDULE(&SplashScreen::endSplash), 5);