Планирование 2D-движка плиток - проблемы производительности
Как следует из названия, я разработал дизайн для 2D-платформерного движка. Это все еще в стадии проектирования, но я беспокоюсь, что у меня возникнут проблемы с рендерером, и я хочу избежать их, если они будут проблемой.
Я использую SDL для своей базовой библиотеки, и игра будет настроена на использование одного большого массива Uint16
держать плитки. Эти индексы превращаются во второй массив "определений листов", которые используются всеми частями движка, от обработки столкновений до графической процедуры, что является моей самой большой проблемой.
Графический движок предназначен для работы с разрешением 640x480 и плиткой 32x32. На слой на кадр приходится 21x16 плиток (для обработки дополнительной плитки, отображаемой при прокрутке), и можно нарисовать до четырех слоев. Слои - это просто отдельные массивы плиток, но массив определения плиток является общим для всех четырех слоев.
Что меня беспокоит, так это то, что я хочу иметь возможность использовать прозрачные пленки и анимированные плитки с помощью этого движка, и, поскольку я не слишком знаком с проектами, я боюсь, что мое текущее решение будет слишком неэффективным, чтобы хорошо работать.
Мой целевой FPS - это плоские 60 кадров в секунду, и при прорисовке всех четырех слоев я смотрю на 21x16x4x60 = 80,640 отдельных плиток 32x32px, которые необходимо рисовать каждую секунду, плюс сколько блиттов нечетного размера необходимо для спрайтов, и это кажется немного чрезмерным. Итак, есть ли лучший способ приблизиться к рендерингу настроек карты тайла, который у меня есть? Я смотрю на возможности использования аппаратного ускорения для рисования карт листов, если это поможет значительно повысить производительность. Я также хочу надеяться, что смогу хорошо запустить эту игру и на чуть более старых компьютерах.
Если я ищу слишком много, то не думаю, что об уменьшении возможностей двигателя не может быть и речи.
7 ответов
Обязательно используйте альфа-прозрачность только для плиток, которые фактически используют альфа, и пропустите рисование пустых плиток. Убедитесь, что глубина цвета поверхности плитки соответствует глубине цвета экрана, когда это возможно (на самом деле это не вариант для плиток с альфа-каналом), и сохраняйте плитки в видеопамяти, чтобы sdl использовал аппаратное ускорение, когда это возможно. Прозрачность цветового ключа будет быстрее, чем наличие полного альфа-канала, для простых плиток, где частичная прозрачность или смешивание сглаженных краев с фоном не требуется.
В системе с частотой 500 МГц вы получите около 6,8 тактов процессора на пиксель на слой или 27 на пиксель экрана, что (я считаю) будет недостаточно, если у вас есть полные альфа-каналы на каждом тайле каждого слоя, но следует будет хорошо, если вы берете ярлыки, подобные тем, которые упоминались, где это возможно.
Я думаю, что проблема будет заключаться в количестве вызовов отрисовки, а не в общей "скорости заполнения" всех пикселей, которые вы рисуете. Помните - это более 80000 звонков в секунду, которые вы должны сделать. Я думаю, что ваше самое большое улучшение будет как-то объединять их вместе.
Одной из стратегий снижения скорости заполнения плиток и слоев будет объединение статических областей. Например, если вы знаете, что область не нуждается в обновлении, ее можно кэшировать. Многое зависит от того, прокручиваются ли слои независимо (стиль параллакса).
Кроме того, посмотрите в Google "грязные прямоугольники" и посмотрите, могут ли какие-либо схемы соответствовать вашим потребностям.
Лично я бы просто попробовал и посмотрел. Это, вероятно, не повлияет на ваш общий игровой дизайн, и если у вас хорошее разделение между логикой и представлением, вы можете оптимизировать рисунок плитки, пока коровы не вернутся домой.
Можете ли вы просто буферизовать каждый полный слой в его виде плюс дополнительный размер плитки для всех четырех концов (если у вас вертикальная прокрутка), снова использовать буфер, чтобы создать новый буфер минус первый столбец и нарисовать новый конечный столбец? Это уменьшит много ненужных перерисовок.
Кроме того, если вы хотите 60 кадров в секунду, вы можете найти способы создания методов пропуска кадров для более медленных систем, пропуская каждый второй или каждый третий этап прорисовки.
Я согласен с Комбува. Если это простая 2D-игра на основе плиток, вам действительно следует немного снизить стандарты, поскольку это не Crysis. 30FPS очень плавный (исследуй Command & Conquer 3, который ограничен 30FPS). Тем не менее, я написал программу для просмотра на удаленном рабочем столе, которая работала со скоростью 14FPS (1900 x 1200), используя GDI+, и она была все еще довольно гладкой Я думаю, что с вашей 2D-игрой у вас все будет хорошо, особенно с использованием SDL.
Вы можете подумать о слиянии соседних плиток с одинаковой текстурой в более крупный полигон с текстурным листом (своего рода процесс сборки).
Думаю, вы будете приятно удивлены тем, сколько таких плиток вы сможете нарисовать за секунду. Современное графическое оборудование может заполнять кадровый буфер 1600x1200 много раз за кадр с частотой 60 кадров в секунду, поэтому кадровый буфер 640x480 не будет проблемой. Попробуйте и посмотрите, что вы получите.
Вы обязательно должны воспользоваться аппаратным ускорением. Это даст вам 1000-кратную производительность при минимальных усилиях с вашей стороны.
Если вам все-таки нужно оптимизировать, то самый простой способ - перерисовать только те области экрана, которые изменились со времени последнего кадра. Похоже, вам нужно знать о любых анимационных плитах и любых плитах, которые изменили состояние каждого кадра. В зависимости от игры это может быть где угодно, от какой-либо выгоды до огромной экономии - это действительно зависит от того, сколько экрана меняет каждый кадр.
Как насчет уменьшения частоты кадров до 30 кадров в секунду. Я думаю, что это будет достаточно для 2D-игры.