Аксессоры к структурам данных и массивам в GameMaker: Studio

Перевод: Dmi7ry
Оригинал: James Foreman

Последнее обновление (начиная с версии 1.2.1261]) GameMaker: Studio добавляет интересный дополнительный функционал для некоторых структур данных и обычным массивам, называемый “аксессоры” (Accessors, методы доступа). Эти аксессоры являются простыми логическими выражениями, которые позволяют вам добавлять или изменять значения в этих структурах и записываются таким образом, будто вы работаете с массивами, с тем отличием, что используется специальный идентификационный символ перед первым аргументом, который говорит GameMaker: Studio, что вы работаете со структурой данных (заранее созданной), либо напрямую с исходным массивом.

Вы можете добавлять, заменять и получать значения и ключи для следующих типов структур данных: ds_maps, ds_lists и ds_grids, каждый из которых имеет свой собственный символ для доступа, изменения или установки значения, как показано ниже. Для массивов этот функционал даёт вам прямой доступ к исходному массиву, передаваемому в скрипт, взамен стандартного поведения, когда передаётся копия массива, которое обычно и ожидается (это объясняется в конце статьи).

Также обратите внимание, что символы, выбранные для обозначения метода доступа, были выбраны в соответствии с их мнемонической природой (например, # – это идентификатор для ds_grid), что делает их более лёгкими для опознавания и запоминания.

ds_list [| ]

Синтаксис для списков следующий:

list_index[| index]

После создания списка с помощью ds_list_create(), вы можете использовать индекс списка, который у вас сохранён в переменной, для обращения к нему. Значение index здесь указывает на позицию элемента в списке, который вы хотите добавить или установить. Например, следующий код создаёт список и добавляет 10 записей, каждая из которых будет содержать случайное число от 0 до 9:

ds = ds_list_create();

var index = 0;

repeat(10)
{
    ds[| index++] = irandom(9);
}

После создания вашего списка и заполнения его данными, чтобы получить значение из списка, нужно сделать что-нибудь типа этого:

value = ds[| 5];

Этот код получает значение из элемента 5 (но это шестая позиция в списке, так как нумерация начинается с нуля) и сохраняет его в переменную. Обратите внимание, что если вы используете выражение для добавления ссылки на элемент, который уже имеет значение, то предыдущее значение будет заменено новым, а не просто добавится в список. Чтобы добавить дополнительные элементы, нужно узнать размер структуры данных (ds_list_size) и добавить их в её конец. Ещё нужно отметить, что вы также можете задать индекс элемента больше, чем их количество в списке – в этом случае установится заданный элемент, одновременно увеличивая список и заполняя все предыдущие элементы нулём.

ds​_map [? ]

Синтаксис для карт следующий:

map_index[? key]

После создания вашей карты с помощью ds_map_create(), вы должны использовать индекс карты, сохранённый в переменной, чтобы обращаться к ней. Значение “key” указывает на ключ карты, который необходимо записать или прочитать. Например, следующий код создаёт карту и после добавляет несколько записей, используя этот синтаксис:

ds = ds_map_create();

ds[? "Name"] = "Hamish";

ds[? "Company"] = "MacSeweeny Games";

ds[? "Game"] = "Catch The Haggis";

После создания вашей карты и заполнения её данными, чтобы получить значения из карты, нужно сделать что-нибудь типа этого:

value = ds[? "Name"];

Этот код получает значение из ключа “Name” и сохраняет его в переменную. Обратите внимание, что если при записи значения, в карте уже содержится запись с таким ключом, то предыдущее значение будет заменено новым.

ds_grid [# ]

Синтаксис для сеток следующий:

grid_index[# xpos, ypos]

После создания вашей сетки с помощью ds_grid_create(), вы должны использовать индекс сетки, сохранённый в переменной, чтобы обращаться к ней. Значения “xpos” и “ypos” указывают на элемент сетки, который необходимо записать или прочитать. Например, следующий код создаёт сетку, очищает её нулём и после добавляет несколько записей в неё:

ds = ds_grid_create();

ds_grid_clear(ds, 0);

var gw = ds_grid_width(ds) - 1;

var gh = ds_grid_height(ds) - 1;

repeat(10)

{
    var xx = irandom(gw);

    var yy = irandom(gh);

    if ds[# xx, yy] == 0 ds[# xx, yy] = 1;
}

Когда у вас есть созданная и заполненная данными сетка, для чтения элемента в заданной позиции, можно использовать что-нибудь вроде:

value = ds[# mouse_x div 16, mouse_y div 16];

Этот код получает значение из сетки, основываясь на координатах мыши (поделенных на размер “клетки” в комнате, чтобы получить корректную позицию).

Массивы.

Обычный метод работы GameMaker: Studio с массивами – “копирование при записи”, означающий, что при передаче массива (как пример) в скрипт, передаётся ссылка на оригинальный массив, но при изменении любого значения массива, будет создана копия массива. Это означает, что для того, чтобы получить новые значения, которые вы установили, вы должны вернуть массив из скрипта и переназначить его исходной переменной массива. Например:

//CREATE EVENT
a[9] = 0; //initialise a 10 value array

​
//CALL A SCRIPT WITH THE ARRAY
a = scr_Set_Array(a);

 
//SCRIPT
var temp_a = argument0;

temp_a[3] = 10;

return temp_a;

Однако, это может быть весьма ограниченно и также очень медленно, особенно когда у вас очень большой массив и он копируется каждый раз при запуске скрипта. Но теперь есть аксессор для работы с массивами, с следующим синтаксисом:

array[@ val]; //1D array

array[@ val, val]; //2D array

Это делает запись напрямую в исходный массив, что означает отсутствие необходимости создания собственной копии массива в скрипте. Используя код выше в качестве эталона, вы можете поменять его на это:

//CREATE EVENT
a[9] = 0; //initialise a 10 value array


//CALL A SCRIPT WITH THE ARRAY
a = scr_Set_Array(a);


//SCRIPT
var temp_a = argument0;

temp_a[@ 3] = 10;

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

Leave a Reply

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.