Отрисовка всех DrawableGameComponents в одном пакете

Это вопрос XNA...

У меня есть большое количество объектов DrawableGameComponents в моей игре, и все они используют один и тот же SpriteBatch. Однако мне приходится каждый раз вызывать SpriteBatch.Begin() и .End() для отрисовки каждого компонента. Я хочу рисовать все одним пакетом для повышения производительности, но я не знаю, куда могут пойти .Begin() и .End(), поскольку .Draw() вызывается автоматически (поскольку они являются DrawableGameComponents)

Кто-нибудь знает, что я могу сделать, чтобы все они были нарисованы между одним вызовом .Begin() и .End(), сохраняя при этом их как DrawableGameComponents?

Редактировать:

Хорошо с этого веб-сайта http://www.progware.org/Blog/post/XNA-Game-Development-(Decentralize).aspx Я полагал, что он вызывается при вызове base.Draw() основного игрового цикла... поэтому я могу просто обернуть его с помощью Begin и End методы

protected override void Draw(GameTime gameTime) {
    if (Cell.Cell.CellSpriteBatch != null) {
        Cell.Cell.CellSpriteBatch.Begin(
            SpriteSortMode.BackToFront, BlendState.AlphaBlend, 
            SamplerState.AnisotropicClamp, null, null, null,
            gamePlay.Camera.GetTransformation()
        );
    }

    base.Draw(gameTime);

    if (Cell.Cell.CellSpriteBatch != null) {
        Cell.Cell.CellSpriteBatch.End();
    }
}

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

Любое решение для этого?


person Dois    schedule 28.12.2010    source источник
comment
Не имеет отношения к вашему вопросу, но: вы действительно хотите использовать анизотропную фильтрацию? Обычно это бесполезно для спрайтовой графики.   -  person Andrew Russell    schedule 28.12.2010
comment
Привет... Мне было интересно, почему вы вдруг упомянули об этом, а потом я понял, что это из-за того, что SamplerState был установлен на AnsiotropicClamp. Эта часть на самом деле сделана моим товарищем по команде, программирующим камеру, и я только что связался с ним — он сказал, что не знает, для чего это нужно, и я думаю, что у него нет причин быть там. Я просто изменил его на LinearClamp по умолчанию. Спасибо!   -  person Dois    schedule 28.12.2010


Ответы (1)


Во-первых, если вы уже не знаете, что ваша партия ограничена, вероятно, не стоит этого делать. Если каждый отдельный вызов .Draw извлекает одну и ту же текстуру, вы можете увидеть некоторое ускорение. Если это разные текстуры, то переход к одному началу/концу не будет иметь никакого значения. SpriteBatch в любом случае разобьёт ваши вызовы отрисовки.

Как вы обнаружили, это также делает ваш код довольно запутанным — вам нужно отслеживать между компонентами.

Единственное решение вашей текущей проблемы — сделать SpriteBatch Immediate так, чтобы он рисовал, когда вы вызываете вызовы отрисовки, а не рисуете при вызове End. Однако это убьет вашу производительность, так как пакетная обработка вообще не выполняется.

Лично я бы придерживался начала/конца для каждого компонента, пока вы не столкнетесь с проблемой производительности. Предполагая, что у вас нет 5000 компонентов, в этом случае вам, вероятно, нужно немного по-другому спроектировать вещи.

person The ZMan    schedule 28.12.2010
comment
Да, я думаю, что реальное решение состоит в том, чтобы спроектировать вещи по-другому. Игра, которую я делаю, имеет большое количество ячеек повсюду, поэтому иногда она действительно достигает 5000 компонентов. Я структурировал код таким образом, чтобы определенные вещи, которые должны быть отрисованы сверху, вызывались последними, так что все работает нормально, просто код действительно сбивает с толку... но, поскольку у меня мало времени, я просто собираюсь пойти с этим. Однако я согласен с тем, что лучший способ — коренным образом изменить структуру моего кода, вероятно, без использования GameComponents. - person Dois; 28.12.2010
comment
Может быть, один GameComponent для всех ячеек и каждая ячейка, представленная классом, который вы создаете для нее, который имеет метод Draw. Есть некоторые накладные расходы с GameComponent. Вы действительно отображаете 5000 спрайтов на экране одновременно? - person Jason Goemaat; 28.12.2010
comment
Помните, что то, что что-то является GameComponent, не означает, что вы должны добавить его в Game.GameComponents для управления. Если вы используете GameComponent в качестве базового класса для Sprite, это нормально, но добавьте SpriteManager в коллекцию компонентов, у которой есть собственная коллекция компонентов, которой вы можете лучше управлять самостоятельно. Затем используйте это для обработки вызовов Бытия/Конца. Используйте коллекцию Game.GameComponents для «больших групп» вещей. - person The ZMan; 28.12.2010