Game Maker Language | |
---|---|
Класс языка | объектно-ориентированный, событийно-ориентированный, скриптовый |
Появился в | 1999 |
Автор | Маркус Овермарс |
Разработчик | Овермарс, Маркус Хендрик |
Расширение файлов | .gml, .gmk, .gm6, .gmd, .gm8, .gm81 |
Испытал влияние | C++ |
Сайт | yoyogames.com |
ОС | Windows |
Game Maker Language (GML) — интерпретируемый язык программирования, разработанный для использования вместе с программой для разработки компьютерных игр, называемой Game Maker. Изначально поддержка языка была внедрена в Game Maker Марком Овермарсом для дополнения системы кнопочных событий, однако позже все кнопочные события были включены в GML, позволяя программисту избежать использования кнопочных функций. GML очень сильно связан со средой Game Maker. Game Maker организован так, чтобы не было необходимости программирования вручную таких вещей, как управление событиями, дизайн уровней и настройка объектов. Существует заблуждение, что GML поддерживает вставки фрагментов кода на других языках, таких как Pascal, Assembler или C++. Заблуждение возникло из-за частичной схожести синтаксиса GML с Pascal и C++. (Например, оператор «&&» может быть заменен на «and»).
В Game Maker совокупность кнопочных событий образует библиотеку. В интерфейсе программы библиотеки отображаются как закладки, в которых находятся различные иконки событий. Каждое такое событие — это GML-скрипт или функция, которую пользователь может использовать в игре. В поставку Game Maker входят несколько стандартных библиотек, которые содержат основные события, используемые в большинстве игр. Также существует возможность создавать свои собственные библиотеки, используя Library Maker. В GMS2 встроен механизм конвертации действий, заданных «кнопками», в код GML и обратно, что позволяет новичкам быстрее перейти на GML и улучшает понимание того, как работают стандартные действия.
GML структурно похож на язык С своими блоками кода, вызовами функций, присваиванием переменных, синтаксисом операторов и так далее. GML различает операторы и выражения. Например,
g < 1;
не является правильным оператором и вызовет ошибку. Также, присваивание переменных — это всегда оператор, и поэтому не может быть использован в выражениях. Например, следующая строка всегда генерировала бы ошибку потому, что она бы вычисляла вложенное выражение как true или false, а затем сравнивала бы булевый результат со строкой «Yes» (неправильное сравнение):
if ((answer = get_string("Yes or No?", "")) == "Yes")
Стоит помнить, что знак равно «=» является оператором присвоения и булевым оператором сравнения в выражениях, тогда как в C++ в выражениях пишут двойной знак «==». Тем не менее, двойной знак равно «==» будет правильно интерпретирован в случае использования его в выражениях. Использование такого знака в качестве оператора присваивания вызовет ошибку исполнения. GML также поддерживает операторы инкремента:
g++; // поддерживается как постфиксная, так и префиксная запись
и
g += 1;
то же самое, что и
g = g + 1;
Также существуют операторы: -=, *=, /=, |=, &= и ^=. Начиная с GMS2 введена поддержка тернарного оператора ?:. Операторы в GML могут быть разделены точкой с запятой, однако это не является обязательным условием (хотя и может привести к ошибке в некоторых специфичных случаях).
Game Maker содержит обширную библиотеку встроенных функций для обеспечения основной функциональности. Программист может создавать свои собственные скрипты с помощью ключевого слово «function»
function move(dx, dy, spd) { x += dx * spd y += dy * spd }
В аргументы dx, dy, spd можно засунуть абсолютно любой Тип данных (В том числе переменные), главное чтобы аргумент был осмысленным
Чтобы вызвать функцию нужно написать её название со скобками. В нашем случае это «move()», в скобках нужно написать нужное количество аргументов
move(2, 3, 10)
Данный код будет передвигать объект вправо на 20 пикселей (Так как 2 x 10 = 20) и вниз на 30 (Так как 3 x 10 = 30) пикселей
Функции рисования в Game Maker используют Direct3D API. При необходимости Game Maker также позволяет вызывать нативный код платформы посредством расширений (DLL на Windows, Java на Android, JS на HTML5 и т.п).
Обычно, GML не нужно предварительно объявлять переменную, как это делается в некоторых других языках. Переменная создается автоматически, сразу после присваивания ей какого-либо значения:
foo = "bar";
В Game Maker есть множество встроенных переменных и констант. Каждый экземпляр объекта содержит множество локальных переменных, например «х» и «у». Также существует несколько встроенных глобальных переменных, например «score». Эти переменные существуют независимо от экземпляров объектов. Эти переменные не содержат приставку «global.», в отличие от глобальных переменных, указанных программистом. Одномерные и двумерные массивы также поддерживаются.
В GML есть функции для создания и редактирования структур данных шести типов: стек, очередь, список, карта (ассоциативный массив), приоритетная очередь и сетка. К сетке, списку и карте также есть возможность доступа посредством аксессоров, предоставляющих синтаксис, подобный массивам:
var value = list[| 0]; // вместо ds_list_find_value(list, 0) map[? "name"] = "Username"; // вместо ds_map_add(map, "name", "Username") var value = map[? "name"]; // вместо ds_map_find_value(map, "name");
В GML поддерживаются следующие типы данных:
Хотя GML и можно рассматривать как объектно-ориентированный язык, природа объектов и экземпляров объектов в Game Maker создает некоторые важные отличия в способе разграничения переменных. Существует два типа локальности: локальность в объекте и локальность в скрипте (или другом куске кода, содержащемся в отдельном контейнере). То, что переменная является локальной для экземпляра объекта, означает, что переменная привязана к конкретному экземпляру объекта и извне этого экземпляра может быть использована только с приставкой, определяющей этот экземпляр; то, что переменная является локальной для скрипта, означает, что эта переменная может быть использована только в этом скрипте (и уничтожается после окончания скрипта). Далее термин «локальный» будет означать локальность в объекте. По умолчанию, переменная локальна для объекта, но не локальна для скрипта, в котором она используется. Для того чтобы сделать переменную доступной всем экземплярам объектов, она может быть определена через глобальное пространство имен:
global.foo = "bar";
Также существует возможность объявлять глобальные переменные используя ключевое слово globalvar:
globalvar foo, bar;
Но такого способа следует избегать, так как это может легко привести к сложно выявляемым ошибкам, из-за пересечения областей видимости переменных (то же самое рекомендуют и непосредственно разработчики GMS; более того, возможно, что в будущем это ключевое слово будет полностью убрано из языка - в данный момент оно оставлено исключительно из соображений обратной совместимости). Для того, чтобы сделать переменную локальной для скрипта, её нужно определять так:
var foo, bar;
Областью видимости локальной переменной является скрипт, внутри которого она объявлена. Это подразумевает, что при переключении контекста (c использованием with) она по-прежнему будет доступна. Например:
var foo = "bar"; with other { show_message(foo); // переменная foo доступна }
Доступ к локальным переменным объекта можно получить, используя идентификатор экземпляра объекта как приставку
instance.varname
но, тем не менее, таким образом невозможно получить локальные переменные одного скрипта из другого, пока они не передаются как параметры функции. Текущее пространство имен объекта может быть изменено с помощью конструкции «with». Например, следующий скрипт, если его поместить в событие столкновения, уничтожит другой экземпляр объекта, вовлеченный в это событие (заметим, что в событии столкновения Game Maker автоматически устанавливает переменную other на второй экземпляр объекта, с которым произошло столкновение):
with other { instance_destroy(); }
GML автоматически распределяет память под переменные на ходу, и использует динамические типы, поэтому присваивание переменным значения различных типов также возможно. Например, сначала можно создать целочисленную переменную, а потом изменить её на строковую:
intNumber = 1; intNumber = "Эта переменная теперь содержит строку";
В GML нет специального функционала, позволяющего освобождать память, занятую под переменную, однако при необходимости можно присваивать переменной новое значение, меньшего размера. Например, если у вас есть переменная, в которой хранится большой текст, то, присвоив переменной значение пустой строки, можно добиться высвобождения памяти. То же самое касается и массивов:
data = [1, 2, 3, 4, 5]; // создали массив (такой синтаксис создания массивов доступен начиная с GMS2) data = 0; // уничтожили массив (теперь это просто переменная)
При уничтожении объекта также уничтожаются все переменные, локальные для него, а любые глобальные переменные существуют независимо от них. Поэтому предпочтение нужно отдавать локальным переменным, а глобальные переменные использовать только в случае реальной необходимости этого. Для хранения больших объёмов информации более эффективно, в Game Maker есть поддержка нескольких структур данных - таких, как стек, очередь, список, карта, приоритетная очередь и сетка. Эти структуры создаются, модифицируются и уничтожаются посредством встроенных функций. Также есть функции практически во всех структурах для сортировки данных в них. В некоторых случаях более удобным и более эффективным будет использование буферов, позволяющих хранить произвольные данные и являющимися, по сути, просто выделенными кусками памяти.
В основе работы Game Maker с ресурсами лежат уникальные идентификаторы, которые служат для определения конкретного ресурса или экземпляра объекта. Эти идентификаторы могут быть использованы скриптами или функциями для указания необходимого ресурса. Так как создание ресурсов непосредственно в Game Maker подразумевает указание имени, то это имя служит константой, содержащей идентификатор ресурса. Идентификатор конкретного экземпляра хранится в локальной переменной «id». При динамическом создании ресурсов, всегда возвращается идентификатор созданного ресурса, который может быть использован в дальнейшем.
Вот простой пример скрипта, который выводит легендарную фразу «Hello, World!»:
show_message("Hello, World!");
Ещё один пример, который отображает тот же текст, но уже в окне программы. Заметьте, что по умолчанию Game Maker непрерывно перерисовывает окно, поэтому в обычном случае этот код нужно поместить в событие рисования.
draw_text(10, 10, "Hello, World!");
Вот фрагмент кода из игры на GML:
// это комментарий
/* Так комментарии пишутся в C++. */
/* определение временных переменных.
Эти переменные будут удалены после окончания скрипта.
Заметьте, что переменные не требуют никакого определения типа! */
var xx, yy, nn;
// Условие. Оно может быть сокращено до «if (can_shoot)».
if (can_shoot = true) // "=" и "==" могут быть использованы
{ // Начало блока кода. Вы можете также писать «begin» как в Pascal.
/* Устанавливаем переменную в ложь. То же самое можно написать и так: «can_shoot = 0;»
Так как Game Maker не различает булевские и целочисленные значения. */
can_shoot = false;
/* Здесь устанавливаем нулевой таймер на пять шагов.
Переменная таймера будет опускаться до 0, а когда достигнет его,
Событие нулевого счетчика будет вызвано. */
alarm[0] = 5;
/* Здесь локальная переменная xx определена как целочисленная,
И использована функция lengthdir_x. */
xx = x + lengthdir_x(14, direction);
yy = y + lengthdir_y(14, direction);
//Эта функция создает образец объекта obj_bullet и возвращает идентификатор нового объекта.
nn = instance_create(xx, yy, obj_bullet);
/* Оператор with позволяет вам обращаться к переменным объекта напрямую */
with (nn)
{
speed = obj_tank.speed + 3;
direction = obj_tank.direction;
}
}
Стили кода можно смешивать. Например, предыдущий пример может быть записан так:
var xx, yy, nn;
if can_shoot = true then begin
can_shoot := false
alarm[0] := 5
xx := x + lengthdir_x(14, direction)
yy := y + lengthdir_y(14, direction)
nn := instance_create(xx, yy, obj_bullet)
with nn begin
speed := obj_tank.speed + 3
direction := obj_tank.direction
end
end
Вот пример обычного управления с клавиатуры. Функция motion_set принимает два параметра: направление (в градусах) и скорость (пикселей за шаг). Вызов этой функции приведет к изменению встроенных локальных переменных speed и direction, которые использует Game Maker для перемещения объектов (объекты также можно сдвигать напрямую, используя локальные переменные x и y):
if (keyboard_check(vk_left)) motion_set(180,4);
if (keyboard_check(vk_up)) motion_set(90,4);
if (keyboard_check(vk_right)) motion_set(0,4);
if (keyboard_check(vk_down)) motion_set(270,4);
if (keyboard_check(vk_nokey)) motion_set(0,0);
А вот пример более сложного скрипта для платформенной игры. Используя его, игрок может ходить по выпуклой поверхности:
if !place_free(x-4,y)
{
if place_free(x-4,y-4)
{
x-=4
y-=4
}
else if place_free(x-3,y-5)
{
x-=3
y-=5
}
else if place_free(x-2,y-6)
{
x-=2
y-=6
}
}
else
x-=4
Код:
if i == 3{ if dir = 90{ dir = 0 i = 0 x += 1 } }
Можно сократить:
if i == 3 && dir == 90 {dir = 0; i = 0; x++}
С помощью сокращения вы сможете укротить свой код, сделать его более понятным, и просто красивее.
switch 0begin case 0:x=0break}
if a=0then begin b=1}else if a==0{b:=1end
Для улучшения этой статьи желательно:
|