Как загрузить сцену при анимации спрайта в cocos2d-x?

у меня есть сцена "выбор сцены" и сцена "игра". Однако, когда пользователь нажимает кнопку для запуска игровой сцены, между нажатием и отображением сцены возникает задержка (около 2 секунд или более на старых устройствах). Поэтому я подумал, что должен создать сцену загрузки.

Итак, то, что я делаю прямо сейчас, переходит к моей сцене "загрузки" 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 секунд, пока сцена не загрузится, а затем ее представят..

кто-нибудь знает, как сохранить анимацию спрайта, пока сцена загружается, чтобы она никогда не останавливалась, пока не будет показана сцена "игра"?


Edit:

Я использую 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));

Edit 2:

причина, по которой моя игровая сцена занимает слишком много времени для загрузки, заключается в том, что я загружаю все spritemaps, которые нужны моей сцене:

// 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 ответов


попробуйте это:

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 и попытаться оптимизировать его.


Я не знаю, что cocos2d-x поддерживает это особенно хорошо:

CSLoader загружает сцену в текущий поток, поэтому он блокирует цикл анимации до его завершения.

для достижения гладкой анимации хитрый CSLoader работает, он должен быть переработан либо * для запуска в рабочем потоке - что будет сложно, поскольку (в последний раз, когда я смотрел) любой ref-производный объект будет паниковать, если он не создан в основном потоке cocos. * часто обращаться к Диспетчер / runloop, чтобы разрешить анимацию кадра. Я не смотрел на код cocostudio::CSLoader, чтобы увидеть, насколько он будет поддаваться этому... это, конечно, не похоже на поддержку этого из коробки.

альтернатива, которую может быть трудно достичь, - просто разбить сцену на куски , каждый из которых может быть быстро загружен, поэтому нет заметной задержки загрузки.


Я согласен с тем, что говорит Крис, в частности, разгружая работу или разбивая вещи на куски.

True, Cocos2d-x не предназначен для многопоточности, поэтому вам нужно реализовать update обратный вызов, который выполняет только небольшой объем работы, а затем ждет до следующего runloop, чтобы позволить движку визуализировать.

Я хотел бы помочь вам решить проблемы с загрузкой, но код, который вы показываете, предназначен только для загрузки анимаций, что на самом деле не проблема. Нам нужно увидеть код, который вызывает замедление, чтобы обеспечить некоторые практические решения.