如何在cocos2d-x中设置精灵动画时加载场景?

时间:2015-09-14 04:42:13

标签: c++ cocos2d-x cocos2d-x-3.0

我有一个"舞台选择"场景和游戏"现场。然而,当用户按下按钮以开始游戏场景时,在按下和场景显示之间存在延迟(在旧设备上大约2秒或更多)。所以我认为我应该创建一个加载场景。

所以我现在正在做的是转到我的'#34; Loading"场景a std :: function 在加载场景出现后0.1秒被调用。这个函数有代码来启动"游戏"像这样的场景:

用于创建加载场景。

auto loading_scene = LoadingScene::createLoadingScene([stage_course]() {

    Director::getInstance()->replaceScene(Game::createScene(stage_course->course_id));

});

Director::getInstance()->replaceScene(loading_scene);

加载游戏场景。

void LoadingScene::onEnter()
{
    Node::onEnter();

    call_after(0.1, callback_start);  
}

这样的结果是加载场景显示了一个正在运行的字符的简单动画精灵。起初我尝试在回调之前延迟1.0秒来检查精灵是否正常工作(确实如此,角色运行)。但是当执行回调时(加载新场景的那个)它会停止移动,并且在场景加载然后呈现之前保持这样大约1-2秒......

有人知道如何在场景加载时保持精灵的动画效果,这样它就不会停止运行直到#34;游戏"现场显示?

编辑:

我使用的是cocos2d-x-3.8。

我的加载场景在其init函数中有以下代码,用于创建用于为尖顶设置动画的动画:

// Create the sprite animation
Animation *animation = Animation::create();
for (int i = 0; i < INT16_MAX; i++)
{
    string frame_sprite_name = StringUtils::format("Interface/loading/0_%d.png",i);

    auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(frame_sprite_name);

    if (frame) {
        animation->addSpriteFrame(frame);
    } else {
        break;
    }
}

animation->setDelayPerUnit(0.15f);


Animate *animate = Animate::create(animation);


// Create a temporal sprite to run the animation

auto temp_sprite = Sprite::create();

temp_sprite->setAnchorPoint(Vec2(0.5,0.5));
temp_sprite->setPosition(Vec2(DISPLAY_WIDTH/2.0f,DISPLAY_HEIGHT/2.0f));


this->addChild(temp_sprite);

temp_sprite->runAction(RepeatForever::create(animate));

编辑2:

我的游戏场景需要花费太多时间才能加载的原因是因为我正在加载我的舞台需要的所有精灵图像:

// Shared

if (!SpriteFrameCache::getInstance()->isSpriteFramesWithFileLoaded(STUDENTS_SPRITE_MAP)) {
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(STUDENTS_SPRITE_MAP);
}

if (!SpriteFrameCache::getInstance()->isSpriteFramesWithFileLoaded(OTHERS_SPRITE_MAP)) {
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(OTHERS_SPRITE_MAP);
}

if (!SpriteFrameCache::getInstance()->isSpriteFramesWithFileLoaded(INTERFACE_SPRITE_MAP)) {
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(INTERFACE_SPRITE_MAP);
}

if (!SpriteFrameCache::getInstance()->isSpriteFramesWithFileLoaded(ZOMBIES_SPRITE_MAP)) {
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(ZOMBIES_SPRITE_MAP);
}

if (!SpriteFrameCache::getInstance()->isSpriteFramesWithFileLoaded(PORTRAITS_SPRITE_MAP)) {
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(PORTRAITS_SPRITE_MAP);
}

if (!SpriteFrameCache::getInstance()->isSpriteFramesWithFileLoaded(CUTS_SPRITE_MAP)) {
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(CUTS_SPRITE_MAP);
}

// Exclusive

if (!SpriteFrameCache::getInstance()->isSpriteFramesWithFileLoaded(TEACHERS_SPRITE_MAP)) {
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(TEACHERS_SPRITE_MAP);
}

3 个答案:

答案 0 :(得分:4)

试试这个:

void HelloWorld::loadTextures1(){
    Director::getInstance()->getTextureCache()->addImageAsync("sprites1.png", CC_CALLBACK_1(HelloWorld::loadTextures2, this));
}

void HelloWorld::loadTextures2(Texture2D* texture1){
    this->texture1 = texture1;
    CCLOG("Texture 1 loaded!");
    Director::getInstance()->getTextureCache()->addImageAsync("sprites2.png", CC_CALLBACK_1(HelloWorld::loadTextures3, this));
}


void HelloWorld::loadTextures3(Texture2D* texture2){
    this->texture2 = texture2;
    CCLOG("Texture 2 loaded!");
    Director::getInstance()->getTextureCache()->addImageAsync("sprites3.png", CC_CALLBACK_1(HelloWorld::allTexturesLoaded, this));
}

void HelloWorld::allTexturesLoaded(Texture2D* texture3){
    this->texture3 = texture3;
    CCLOG("Texture 3 loaded!");

    auto cache = SpriteFrameCache::getInstance();

    cache->addSpriteFramesWithFile("sprites1.plist", texture1);
    cache->addSpriteFramesWithFile("sprites2.plist", texture2);
    cache->addSpriteFramesWithFile("sprites3.plist", texture3);

    auto scene = GameScene::createScene();
    Director::getInstance()->replaceScene(TransitionShrinkGrow::create(.5, scene));
}

它异步加载这3个纹理,然后用预加载的纹理同步加载plist文件。最后有一点冻结(同步部分),但我认为它还不错。您也可以深入研究SpriteFrameCache并尝试对其进行优化。

答案 1 :(得分:1)

我不知道cocos2d-x特别支持这个:

CSLoader在当前线程上加载场景,因此它会阻止动画循环直到完成。

为了实现CSLoader工作的平滑动画,它也需要重构 *在一个工作线程中运行 - 这将是很难(因为我上次看)任何Ref派生对象如果不在主cocos线程上创建就会发生恐慌。 *经常调用Dispatcher / runloop以允许框架动画。我没有看过cocostudio :: CSLoader代码,看看它对于它有多么合适......它似乎并不支持这个方法。

可能难以实现的替代方案是简单地将场景分解为块 - 每个块都可以快速加载,因此没有明显的负载延迟。

答案 2 :(得分:1)

我同意克里斯所说的话,特别是卸载工作或将事情分解成块。

没错,Cocos2d-x不是为多线程而设计的,所以你需要实现一个只进行少量工作的update回调,然后等到下一个runloop到允许引擎渲染。

我希望我可以帮助您解决加载问题,但您展示的代码仅用于加载动画,这不是真正的问题。我们需要看到导致速度减慢的代码提供一些实用的解决方案。