2013-05-29 4 views
2

В настоящее время я делаю игру с использованием C# и XNA, и я реализовал своего рода функцию блока, похожую на Minecraft, за исключением сверху вниз. Добавление блоков реализуется с помощью списка блоков и их векторов (чтобы я мог повторно добавить все блоки, когда кто-то пытается загрузить игру). Это работает отлично, но я обнаружил, что (после добавления 4 новых блоков в игру) обновление каждого блока вызывает колоссальные запаздывания.Задержка при обновлении многих вещей? XNA

Я реализовал функцию, которая проверяет, если блоки ограничивающего параллелепипеда находится в пределах видовых границ здесь:

for (int b = 0; b < blocklist.Count; b++) 
{ 
    if (view.Contains((int)blocklist[b].blockposition.X, (int)blocklist[b].blockposition.Y)) 
    { 
     blocklist[b].visible = true; 
    } 
    else 
    { 
     blocklist[b].visible = false; 
    } 
} 

Если visible равен true, блок рисуется, однако, я все еще получаю немного отставание, несмотря на это, так что мне было интересно, если я мог бы сжиматься метод обновления с этого:

foreach (Builder b in blocklist) 
{ 
    b.Update(); 
} 

Для этого:

foreach (Builder b in blocklist) 
{ 
    if (b.visible == true) 
    { 
     b.Update(); 
    } 
} 

Будет ли это игнорировать обновление блоков, если они не отображаются на экране?

Спасибо за любой вклад и советы по производительности!

EDIT: Я пытался реализовать идею массива, но у меня возникают некоторые проблемы

 if (player.Builder == true && player.LMBpressed == true && blockspawnamount >=          placeblock && collisionengine.connecting <= 0) 
     { 
      if (build.BlockID == 1 && menu.open == false) 
      { 

       position = new Vector2((int)(cursor.cursorPos.X/ 58) * 58, (int)(cursor.cursorPos.Y/58) * 58); 

       blocktex1 = grass1; 
       Builder[,] blocks = new Builder[grass1.Width, grass1.Height]; 
       Builder block = blocks[x,y]; 

       for (int x = view.Left; x < view.Right; ++x) 
       { 
        for (int y = view.Top; y < view.Bottom; ++y) 
        { 
         blocks[x,y].Update(); 
        } 
       } 


       blockpos1.Add(position); 


       placeblock = 200.0f; 
      } 


     } 

Проблема у меня в том, что здесь:

Builder block = blocks[x,y]; 

он говорит, что индекс был вне границ массива.

Теперь, чтобы объяснить, как это работает. При нажатии на позицию устанавливается позиция курсора, разделенная на ширину блоков блоков (в этом случае int 58). Затем он добавляет блок в список и рисует его позже. У меня нет отдельного класса Blocks, который управляет типом блока, однако класс Builder управляет размещением и типом блока.

Теперь вот мой вопрос: Вы добавили в массив, который обычно добавляете в список? можете ли вы нарисовать его как список?

также: из-за того, что класс Builder контролирует размещение блоков, я не могу удалить переменную позицию, если я, не будет никакой позиции для размещения блоков

+0

Я согласен с Vaughan рукояти, вам нужно свой код, чтобы найти, где узкое место. Однако на первый взгляд, я вижу вашу функцию, которая проверяет, является ли поле видимым, вероятно, узким местом. Вы по существу проверяете каждый отдельный ящик; это означает, что если у вас 10 000 ящиков, но только 3 видимы, вы все равно проверили все 10 000. Поскольку у вас есть 2D сверху вниз, возможно, вы можете реализовать [QuadTree] (http://en.wikipedia.org/wiki/Quadtree) или [RTree] (http://en.wikipedia.org/wiki/Rtree). Они дадут вам _super-fast_ lookups, чтобы найти, какие блоки видны. –

ответ

1

Вы должны изменить свою структуру из списка на 2D Array (Examples) Это IDEAL для того, что вы делаете, и вы увидите огромное увеличение производительности по сравнению с использованием списка.

Например:

Builder[,] Blocks = new Builder[WIDTH,HEIGHT]; 

Вы не будете нуждаться в переменной позиции в вашем Builder классе, так что вы можете удалить это.

Теперь, когда вы хотите получить или установить какой-либо блок, то, как с помощью сетки, вместо списка, так что очень легко получить конкретный блок

Builder Block = Blocks[x,y]; 

Теперь, когда вы обновляете или рисовать эти блоки, вы можете ввести метод, называемый culling, то, что он делает это, препятствует тому, чтобы объекты, которые отключены от сцены, были нарисованы/обновлены.

for (int x = left; x < right; ++x) 
{ 
    for (int y = top; y < bottom; ++y) 
    { 
      Blocks[x,y].Update() 
    } 
} 

Теперь ваши left, right, top и bottom переменные будут края вашего окна просмотра/камеры. Если вы просто хотите протестировать это без отбраковки, вы можете просто установить left как 0 и вправо как Blocks.GetUpperBound(0); (0 - ширина, 1 высота)

Кроме того, не пытайтесь угадать, что не так, вам нужно использовать профилировщик, чтобы найти то, что потребляет процессор.

Имеет некоторые связанные с этим проблемы, которые у меня были, что может помочь вам.

Low FPS, What Profiling Application Should I use?

Performing an Update Tick on tiles

+0

Я даже не знал про профилировщики до сегодняшнего дня, спасибо! –

0

Это будет работать, только если вы обновите такой флаг самостоятельно в своем коде где-нибудь. Если вы примените логику для установки этого флага, то, конечно, это сработает. Если вы этого не сделаете - тогда такой флаг бесполезен. Профилируйте свой код и найдите узкое место - не догадывайтесь.

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