Коллекция с быстрым удалением / итерацией / вставкой, которая повторяет объекты в программах Android / Java? - PullRequest
5 голосов
/ 28 января 2010

Я программирую игру для Android. Например, игра может включать пули, врагов, драгоценные камни и т. Д., Которые должны быть:

  • создано и уничтожено в игровом мире во время игры, например пуля - это огонь, а затем исчезает при попадании в стену.

  • последовательный доступ, например, все обновляется в последовательности, затем все рисуется в последовательности.

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

  • Не выделять объекты, когда в этом нет необходимости, потому что сборщик мусора сработает и испортит вашу частоту кадров.

  • Предпочитаю, например, доступ к локальной переменной для доступа к полям объекта и вызова функций.

Для игровых объектов, упомянутых выше в компьютерной игре, я обычно просто использую что-то вроде Vector или LinkedList. Однако они не будут перерабатывать объекты, и использование Iterator создаст новый объект, а также вызовет несколько вызовов функций при выполнении итерации.

Какая коллекция подходит для использования?

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

Это работает довольно хорошо:

Плюсы: перерабатывает объекты, мало / нет вызовов функций Минусы: склонны к ошибкам (особенно при удалении), когда они не реализованы как класс коллекции

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

Спасибо.

Ответы [ 2 ]

7 голосов
/ 28 января 2010

Я программировал игры в конце 80-х и в последнее время на Java для мобильных устройств. Я могу сказать вам, что вы собираетесь убить частоту кадров, если будете использовать LinkedList или Vector для хранения объектов Java, соответствующих таким простым вещам, как маркеры. Это не то, как эффективные мобильные игры запрограммированы. Эффективные мобильные игры программируются с учетом того, что «каждый бит имеет значение». Это одна из тех областей, где царит оптимизация.

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

(20,30,3) (10, 50, 2) (30, 40, -3) (50, 50, 5)

Таким образом, первый пункт находится в пикселе (20,30) в вашем координатном пространстве и движется со скоростью 3 (что бы ни означала скорость 3, это всего лишь пример) вправо (упрощенно, это просто объяснить) , пуля 2 в (10,50) идет со скоростью 2 вправо, пуля 3 в (30,40), со скоростью 3 влево (минус здесь означает слева) и последняя пуля в (50,50,5) едут со скоростью 5 вправо.

Как это отображается в памяти в современных мобильных играх?

Вот так, в int []:

int [] = {4, 20, 30, 3, 10, 50, 2, 30, 40, -3, 50, 50, 5, ..., ..., ...};

Первые 4 говорят нам, что эта «структура данных представляет собой 4 элемента. И вы знаете, что каждое из них состоит из 3 значений (в нашем упрощенном примере).

Теперь представьте, что пуля 2 попадает в стену и исчезает, что происходит?

Это:

int [] = {3, 20, 30, 3, 50, 50, 5, 30, 40, -3, 50, 50, 5, ..., ..., ...};

Мы упрощаем уменьшенный первый int до 3, чтобы указать, что на данный момент в нашем игровом мире осталось только 3 маркера, и мы просто переместились (50, 50, 5) в положение «2», заменив (10, 50,2) по (50, 50, 5). Это связано с тем, что порядок нашей маркировки не имеет значения (все они имеют одинаковый эффект), и «перемещение всех элементов int [] влево» будет действительно неэффективным.

Обратите внимание, что мы даже не удосужились «очистить» «четвертую пулю»: старый (50,50,5) все еще там в конце, но мы знаем, что у нас осталось только 3 элемента, поэтому мы не будем все равно.

Так в памяти это выглядит так:

int [] = {3, 20, 30, 3, 50, 50, 5, 30, 40, -3, 50, 50, 5, ..., ..., ...};

Вас беспокоит только это:

int [] = {3, 20, 30, 3, 50, 50, 5, 30, 40, -3, ..., ..., ..., ..., ...,. ..};

ТО - это то, как это делается в большинстве современных мобильных игр: создание нулевого объекта для «обработки маркеров» в основном цикле. Вы управляете такими простыми структурами данных самостоятельно, используя массивы примитивов.

И int [] инициализируется в начале вашей игры вашего уровня на максимальное количество пуль, которое может произойти в вашей игре / уровне.

Вот вам и ваш «пул многоразового использования».

Если вы начнете думать о том, чтобы иметь объект Java для чего-то столь же тривиального, как пуля, и использовать LinkedList или Vector, которые вы будете изменять в каждом кадре, вы никогда не получите приемлемую производительность: вы будете генерирование бесчисленных ненужных объектов 50 раз в секунду и слишком частое срабатывание ГХ.

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

Моя техника «удаления пуль» включает в себя один декремент (количество пуль) и 3 int копии. Вы не можете победить это;)

И это работает для многих вещей: пуль, эффектов частиц, врагов, предметов, бонусов и прочего:)

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

2 голосов
/ 28 января 2010

Я думаю, что вы ищете / говорите о объектном пуле

Из Википедии:

пул объектов - это шаблон проектирования программного обеспечения. Пул объектов - это набор инициализированных объектов, которые остаются готовыми к использованию, а не размещаются и уничтожаются по требованию. Пул объектов может предложить значительное повышение производительности в ситуациях, когда стоимость инициализации экземпляра класса высока, скорость создания класса высока , а число экземпляры, используемые в любое время, низки .

Похоже, вы уже начали свой путь к созданию пула объектов, поэтому он может подойти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...