0

В моей игре я должен изменить фон сцены во время игрового процесса. Когда я устанавливаю новую текстуру для фона, игра на мгновение замедляется. Чтобы избежать этого, я пытаюсь предварительно загрузить текстуру асинхронно, а затем показать ее в основном потоке. Это, как я могу это сделать:Невозможно отобразить текстуру, загруженную асинхронно

NSString *filename = [NSString stringWithFormat:@"res/src/level_%i/background.png", [GameLevel sharedGameLevel].currentLevelIndex + 1]; 
__block CCTexture2D *texture; 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    NSLog(@"FILENAME %@", filename); 
    [[CCTextureCache sharedTextureCache] addImage:filename]; 
    NSLog(@"%@", [CCTextureCache sharedTextureCache]); 

    dispatch_async(dispatch_get_main_queue(), ^{ 

     texture = [[CCTextureCache sharedTextureCache] textureForKey:filename]; 

     [spareBackground setTexture:texture]; 

     [dayBackground runAction:[CCSequence actions:fadeOut,[CCCallBlockN actionWithBlock:^(CCNode *node) 
     { 
      NSLog(@" TEXTURE %@", texture); 
      [dayBackground setTexture:texture]; 
      CCFadeIn *fadeIn = [[[CCFadeIn alloc] initWithDuration:5] autorelease]; 
      [dayBackground runAction:fadeIn]; 
     }], nil]];  

    }); 
}); 

но вместо фона я всегда получаю пустой экран, несмотря на текстуру была успешно загружена, это не nil. Этот код отлично работает, если текстура загружается в основной поток без использования gcd. Что мне не хватает?

+0

Все ваши NSLogs до последнего показывают ожидаемые результаты? – sergio

+0

и как насчет 'запасного фонда' против' dayBackground'? Что ты пытаешься сделать? оба назначения производят черную текстуру? – sergio

+0

@sergio все NSLogs показывают, что я ожидаю увидеть. запасная площадка просто лежит под днем. да, оба пустые –

ответ

1

Мой подозреваемый в том, что CCTextureCache не является потокобезопасным (и, будучи общими объектами, он должен быть потокобезопасным для безопасного вызова из другого потока).

Cocos2d, с другой стороны, уже предоставляет механизм для загрузки текстуры асинхронно, поэтому вы можете использовать их вместо этого. Это должно быть подпись:

[[CCTextureCache sharedTextureCache] addImageAsync:filename target:self selector:@selector(textureLoaded:)]; 
+0

, к сожалению addImageAsync замедляет основной поток, а также –

+0

, вероятно, для правильного управления кешем ... –

+1

@ Андрей Чернуха: ну, каждая задача, которую вы запускаете на том же самом процессоре, что и основной поток, замедляет основной поток. Если вы посмотрите на реализацию 'addImageAsync', вы увидите, что он просто загружает изображение в отдельный поток (но он делает это поточно-безопасным способом). нет оснований полагать, что создание потока CGD было бы очень различным (за исключением затрат на обработку поточной безопасности). – sergio

0

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

Кроме того, я обнаружил, что загрузка текстур pvr вместо png будет выполняться значительно быстрее (т. Е. Потребляет меньше процессора, я думаю). Вы можете попробовать это как первую попытку - надеясь, что «пауза» будет приемлемой с точки зрения пользователя.

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

Смежные вопросы