Home (Русский) - nkrapivin/GMESCAPI GitHub Wiki
Добро пожаловать в вики GMESCAPI!
Сначала вам лучше ознакомиться с https://github.com/nkrapivin/GMESCAPI/wiki/Generic-Docs-(%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9)
Здесь я объясню как пользоваться расширением GMESCAPI.
Представим что вы уже импортировали расширение в свой проект и создали некий объект.
Снятие одного снимка
Сначала, сделайте переменные для высоты/ширины, переменной которая говорит что идёт запись, номера устройства, и айди асинхронного события:
width = 320;
height = 240;
busy = false;
device = 0;
async_id = -1;
Теперь, т.к. GameMaker не позволяет нам писать в видеопамять, единственный способ нормально получать данные с камеры это через буффер.
Я сделал небольшую функцию gm_escapi_offset
которая расчитывает размер для буффера чтобы он вместил n-снимков, ну или если у вас уже есть буффер с какими-то снимками, этой функцией можно расчитать позицию каждого снимка.
Используется она вот так:
buf = buffer_create(gm_escapi_offset(width, height, 1), buffer_fixed, 4);
Последний аргумент это сколько кадров мы планируем держать, одного хватит.
Буффер будет фиксированного размера, и выровнен по четырём байтам, т.к. один пиксель это как раз четыре байта.
А, и надо сделать переменную для сурфейса:
surf = -1;
Создавать сурфейсы в Create событии плохо, сделаем это в Draw.
Потом в каком нибудь событии нажатии клавиши сделайте вот так:
if (busy) exit;
busy = true;
async_id = gm_escapi_capture_async(device, width, height, buf, 0);
Здесь мы проверяем заняты ли мы, и если нет, начинаем запись.
Последний аргумент это сдвиг с которого нужно писать кадр, но т.к. у нас один буффер для одного кадра, ставим сдвиг 0.
Эта функция начнёт писать кадр в буффер в отдельном потоке, и вернёт айди операции, имейте ввиду что вы не можете начать запись больше одного раза для одной камеры, одно событие записи - одна камера. Иначе игра либо повиснет либо вылетит.
Результат операции будет возвращён в Async - Social событии (т.к. YoYo говорит в дллках использовать именно Social):
var ev_type = async_load[? "event_type"];
switch (ev_type)
{
case "escapi_capture_result":
{
var my_id = async_load[? "escapi_async_id"];
if (my_id != async_id) exit;
busy = false;
}
default: break;
}
Здесь мы проверяем что событие пришло от GMESCAPI, и что оно соответствует нашему async_id
, если всё хорошо, то мы ставим busy
в false (то есть мы свободны делать новый снимок), можете какой-то звук вспышки добавить или что-то ещё.
Теперь мы можем наконец отрисовать наш кадр в событии Draw:
if (busy) exit;
if (!surface_exists(surf)) surf = surface_create(width, height);
buffer_set_surface(buf, surf, 0, 0, 0);
draw_surface(surf, x, y);
Здесь, если мы сейчас не пишем снимок, мы создаём сурф если его нет, и копируем пиксели из буффера в сурф, а потом уже рисуем сурф.
Вы наверное заметили что код то работает, но картинка мыльная, это происходит из-за того что когда мы говорим камере сделать снимок, она не всегда сразу готова, нужно сфокусироваться.
Для установки времени на фокусировку используйте функцию gm_escapi_set_focus_frames
, она говорит сколько снимков нужно сделать в "пустую" просто для того чтобы камере было на что поймать фокус.
Вставьте эту строчку в конец Create:
gm_escapi_set_focus_frames(10); // adjust this please.
Это значит что вместо одного снимка, камера сделает десять, и потом уже вернёт десятый снимок вам. У камеры будет аж 9 кадров чтобы успеть поймать фокус. Но иногда этого не достаточно, сделайте настройку какую нибудь.
Продвинутое использование & играемся с яркостью
Сначала вам нужно сохранить текущие настройки камеры, например так:
// получить текущие настройки камеры
prop_values = array_create(CAPTURE_PROP_MAX);
prop_auto = array_create(CAPTURE_PROP_MAX);
gm_escapi_get_sys_capture_props(device); // или -1 для всех камер.
for (var i = 0; i < CAPTURE_PROP_MAX; i++) {
prop_values[i] = gm_escapi_get_capture_prop(device, i);
prop_auto[i] = gm_escapi_is_capture_prop_auto(device, i);
var val = string(prop_values[i] * 100) + "%";
if (val < 0) val = "N/A";
show_debug_message(val + " " + (prop_auto[i] ? "Авто" : "Вручную") + " " + gm_escapi_prop_reflection(i));
}
Теперь давайте выкрутим насыщенность на 100%:
// выкручиваем насыщенность
// все опции записи имеют значение от 0 до 1
// чтобы получить значение в процентах (0-100%) умножьте значение на 100
gm_escapi_set_capture_prop(device, CAPTURE_SATURATION, 1, false, false);
Ну и вообще можете ставить что хотите, только убедитесь что вас хотя бы видно :D
Не забудьте потом либо перед выходом из игры, либо из вашей менюшки, вернуть всё назад:
show_debug_message("восстанавливаем настройки...");
for (var i = 0; i < CAPTURE_PROP_MAX; i++) {
gm_escapi_set_capture_prop(device, i, prop_values[i], prop_auto[i], false);
}
// обычно настройки применяются после взятия снимка
// но у нас особая ситуация, нам нужно принять изменение без всяких снимков
// и эта функция как раз для этого. (но лампочка всё равно моргнёт)
gm_escapi_set_sys_capture_props(device);
Собсна всё, между сохранением и восстановлением можете творить магию.