Подходит ли Java AWT для рендеринга 2d игр?

8

[Повторяю этот вопрос из stackoverflow, поскольку было отмечено, что он подходит лучше здесь.]

В настоящее время я портирую свой 2D-движок на Java. Я посмотрел на некоторые из библиотек игр, указанных здесь, на stackoverflow. Однако те, на которые я смотрел, были довольно упрощенными и даже не указывали, поддерживают ли они такие вещи, как альфа-прозрачность, поэтому я решил портировать свой рендерер C ++, для которого я уже выписал логику.

Этот рендерер является чисто программным рендерером, который использует тайлинг, чтобы избежать ненужного повторного рендеринга. Я оптимизировал его производительность прокрутки, создав «внеэкранный буфер», немного больший, чем моя панель вывода, и поместил этот внеэкранный буфер на мой вывод в каждом кадре. Таким образом, я мог бы избежать ненужной перерисовки тайлов только потому, что прокручивал пиксель на карте.

Я использовал AWT Java для его реализации, используя большой BufferedImage для закадрового буфера. Использование процессора в порядке (примерно вдвое больше, чем у меня в C ++), но есть странная проблема с непрерывной прокруткой, когда каждую секунду или около того рендерер задерживается примерно на 0,2 секунды.

Так как в моем собственном коде нет ничего, что могло бы произойти в эти периоды, и, так как пики исчезают, если я не отрисовываю свой внеэкранный буфер на главном экране, я могу только заключить, что Java выполняет некоторую внутреннюю оптимизацию самостоятельно. Однако я не уверен, что он делает, и не знаю, какую из моих собственных оптимизаций мне пришлось бы удалить, чтобы избавиться от пиков. Кроме того, может случиться так, что java AWT не был создан с непрерывной прокруткой с высоким FPS, и это совершенно непригодно для этой цели.

Есть ли какой-то способ избавиться от этих шипов?

CIB
источник
4
Это может быть сборщик мусора?
bummzack
@bummzack: возможно. В профилировщике это выглядит так: i.imgur.com/EMxkA.png Однако я не уверен, как бы я уменьшил этот эффект, особенно если он вызван моими вызовами graphics.drawImage
cib

Ответы:

4

Хотя я не могу быть уверен, не посмотрев на ваш код, похоже, ваша проблема в сборщике мусора. В Java время от времени происходят крупные и второстепенные сборки мусора. Несовершеннолетние израсходуют часть вашего процессора, но не будут вас сильно беспокоить. Основные коллекции могут представлять реальную проблему для приложений реального времени, таких как игры, поскольку они фактически приостанавливают все во время работы.

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

Pjotterke
источник
2

Да.

Для игр на основе 2D-спрайтов, AWT может использоваться для управления рендерингом с большим эффектом. Это может быть даже аппаратное ускорение , в зависимости от доступного оборудования.

Без какого-либо кода или подробных фрагментов профилирования трудно сказать, в чем проблема. Лучшее, что я могу сделать, - это предложить несколько основных советов по работе с Java и AWT при создании игр.

Работа с сборщиком мусора

GC на Java - это то, о чем мы должны помнить, создавая наши игры. Он будет периодически запускаться, искать объекты, на которые нет ссылок, и удалять их из памяти. Этот процесс удаления является медленным и, вероятно, является причиной сбоя, который вы испытываете.

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

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

public final class Resources {
    public static Map<int, String> strings;
    public static Map<int, Texture> textures;
    public static Map<int, GameObject> objects;
    public static Map<int, SoundEffect> sounds;
}

Во время загрузки экранов вы можете увеличивать или уменьшать свои Mapэкземпляры, используя newключевое слово. Но во время игры вы захотите избегать этого настолько, насколько сможете. Если что-то разрушено во время игры, установите флаг на объекте, чтобы вы знали, что это не то, что в данный момент активно. Если вам нужно создать новый объект, просмотрите его, Mapпока не найдете неактивный объект, установите его свойства и отметьте его как активный.

Это то, что вы должны иметь в виду при использовании Java для чувствительных к производительности приложений, независимо от того, используете ли вы AWT, JavaFX или OpenGL для рендеринга.

холст

В частности, для AWT я настоятельно рекомендую использовать класс Canvas для отображения всего по разным причинам:

  • Вы лучше контролируете, когда все рендерится. Это означает, что вы можете написать свой собственный игровой цикл и выполнять такие вещи, как интерполяция, экстраполяция, ограничение скорости и т. Д.
  • Кажется, работает лучше. Мне удалось одновременно выводить на экран больше вещей с приемлемой частотой кадров, а не пытаться анимировать несколько объектов Label и Image.
  • Проще встраивать в редакторы. Возможность установки фрейма с обычными элементами управления графическим интерфейсом и наведения логики рендеринга вашей игры на Canvas означала, что я мог повторно использовать код рендеринга игры в инструментах редактора.
  • Это дает вам легкий доступ к API Java2D (он же класс Graphics2D ).
зашифровывать
источник