Загрузка экранов в играх (чтобы анимация не заикалась во время перехода) - PullRequest
3 голосов
/ 01 марта 2011

У меня есть игра cocos2d, она работает со скоростью 55–60 кадров в секунду после загрузки и запуска игры.

Однако из-за использования листов спрайтов как для моего меню, так и для игры (по одному для каждого), при загрузке игры возникла точка пересечения, которая вызвала бы предупреждения памяти, из-за слишком большого количества больших png, загруженных в память.

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

Это прекрасно работает. Тем не менее, я столкнулся с небольшим дорожным блоком, на моем экране загрузки у меня вращается главный персонаж рядом со словом загрузки (чтобы показать, что что-то происходит).

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

Однако, 5-6 / 10 раз, я получаю это сообщение об ошибке.

 Received memory warning. Level=1
 *** -[NSLock dealloc]: lock (<NSLock: 0x3ded70> '(null)') deallocated while still in use
  *** Break on _NSLockError() to debug.
  *** -[CFDictionary setObject:forKey:]: message sent to deallocated instance 0x3decc0

Я использую этот код для загрузки своей игры.

Внутри кнопки -

NSThread* thread = [[[NSThread alloc] initWithTarget:self selector:@selector(goToNextScene) object:nil] autorelease];
[thread start];

Метод, выполненный в новом потоке -

-(void) goToNextScene {

NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];

EAGLContext *k_context = [[[EAGLContext alloc]
                           initWithAPI :kEAGLRenderingAPIOpenGLES1
                           sharegroup:[[[[CCDirector sharedDirector] openGLView] context] sharegroup]] autorelease];
[EAGLContext setCurrentContext:k_context];

CCScene *gs = [GameEngine scene];

[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:0.5 scene:gs]];

[autoreleasepool release];

}

Есть идеи о том, как я могу предотвратить то, что происходит?

NSLock вызывается, когда gameScene пытается загрузить список gamesheet.plist (имена отдельных изображений в пределах спрайт-листа и координат)

1 Ответ

2 голосов
/ 04 марта 2011

Вы сами правильно его диагностировали, хотя это не CCSpriteFrameCache, который обрабатывается, а CCTextureCache, на который он опирается.

Если вы создали свой проект из шаблона cocos2d по умолчанию, ваш представитель приложения отвечает на applicationDidReceiveMemoryWarning, вызывая [[CCDirector sharedDirector] purgeCachedData].Это в свою очередь вызывает [CCTextureCache purgeSharedTextureCache], которая освобождает и обнуляет общий кеш.Это происходит в главном потоке приложения, и поскольку ваш фоновый поток использует тот же кеш для хранения текстур, которые он загружает ... boom.

Самое простое решение - просто удалить этот вызов purgeCachedData изВаше приложение делегат.Вы понимаете, что потребление памяти вашим приложением лучше, чем ОС, поэтому вместо того, чтобы ОС сообщала вам, когда нужно очищать кэш, делайте это сами: вызывайте purgeCachedData только тогда, когда вы знаете, что у вас есть кэшированные текстуры, которые вы больше не будете использовать.

Из вашего краткого описания это звучит так, как если бы вы делали это в начале сцены перехода / загрузки.Обязательно выполните очистку после , когда вы создаете спрайты, которые используете для анимации прогресса, чтобы их текстуры сохранялись.(Вызов очистки не удаляет ничего, что используется в данный момент.) Аналогично, обязательно выполните очистку до того, как вы запустите свой фоновый поток, иначе вы получите тот же сбой, который видитеТеперь.

...