Масштабирование в 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.

Метод работает, но возможны проблемы из-за разных видеокарт. Я с ними не встречался, однако говорят, что такое бывает.

И еще, не забудьте включить использование вида в настройках комнаты, и сделать нулевой вид видимым по умолчанию. Размеры вида и порта на экран должны быть одинаковыми!

  • yeo
  • 18 января 2011, 18:22