Всем привет! Меня зовут Данил Рафиков и я решил присоединиться к блогу econdude.pw в качестве соавтора статей. У меня есть YouTube канал - HavingTeam где вы можете найти мои уроки по Game Maker.
Я планирую периодически писать в этом блоге статьи про Game Maker Studio и на тему программирования, постараюсь делать статью к каждому новому видео на моём канале (выходит 1-2 раза в месяц).
Например, вот моё последнее видео:
Например, вот моё последнее видео:
Основы Game Maker #20
Продвинутое использование буферов (Копирование, Сурфейсы, SHA-1)
Сегодня я хочу вам рассказать о продвинутом использовании буферов. Затронем такие темы как копирование данных из одного буфера в другой, загрузка и выгрузка сурфейса в буфере, MD5 и SHA-1 хеширование.
- Первый аргумент этой функции требует буфера, откуда вы хотите скопировать данные.
- Второй означает уровень смещения, иными словами с какой позиции начинать копировать.
- Третий значит размер этого буфера. Тут можно написать buffer_get_size(искомый буфер).
- Четвертый аргумент- это буфер, куда копировать.
- Ну и последний аргумент - уровень смещения в буфере, куда будем копировать данные.
Если у вас заранее там записаны какие-то данные, то здесь надо написать buffer_tell(буфер) - функция, возвращающая последнюю позицию в буфере.
Обязательно стоит учесть, что при копировании, смещение в буфере не произойдет как при записи. Надо будет в конце перемотать буфер на конец функцией buffer_seek(буфер, buffer_seek_end, 0), buffer_seek_end - перематывает на конец буфера.
Если не учесть это правило, то при отправке буфера в Networking вы отправите "кусок" буфера, а не его целую часть.
Оформим это дело в коде. Создадим растущий буфер buff_1 и запишем в него 4 байта:
#Create
buff_1 = buffer_create(1,buffer_grow,1);
buffer_write(buff_1,buffer_u16,mouse_x);
buffer_write(buff_1,buffer_u16,mouse_y);
Теперь создадим аналогичный буфер buff_2 и внесем туда строковое значение:
buff_2 = buffer_create(1,buffer_grow,1);
buffer_write(buff_2,buffer_string,"Hello").
Теперь прописываем само копирование:
buffer_copy(buff_1,0,buffer_get_size(buff_1),buff_2,buffer_tell(buff_2));
Из этой строки получается, что 4 байта пойдут после строкового значения.
Сделаем вывод. Будем копировать значения buff_1 в buff_2 при нажатии клавиши 1.
#Step
Пишем:if keyboard_check(ord("1"))
{
buffer_copy(buff_1,0,buffer_get_size(buff_1),buff_2,buffer_tell(buff_2))
}
После копирования нам надо перемотать буфер на начало, так как если мы начнем его читать в таком виде, то вылезет ошибка о том, что мы читаем за границей буфера.
Перемотать на начало можно buffer_seek(buff_2,buffer_seek_start,0), buffer_seek_start – перемотка на начало буфера.
Перемотать на начало можно buffer_seek(buff_2,buffer_seek_start,0), buffer_seek_start – перемотка на начало буфера.
Получается так:
buffer_seek(buff_2,buffer_seek_start,0);
И сделаем вывод:
var str = buffer_read(buff_2,buffer_string);
var mx = buffer_read(buff_2,buffer_u16);
var my = buffer_read(buff_2,buffer_u16);
show_message(string(str)+" | mouse_x : "+string(mx)+" | mouse_y : "+string(my)).
Запускаем. Нажимаем 1 и видим, что данные из буфера успешно скопированы в другой.
Теперь приступим к загрузке сурфейса в буфер. Зачем это надо?
Вообще иногда нужно сохранять сурфейсы так, чтобы их никто не смог редактировать и нужна быстрая загрузка.
Буфера идеально справляются с этой задачей.
#Create
Создадим сурфейс surf. Сделаем его белым:surf = surface_create(room_width,room_height);
surface_set_target(surf);
draw_clear_alpha(c_white,1);
surface_reset_target();
Стоит обязательно учесть, что сурфейсы могут пропадать при взаимодействии с окном приложения. Создадим для этого скрипт surface_rebuilding(), который будет пересоздавать сурфейс в случае его исчезновения.
#Scripts
surface_rebuilding();
surface_create(room_width,room_height);
surface_set_target(surf);
draw_clear_alpha(c_white,1);
surface_reset_target();
Теперь отрисовываем его.
#Draw
if surface_exists(surf) // Проверяем наличие сурфейса
{
draw_surface(surf,0,0);
}
else // Если его нет
{
surface_rebuilding(); // Применяем наш скрипт
}
Сделаем рисование на сурфейсе:
if mouse_check_button(mb_left)
{
surface_set_target(surf);
draw_circle(mouse_x,mouse_y,8,false);
surface_reset_target();
}
#Step
Теперь надо сделать сохранение сурфейса в буфер.
Тут надо учесть то, что вы должны создать буфер, у которого размер будет заранее подготовлен для сурфейса. Ибо даже растующий буфер автоматически не выделит места.
Как посчитать размер сурфейса? Очень просто.
Берете размеры сурфейса, в моем случае это размеры комнаты, умножаете их, и умножаете еще на 4.
Тут надо учесть то, что вы должны создать буфер, у которого размер будет заранее подготовлен для сурфейса. Ибо даже растующий буфер автоматически не выделит места.
Как посчитать размер сурфейса? Очень просто.
Берете размеры сурфейса, в моем случае это размеры комнаты, умножаете их, и умножаете еще на 4.
Получается так:
var buff_size = room_width*room_height*4;
Теперь, при нажатии клавиши 2 будем сохранять сурфейс в буфер. Заранее стоит проверить, существует ли сурфейс, чтобы избежать ошибки, прописываем перед нажатием клавиши условие:
if surface_exists(surf)
Если нет, то применяем наш скрипт surface_rebuilding();
Получается так:
if surface_exists(surf)
{
if keyboard_check(ord("2"))
{
var buff_3 = buffer_create(buff_size,buffer_grow,1);
}
}
else
{
surface_rebuilding();
}
Чтобы загрузить сурфейс в буфер существует функция buffet_get_surface.
Первый аргумент значит буфер, куда будем копировать.
Второй - это сурфейс, который копировать.
Третий - данные, которые получить с сурфейса. Здесь ставим значение 0, то есть это будет значит, что мы будем копировать все данные с сурфейса.
Четвертый аргумент - это уровень смещения в буфере, то есть в какую позицию копировать данные, ну и пятый - это смещение от конца линии к началу следующего, ставим здесь 0.
Первый аргумент значит буфер, куда будем копировать.
Второй - это сурфейс, который копировать.
Третий - данные, которые получить с сурфейса. Здесь ставим значение 0, то есть это будет значит, что мы будем копировать все данные с сурфейса.
Четвертый аргумент - это уровень смещения в буфере, то есть в какую позицию копировать данные, ну и пятый - это смещение от конца линии к началу следующего, ставим здесь 0.
#Step
Получается это так:buffer_get_surface(buff_3,surf,0,0,0);
Теперь сохраняем буфер в файл:
buffer_save(buff_3,"surface.b");
И удаляем буфер для освобождения памяти:
buffer_delete(buff_3);
Теперь сделаем загрузку сурфейса из буфера.
Загрузка будет происходит при нажатии клавиши 3:
if keyboard_check(ord("3"))
{
if file_exists("surface.b") // Проверяем, есть ли наш файл с буфером{
var buff_4 = buffer_load("surface.b") //Загружаем буфер
}
}
Для выгрузки сурфейса из буфера есть функция buffer_set_surface.
Ее аргументы аналогичны той функции, что загружает сурфейс в буфер. Но мы здесь уже выгружаем сурфейс.
Обязательно проверяем, есть ли наш сурфейс, если нет, то пересоздаем его.
Получается так:
if surface_exists(surf)
{
buffer_set_surface(buff_4,surf,0,0,0);
}
else
{
surface_rebuilding();
}
Теперь удалим буфер:
buffer_delete(buff_4);
Запускаем.
Давайте что-нибудь нарисуем. Теперь загружаем сурфейс в буфер и сохраняем его клавишей 2. Сохранили. Чего-нибудь еще нарисуем. Загрузим сурфейс клавишей 3. Отобразилась наша первая фигура, а другая удалилась, так как ее не было до загрузки сурфейса в буфер.
Переходим к хешированию MD5 и SHA-1. Их надобность в том, что они позволяют проверять целостность буфера. Это может помочь в том случае, когда у вас сохранение работает на буферах, и вам нужно проверить наличие изменений в файле сохранения. По-другому это защита. То есть MD5 и SHA-1 возвращают контрольную сумму буфера. Вы занесли в него какие-то данные и из этого получается некоторое значение для проверки целостности данных.
Данные будут проверяться так: мы будем записывать в буфер после записи всех нужных данных контрольную сумма. И при загрузке будем возвращать контрольную сумму загруженных данных и сверять их с записанной контрольной суммой.
Если оба значения будут равны, то это будет значит, что файл не подвергался модификации. Приступим к реализации. Возьмем SHA-1, так как он лучше MD5 в плане безопасности хеширования данных.
Данные будут проверяться так: мы будем записывать в буфер после записи всех нужных данных контрольную сумма. И при загрузке будем возвращать контрольную сумму загруженных данных и сверять их с записанной контрольной суммой.
Если оба значения будут равны, то это будет значит, что файл не подвергался модификации. Приступим к реализации. Возьмем SHA-1, так как он лучше MD5 в плане безопасности хеширования данных.
#Step
При нажатии клавиши 4 мы будем записывать в буфер какое-нибудь значение, далее его сохранять. После этого будем загружать клавишей 5. Тут же встроим SHA-1 хеширования.
if keyboard_check(ord("4"))
{
var buff_5 = buffer_create(1,buffer_grow,1);
buffer_write(buff_5,buffer_string,get_string("Ваше секретное слово","")); // Тут записываем какое нибудь значение
}
Теперь нам надо после этого записать в буфер строковое значение, полученное функцией buffer_sha1. Первый аргумент значит буфер, из которого составить контрольную сумму, второй - уровень смещения, с какой позиции хешировать, третий - размер буфера, тут прописываем buffer_tell(buff_5).
Записываем:
buffer_write(buff_5,buffer_string,buffer_sha1(buff_5,0,buffer_tell(buff_5)));
Теперь сохраняем буфер в файл:
buffer_save(buff_5,"buffer.b");
И удаляем его:
buffer_delete(buff_5);
Осталось добавить загрузку буфера:
if keyboard_check(ord("5"))
{
if file_exists("buffer.b") // Проверяем наличие файла
{
var buff_6 = buffer_load("buffer.b"); //Загружаем буфер
var str = buffer_read(buff_6,buffer_string); // Читаем из него записанное значение
var sha_1_test = buffer_sha1(buff_6,0,buffer_tell(buff_6)); // Возвращаем контрольную сумму данных в буфере, не считая той контрольной суммы, которую мы записали.
var sha_1_check = buffer_read(buff_6,buffer_string); // Читаем записанную контрольную сумму
if sha_1_test == sha_1_check // Проверяем, равны ли получены значения
{
show_message(string(Str));
}
else // Если нет
{
show_message("Файл был подвергнут модификации!")
}
}
}
Вот мы и рассмотрели 3 варианта использования буферов в Game Maker Studio.
Всем спасибо за внимание!
Исходник: Advanced Buffers.gmz
Всем спасибо за внимание! Я надеюсь что у нас с Econ Dude получиться долгое и плодотворное сотрудничество. В скором времени в шапке этого блога появиться новая страница где я буду собирать все свои статьи и уроки. Так-же, возможно, с моей помощью мы прокачаем дизайн этого блога, так-как кроме Game Maker я изучаю еще и web языки.
Подписывайтесь на мой YouTube канал HavingTeam и ждите новых статей тут!