Масштабирование в Game Maker
1. Проблема
Тем, кто работает с Game Maker, известно, что GM выделяет в памяти место для не сжатых картинок, не взирая на изначальный формат. То есть будь это хоть jpeg, хоть gif — GM «смотрит» на него как на bmp.
В связи с этим, рано или поздно, большинство разработчиков сталкивается с проблемой масштабирования картинки, так как «большие» изображения занимают много памяти и приводят в конечном итоге к торможению и большому времени загрузки. Значимая доля разработчиков в принципе работает с «маленькой» графикой, либо из-за ностальгии по старым приставкам, либо из-за «выдранных» ресурсов из игр для тех же старых приставок. Так или иначе, все они приходят к вопросу «как вывести на экран увеличенное в 2 (3, 4, 5) раз изображение».
Это меню настроек Game Maker. На картиночке видно, что GM позволяет запускать игру сразу же на полный экран, сделать процентное масштабирование в окне, сохранить исходные размеры даже при отображении в полном экране и так далее. Есть даже галочка «interpolate colors between pixels», которая должна по идее отвечать за включение/выключение сглаживания графики при масштабировании, но на практике это оказывается не так.
Стоит заметить, что не всем принципиально это самое «сглаживание». В основном, проблема касается тех, кто использует пиксельную графику, которая теряет огромную долю своего очарования при интерполяции. Именно для них в этом месте начинаются проблемы.
Проблема заключается в том, что GM сглаживает или не сглаживает картинку неуправляемо, основываясь на «показаниях» видеокарты. Если карта тянет — сглаживание происходит, если нет — обходится без него. Ни на какие «галки» GM при этом не смотрит.
2. Обходные пути
Обходных путей несколько, и все они недостаточно хороши. Первый путь заключается в том, чтобы масштабировать каждую картинку в игре. Рассматривать его мы не будем, потому что это вариант не гибкий, трудоемкий и потому не используемый.
Второй путь мог бы стать решением, если бы не одно «но».
Это настройки «комнаты». Здесь есть настройки «вида» и портирования на экран. Казалось бы, стоит масштабировать портирование в два раза и вот оно, картинка увеличится вдвое. На деле так и происходит, однако, при движении экрана преимущественно задний фон начинает дрожать, по экрану бегут полосы и все плюсы данного метода улетают в трубу.
3. Решение
Суть третьего и единственного на данный момент более менее работающего метода заключается в использовании «поверхностей» (surface).
Углубляться в механизм действия поверхностей я не буду, однако вкратце смысл таков.
Каждый игровой шаг GM выводит картинку на экран. Фактически, он рисует прямо на экране. Однако можно рисовать вначале на surface, производить над surface какие-то действия, а результат выводить экран.
Таким образом, мы рисуем игровой шаг на поверхность, увеличиваем ее вдвое (втрое, четверо), и потом выводим на монитор пользователя.
Для этого мы создаем три скрипта:
screen_init
//начальные установки
screen_x = 0;
screen_y = 0;
screen_w = 320; //изначальная ширина картинки
screen_h = 240; //изначальная высота картинки
screen_scale = 2; //масштаб. в данном случае в 2 раза. эту переменную можно, например, менять в опциях, чтобы игрок сам мог выбрать нужное ему масштабирование
// создание поверхности
screen = surface_create(screen_w,screen_h);
draw_clear(0);
// далее мы проверяем, сумела ли видеокарта создать поверхность. если нет, то мы используем встроенное масштабирование ГМ, при котором сглаживания происходить не будет, так как видеокарта не потянула
if ( screen = -1 )
{
view_visible[0] = false;
view_visible[1] = true;
window_set_size(screen_w * screen_scale,screen_h * screen_scale);
window_set_region_scale(screen_scale,1);
window_center();
instance_destroy();
}
else
{
//прописываем для ВСЕХ комнат в игре, в данном случае используется только для нулевой комнаты
room_set_view(0,0,1,0,0,screen_w,screen_h,0,0,screen_w * screen_scale,screen_h * screen_scale,100,32,-1,-1,-1);
}
screen_begin
surface_reset_target();
draw_clear(0);
draw_surface_stretched(screen,screen_x,screen_y,screen_w*screen_scale,screen_h*screen_scale);
screen_refresh();
screen_end
surface_set_target(screen);
Затем, при запуске игры создаем постоянный (persistent) и видимый (visible) объект, в котором прописываем наши скрипты:
Событие CREATE screen_init ();
Событие BEGIN STEP screen_begin ();
Событие END STEP screen_end ();
Событие GAME END surface_free (screen);
Запускаем игру и радуемся)
P.S.
Метод работает, но возможны проблемы из-за разных видеокарт. Я с ними не встречался, однако говорят, что такое бывает.
И еще, не забудьте включить использование вида в настройках комнаты, и сделать нулевой вид видимым по умолчанию. Размеры вида и порта на экран должны быть одинаковыми!
- 18 января 2011, 18:22
- 016
37 комментариев