2014-01-03 1 views
1

Я создаю меню прокрутки, которое генерирует новые строки кнопок «на лету» и должно генерировать каждую кнопку из большого количества спрайтов. Поскольку это интенсивность процессора, меню хранится около четверти секунды каждый раз, когда ему нужно загрузить новую строку кнопок. Я понял, что мне нужно добавить многопоточность, чтобы загрузка кнопки могла обрабатываться в другом потоке, чем анимация прокрутки, но когда я делаю это, она срабатывает при попытке загрузить новые кнопки. Вот код, я использую:ошибки при попытке использования dispatch_async с функциями cocos2d

-(void)addRowBelow{ 
    _rowIndex--; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSMutableArray *row = [self addRow:_rowIndex]; 
     [_buttonGrid addObject:row]; 
     [self removeRow:[_buttonGrid objectAtIndex:0]]; 
    }); 
    _nextRowBelowPos += _rowHeight; 
    _nextRowAbovePos += _rowHeight; 
} 

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

+1

Ум ... многопоточность и cocos2d обычно не хорошо подходят для спрайтов (и манипулирования другими объектами cocos2d), потому что движок делает с ними что-то, в то время как ваш собственный поток может делать что-то еще. Можете ли вы предварительно загрузить все спрайты в сцену init, сохранить их в контейнере где-нибудь (модель?), А затем просто принести их в/из, когда вам нужно? – FuzzyBunnySlippers

+0

Вы создаете спрайты «на лету», как вам нужно, или предварительно загружая их? Являются ли они в листе спрайта или отдельных файлах? Ваши спрайты должны быть в листе спрайта, если это возможно ... это действительно экономит на циклах gpu, так как не нужно включать текстуру в/из. – FuzzyBunnySlippers

+0

Да, все мои спрайты находятся на одном листе спрайта. Рисование вызовов показывает как 1. Это не сам спрайт, а число, которое мне нужно отобразить сразу, и расчеты их позиций. Каждая кнопка содержит несколько сотен спрайтов. Я предваряю предварительное создание объектов спрайтов заранее и просто показывая и скрывая их при прокрутке, это хорошая идея. –

ответ

2

Вы, вероятно, получить сбой проблемы, потому что вы многопоточный доступ к Кокосовые управляемых объектов (спрайты, слои, узлы и т.д.). Поскольку движок рассчитывает использовать внутренние элементы этих объектов для отображения, операций графического процессора и т. Д., И является NOT потокобезопасным, вы, вероятно, не будете иметь хороших результатов при многопоточности. Возможно, вы меняете прямо в середине, когда он его использует.

Создание/уничтожение спрайтов на лету, вероятно, является причиной вашего замедления. Cocos2d может отображать много объектов (я думаю, что это порядка 2k) на экране со скоростью 60 кадров в секунду ... пока вы не дросселируете его, сделав много создания/уничтожения или AI.

Я предлагаю вам предварительно загрузить все ваши спрайты, прежде чем ваша сцена выйдет на сцену. Вы можете сделать это во вводной сцене или в самом начале сцены и позволить спрайтам владеть сценой. Затем вы можете перебирать их во время вызова update() и изменять их позиции, делать видимыми/невидимыми и т. Д.

Для справки обычно я создаю разные «слои спрайтов», которые загружают все их спрайты на добавление к место действия. Если у меня будут динамические объекты, я попытаюсь выделить некоторые из них и переработать их, когда это возможно. Это также позволяет мне контролировать порядок «что находится перед чем» на экране (see example here). Каждый слой также нарисовывает элементы определенных типов сущностей, что дает хороший символ «MVC» для большого количества дисплея.

Это аналогично тому, как iPhone Apps перерабатывает ячейки таблицы.

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

Было ли это полезно?

+0

Да, это было полезно. Я перерабатываю всю систему меню, чтобы предварительно загрузить все спрайты и скрыть те, которые в настоящее время не отображаются. Я вернусь и дам вам знать, исправляет ли он проблему после ее завершения. –

+0

@JamesMorrison Очень хорошо. Позвольте мне знать, как это получается. – FuzzyBunnySlippers

+0

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

0

Узор вы, вероятно, хотите использовать

  1. отправка работа в фоновом потоке. (Обратите внимание, что работа должна быть безопасной для выполнения в фоновом потоке.)
  2. Отправляйтесь в основной поток, чтобы обновить свой интерфейс.

Вот пример того, как это выглядит в коде:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    // Do work that is safe to execute in the background. 
    // For example, reading images from disk. 

    dispatch_async(dispatch_get_main_queue(), ^{ 

     // Do work here that must execute on the main thread. 
     // For example, calling Cocos2D objects' methods. 

     NSMutableArray *row = [self addRow:_rowIndex]; 
     [_buttonGrid addObject:row]; 
     [self removeRow:[_buttonGrid objectAtIndex:0]]; 

    }); 
}); 
Смежные вопросы