Cocos2d-x 由于 ccLayer->schedule(schedule_selector(...), ...) 而崩溃;

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

本文关键字:schedule 由于 崩溃 selector Cocos2d-x ccLayer- gt      更新时间:2023-10-16

我有Android开发背景。几天前,我开始学习Cocos2d-x用于游戏开发。我创建了一个简单的启动屏幕和一些菜单屏幕,但遇到了一些应用程序崩溃的问题。我希望飞溅场景停留3秒钟,然后加载MenuScene。所以我试着用时间表的方法来替换场景。但是我在执行预定任务时崩溃了。以下是我的简单课程;

Splash.h类:

#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;

}

启动屏幕运行,但在3秒后,endSplash方法没有被调用,应用程序崩溃。我从来没有用C/C++编程过。知道我哪里错了吗?还有,有没有什么方法可以像我们在android/ios中那样使用调试器来调试cocos2d-x应用程序?

您可以使用gdb进行调试。

你写那些getInstance方法是为了什么?在大多数情况下,一对create+init就足够了。

也许可以尝试使用CCDirector::sharedDirector()->getScheduler()->scheduleSelector,或者只运行对对象调用某个方法的操作:http://www.cocos2d-x.org/reference/native-cpp/V3.0alpha0/d3/d32/classcocos2d_1_1_call_func.html。管理对象上运行的操作比处理调度程序IMO.更容易

当出现这样的错误时,您可能需要尝试放置一些断言,以检查对象是否已死(如果不是nullptr和retancount,则进行检查)。当然,用调试器运行它,看看爆炸发生在哪里。现在我在你的代码中找不到错误,我稍后会在家里运行它。

所以经过一点调查:

  • CCObject的构造函数应该是私有的(读作:几乎总是必须是)
  • 在CCObject.h中,最好用static_cast-->替换类c的defalt castring,这样可以避免调试选择器数小时
  • 您的代码在VC12下对我有效(但我使用了pushScene而不是replaceScene)-->您使用的是cocos的master分支吗

而不是这个。。。

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

试试这个。。

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

其中delayTime=3或任何值。

使用它将为您的工作

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