Буферы

Материал из Вики по GameMaker
Перейти к: навигация, поиск

Буфер — это область памяти, в которой временно хранят данные, пока их перемещают из одного места в другое или обрабатывают. Например, в буфере можно хранить пакет данных в ожидании передачи его по сети или после его получения. Так как буфер хранится во внутренней памяти, он работает очень быстро.

Вот что нужно учитывать при работе с буфером:

  1. Когда буфер создан, он автоматически заполняется нулями.
  2. Размер буфера задаётся в байтах.
  3. Буфер выравнивает данные по заданной величине. Это означает, что каждая новая порция данных записывается не сразу после предыдущей, а в следующей позиции, кратной выравниванию.
  4. Смещение задаётся в байтах. Если выравнивание буфера равно 2, и вы хотите пропустить первые 4 выровненных позиции, укажите смещение в 2 × 4 = 8 байтов.
  5. Некоторые функции (например, buffer_load) создают новый буфер. Этот буфер, как и любой другой, нужно удалять из памяти при помощи функции buffer_delete.
  6. Буфер хранится в системной памяти, так что вы не потеряете данные, даже если игра потеряет фокус. Однако если закрыть и перезапустить приложение, вы потеряете данные в нём.

При создании буфера операционная система выделяет место в памяти, которое остаётся зарезервированным за игрой, пока вы её не закроете или не удалите буфер при помощи функции.

Если вы перезапустите игру, буфер останется в памяти, но вы не сможете получить к нему доступ, потому что потеряете его идентификатор. Это приведёт к утечке памяти, которая в конце концов обрушит вашу игру. Всегда удаляйте буфер перед перезапуском.

Содержание

[править] Типы буферов

GameMaker Studio создаёт буферы четырёх типов. Выберите тот тип буфера, который подходит для вашего случая, иначе буфер станет источником ошибок или бутылочным горлышком вашего кода.

тип описание
buffer_fixed Буфер фиксированного размера. Размер вы указываете при создании буфера и больше не можете его изменить.
buffer_grow Буфер, который будет расти по мере добавления в него данных. Вы создаёте буфер первоначального размера (который должен быть примерно равен размеру данных, которые вы собираетесь хранить), и он будет расширяться при переполнении.
buffer_wrap Буфер, в котором данные закольцованы. Когда буфер переполнен, новые данные запишутся в начало буфера, и дальнейшая запись продолжится с этой точки.
buffer_fast Специальный «урезанный» буфер, в котором данные считываются и записываются чрезвычайно быстро. Однако он работает только с двумя типами данных: buffer_u8 и buffer_s8 — и с выравниванием 1.

Справка GMS также упоминает тип buffer_vbuffer, но ничего про него не говорит.

[править] Типы данных

Данные записывают в буфер и считывают из него порциями, размер которых зависит от типа данных. Порции данных располагаются одна за другой — каждая своего типа.

тип размер, байты описание
buffer_u8 1 Беззнаковое 8-битное целое число (0...255)
buffer_s8 1 Знаковое 8-битное целое число (−128...+127)
buffer_u16 2 Беззнаковое 16-битное целое число (0...65 535)
buffer_s16 2 Знаковое 16-битное целое число (−32 768...+32 767)
buffer_u32 4 Беззнаковое 32-битное целое число (0...4 294 967 295)
buffer_s32 4 Знаковое 32-битное целое число (−2 147 483 648…+2 147 483 647)
buffer_f16 2 16-битное число с плавающей точкой (пока не поддерживается)
buffer_f32 4 32-битное число с плавающей точкой
buffer_f64 8 64-битное число с плавающей точкой
buffer_bool 1 Двоичное число
buffer_string 1—6 на символ Строка любого размера в кодировке UTF-8, после которой стоит символ Nul
buffer_text 1—6 на символ Строка любого размера в кодировке UTF-8 без Nul.

[править] Выравнивание

Буфер, выровненный по одному байту, записывает каждую новую порцию данных сразу после предыдущей. Буфер с выравниванием по двум байтам записывает новую порцию данных через интервал в два байта, то есть, если вы запишите один байт, следующая запись будет сдвинута относительно предыдущей не на один, а на два байта.

Выравнивание влияет только на то, где будут записаны данные. Например, если вы запишите один байт в буфер, выровненный по четырём байтам, функция buffer_tell вернёт смещение в 1 байт (в данном случае смещение — это количество байт от начала буфера до текущей позиции записи или чтения). Если вы теперь запишите ещё один байт и снова вызовите buffer_tell, она теперь уже вернёт смещение в 5 байт (несмотря на то, что вы записали только два байта), потому что к записи было добавлено пустое поле, чтобы выровнять её по четырём байтам. Обратите внимание, что буфер сначала добавляет пустое поле для выравнивания, а потом уже записывает данные, так что buffer_tell возвращает позицию, следующую сразу после записанных данных.

[править] Запись и считывание строк

Чтобы строку можно было прочитать из буфера, нужно как-то обозначить, где она заканчивается. Традиционно для этого используют символ Nul (код 0 в ASCII). Строку, заканчивающуюся символом Nul, называют нуль-термированной строкой. Функция buffer_read считывает байты из буфера, пока не дойдёт до Nul или конца буфера.

Попробуем записать в буфер две строки: «Game» и «Maker», указав тип buffer_string:

buff = buffer_create(11, buffer_fixed, 1);
buffer_write(buff, buffer_string, "Game");
buffer_write(buff, buffer_string, "Maker");
buffer_seek(buff, buffer_seek_start, 0);
show_message(buffer_read(buff, buffer_string));

После выполнения программы буфер будет выглядеть так:

символ G a m e nul M a k e r nul
код 71 97 109 101 0 77 97 107 101 114 0

Программа покажет сообщение «Game».

Теперь попробуем записать в буфер эти же две строки, но теперь укажем тип buffer_text:

buff = buffer_create(11, buffer_fixed, 1);
buffer_write(buff, buffer_text, "Game");
buffer_write(buff, buffer_text, "Maker");
buffer_seek(buff, buffer_seek_start, 0);
show_message(buffer_read(buff, buffer_string));

После выполнения программы буфер будет выглядеть так:

символ G a m e M a k e r nul nul
код 71 97 109 101 77 97 107 101 114 0 0

Программа покажет сообщение «GameMaker».


Подводя итог, для записи строк в общем случае используйте тип buffer_string, а тип buffer_text — когда нужно записать строку по частям. Также следует помнить, что Nul занимает в буфере дополнительный байт.

В кодировке UTF-8 символ занимает от одного до шести байт. Например, символы кириллицы занимают два байта. Поэтому, чтобы определить размер строки в байтах, следует использовать не string_length, а string_byte_length.

[править] Функции

Для работы с буферами используйте следующие функции:

buffer_create
buffer_create_from_vertex_buffer
buffer_create_from_vertex_buffer_ext
buffer_delete
buffer_read
buffer_write
buffer_fill
buffer_seek
buffer_tell
buffer_peek
buffer_poke
buffer_save
buffer_save_ext
buffer_save_async
buffer_load
buffer_load_ext
buffer_load_async
buffer_async_group_begin
buffer_async_group_option
buffer_async_group_end
buffer_copy
buffer_copy_from_vertex_buffer
buffer_get_address
buffer_get_size
buffer_get_surface
buffer_set_surface
buffer_resize
buffer_sizeof
buffer_md5
buffer_sha1
buffer_base64_encode
buffer_base64_decode
buffer_base64_decode_ext
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты