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 структурно схожий на мову С своїми блоками коду, викликами функцій, привласненням змінних, синтаксисом операторів і так далі. GML розрізняє оператори і вирази. Наприклад,

g < 1;

не є правильним оператором і викличе помилку. Також, присвоювання змінних - це завжди оператор, і тому не може бути використаний в виразах. Наприклад, наступний рядок завжди генерувала б помилку тому, що вона б обчислювала вкладене вираз як true або false, а потім порівнювала б булевий результат з рядком «Yes» (неправильне порівняння):

if ((answer = get_string("Yes or No?", "")) == "Yes")

Варто пам'ятати, що знак рівності «=» є оператором присвоєння і булевих оператором порівняння в виразах, тоді як в С ++ у виразах пишуть подвійний знак «==». Проте, подвійний знак одно «==» буде правильно інтерпретований в разі використання його в виразах. Використання такого знака в якості оператора присвоєння викличе помилку виконання. GML також підтримує оператори інкремента :

g ++; // підтримується як Постфіксний, так і префиксная запис 

і

g += 1;

те ж саме, що і

g = g + 1;

Також існують оператори: - =, * =, / =, | =, & = і ^ =. Починаючи з GMS2 введена підтримка тернарного оператора?:. Оператори в GML можуть бути розділені крапкою з комою, однак це не є обов'язковою умовою (хоча і може привести до помилки в деяких специфічних випадках).

ФункціїРедагувати

Game Maker містить велику бібліотеку вбудованих функцій для забезпечення основної функціональності. Програміст може створювати свої власні скрипти, які викликаються точно таким же способом, як і функції. Функції малювання в 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 підтримуються наступні типи даних:

  • string (рядок) - послідовність символів, укладених в одинарні або подвійні лапки (починаючи з GMS2 слід використовувати подвійні лапки).
  • real (число) - ціле або з плаваючою комою. Хоча все значення, створені в GML, зберігаються як числа з плаваючою комою подвійної точності, для роботи з розширеннями можна використовувати і інші типи
  • array (масив) - змінна, яка використовує індекси для доступу до елементів. Можуть містити будь-які дані - числа, рядки, інші масиви, дескриптори інших структур даних і т.п. Їх також можна передати як параметр у функцію, і вони можуть бути повернуті функцією як результат.
  • boolean - може приймати значення true або false. Майте на увазі, що в даний час GML не підтримує «справжні» булеві значення і насправді приймає як false будь-які числа менше 0.5, а все, що дорівнює або більше - як true.
  • pointer (покажчик) - покажчик на область пам'яті. Використовується в деяких специфічних функціях на кшталт buffer_get_address () і ін.
  • enum (перерахування) - задана користувачем колекція констант, що зберігаються в змінної.
  • undefined (не задано) - спеціальне значення, що повертається у випадках, коли запитувані дані не знайдені.

Область дії зміннихРедагувати

Хоча 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:

// це коментар

/ * Так коментарі пишуться в С ++. * /

/ * Визначення тимчасових змінних.

   Ці змінні будуть видалені після закінчення скрипта.

  Зауважте, що змінні не вимагають ніякого визначення типу! * /

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

КритикаРедагувати

Вільний синтаксис GML полегшує створення ігор в певній мірі, але може породити абсолютно нечитабельним код:

switch 0begin case 0: x = 0break}

  if a = 0then begin b = 1} else if a == 0 {b: = 1end

Хоча це і не частина мови, ще одним поширеним приводом для критики старих версій Game Maker був сам процес створення EXE-файлів, які складаються з завантажувача і ресурсів GM-файлу. При запуску такої гри, код розбирається на абстрактне синтаксичне дерево (використовувалася інтерпретація коду), що полегшувало декомпіляцію і суттєво збільшувало час завантаження. Однак в більш сучасних версіях (GameMaker: Studio) механізми були змінені, тому немає ніяких проблем ні зі швидкістю запуску, ні з декомпіляцією (декомпілятори для GMS не існує).

ЛітератураРедагувати

  • Matthew DeLucas. GameMaker Game Programming with GML. — Packt, 2014. — 350 p. — ISBN 978-1-78355-944-2.

Див. такожРедагувати