SpriteKit: бесконечно движущийся спрайт приводит к тому, что кадр иногда прерывается

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

Моя игровая сцена содержит всего 3 спрайта: верхний, средний и нижний. У меня есть десятки изображений спрайтов, поэтому мое решение заключается в динамическом создании 3 спрайтов (чтобы спрайты могли заполнить весь экран), когда нижний спрайт находится за пределами экрана, затем уничтожьте его; когда верхний спрайт опускается по верхнему кадру, создайте новый узел спрайта, затем поменяйте местами нижний, средний, верхний спрайт.

Псевдокод: в файле интерфейса:

 - GameScene:SKScene
 {
      ...
      SKSpriteNode *_topSprite;
      SKSpriteNode *_middleSprite;
      SKSpriteNode *_bottomSprite;
      ...
 }

в файле реализации:

- (void)update:(CFTimeInterval)currentTime 
{
   // 1 compute time interval


   // 2 update sprite node
    _topSprite.position move down  100*timeInterval
   _middleSprite.position move down  100*timeInterval  
   _bottomSprite.position move down    100*timeInterval 

   // 3 crop the off-screen bottom sprite node
   if (_bottomSprite is offScreen)
   {
       [_bottomSprite removeFromParent]
   }

   // 4 check the highest sprite position visible
   // if the highest position is below the frame top,then create new sprite
   _bottomSprite = _middleSprite;  
   _middleSprite = _topSprite;
   _topSprite    = [self createNewNode]; // random a sprite image 
}

в игре fps 60, а количество узлов не увеличивается. Все кажется хорошим, но я обнаружил, что иногда в игре внезапно появляется очень слабый кадр, из-за чего движущийся кадр не является непрерывным. Интуитивно я думал, что основная причина связана с шагом 4. Но у меня нет идей, как это решить. Любые предложения будут оценены.

Вот метод createNewNode:

- (SKSpriteNode *)createNewNode {
    NSString *blockName = [self randomImageName];

    SKSpriteNode *sprite = [[SKSpriteNode alloc] initWithImageNamed:blockName];
    sprite.position = _highestPosition;
    sprite.anchorPoint = CGPointMake(0.5, 0);
    NSLog(@"putAnotherNodeOnTop %@", blockName);
    [self addChild:sprite];
    return sprite;
}

person cartmanie    schedule 11.07.2014    source источник
comment
Каков размер ваших изображений спрайтов? Они загружаются из sprites.atlas?   -  person Akaino    schedule 11.07.2014
comment
Мои изображения спрайтов имеют одинаковый размер: 390 * 512. Я не использую sprites.atlas.   -  person cartmanie    schedule 11.07.2014
comment
Странный. Не должно быть такой проблемы. Не могли бы вы опубликовать свой createNode, пожалуйста?   -  person Akaino    schedule 11.07.2014
comment
Вставляю код в пост.   -  person cartmanie    schedule 11.07.2014
comment
Используйте Time Profiler, чтобы определить, какая строка кода самая дорогая   -  person Andrey Gordeev    schedule 11.07.2014
comment
1. Используйте атлас. 2. Не выпускайте/создавайте новые спрайты, используйте одни и те же 3 спрайта на протяжении всей игры. Просто измените их положение и, при необходимости, их текстуру, перемещая их снизу вверх. # 2, вероятно, является причиной вашей проблемы с производительностью, поскольку циклы выделения / выпуска для спрайтов дороги, тем более, если они должны загружать отдельные изображения, а эти изображения не находятся в атласе, что означает, что каждое отдельное изображение должно быть загружено, а не возможность предварительно загрузить весь атлас в начале.   -  person LearnCocos2D    schedule 11.07.2014


Ответы (1)


Несколько предложений.

Поскольку вы используете одни и те же три изображения, вам не нужно каждый раз заново создавать спрайты. Должно быть дешевле установить для скрытого значения значение ДА, переместить куда-нибудь спрайт, установить текстуру, а затем снова отобразить его со скрытым значением НЕТ. SpriteKit не рисует скрытые узлы или узлы за пределами экрана.

Ваш код в основном запрашивает PNG на диске каждый кадр в обновлении, когда вызывается createNewNode:. Должно быть более производительно загружать текстуры в память и назначать их спрайтам по мере необходимости. Если у вас их всего несколько, сделать их переменными экземпляра SKTexture было бы простым способом.

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

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

person Jeremy    schedule 12.07.2014