В обычных событиях Draw, GameMaker сначала рисует графику на отдельном “холсте” (на самом деле это просто область памяти в VRAM), и лишь потом отображает результат на экран. Такой холст называется поверхностью приложения (application surface). Этой поверхностью можно манипулировать перед выводом на экран.

Кроме application surface, GameMaker позволяет создавать свои собственные сурфейсы, что необходимо для создания различных эффектов.

Правила работы сурфейсами:

  • Все сурфейсы, кроме application surface, являются непостоянными, волатильными. Это означает, что они могут быть уничтожены простым сворачиванием окна, или если окно игры потеряет фокус. Это связанно с тем, что сурфейсы хранятся в текстурной памяти VRAM и они могут быть перезаписаны, если целевой платформе вдруг понадобится эта память. Поэтому необходимо писать отказоустойчивый код, проверяющий существование сурфейса и рисующий его заново, если потребуется.
  • Сурфейсы могут требовать много видеопамяти, поэтому стоит контролировать их количество и стараться не создавать их размером больше игрового окна или view.
  • Сурфейсы нужно создавать только в событии Draw, иначе можно случайно сослаться на application surface. Рисовать что-либо на сурфейсе тоже нужно в событии Draw, хотя есть крайне редкие случаи, когда можно, или даже необходимо, что-либо нарисовать на сурфейсе в другом событии.
  • При рисовании на сурфейсе нужно помнить, что он всегда находится в позиции 0,0. Это означает, что может потребоваться преобразовать абсолютные координаты сурфейса в относительные.
  • Стоит отметить, что при рисовании на сурфейсе будут учитываться и цвет и альфа-компонент каждого пикселя, как самого сурфейса, так и того, что на ней рисуется. Если не понимать как работают режимы смешивания, результат рисования может шокировать

    [!NOTE] Последний пункт не касается рисования на application surface

Пошагово

  1. Сначала нужно создать сурфейс и присвоить её переменной
    1. Настоятельно рекомендуется создавать сурфейсы с размерами равными степеням двойки (16, 256, 512, 1024 и т. д.)
    2. После создания сурфейса его стоит очистить, ведь это область памяти в которой ещё могли остаться данные
//CREATE EVENT
my_surface = surface_create(256, 256)
draw_clear_alpha(c_black, 1)
  1. Затем нужно установить в качестве цели рендеринга созданный сурфейс.
  2. Далее все функции рисования теперь будут применены к сурфейсу.
  3. Когда всё, что нужно нарисовано, цель рендеринга необходимо сбросить, используя команду surface_reset
//DRAW EVENT
surface_set_target(my_surface)
draw_text(0,0, "Hello World!")
surface_reset_target()
  1. Но этого не достаточно, чтобы изображение появилось на экране. Для этого нужно отобразить созданный сурфейс на application surface:
//DRAW EVENT
//Проверка, существует ли сурфейс, на случай если он был уничтожен
if !surface_exists(my_surface)  
{  
    my_surface = surface_create(1024, 1024);  
}  
else
draw_surface(my_surface, 0, 0)
  • Но кроме рисования сурфейса, его таже можно отправить в шейдер, или использовать для других манипуляций.

    Application surface

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

[!NOTE] Единственная вещь, которую нельзя сделать с application surface — это освободить память. Это означает, что application surface существует всегда, но его дескриптор может измениться

Когда игра запускается application surface создаётся при первом вызове события Draw в каждой новой активной комнате. Несмотря на это, все параметры application surface можно изменить, например, в событии Create, ещё до того как он будет создан. Можно получить положение application surface и изменить его размер в событии Create или любом другом без каких-либо ошибок, а используемые значения будут актуальны для application surface при его создании.

Порядок отрисовки application surface

  • Pre-Draw Event
    • application surface создаётся (если он не существует) и устанавливается как цель рендеринга
  • Для каждого видимого вьюпорта, если они активны (в противном случае только 1 раз):
    • Draw Begin Event
    • Draw Event
    • Draw End Event
      • application surface сбрасывается как цель рендеринга
  • Post-Draw Event
    • Содержимое application surface отображается в display buffer (Это можно отключить функцией application_surface_draw_enable)
  • Draw GUI Bod event

[!NOTE] Display buffer — это “холст”, на котором в конце концов всё будет нарисовано. Некоторые события использую в качестве цели рисования именно display buffer, а не application surface, например Pre-Draw Event, в то время как другие сначала рисуют на application surface, а потом в display buffer

Чтобы получить доступ к application surface нужно использовать встроенную глобальную переменную application_surface