Как загрузить сцену при анимации спрайта в 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, чтобы позволить движку визуализировать.
Я хотел бы помочь вам решить проблемы с загрузкой, но код, который вы показываете, предназначен только для загрузки анимаций, что на самом деле не проблема. Нам нужно увидеть код, который вызывает замедление, чтобы обеспечить некоторые практические решения.