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);

Собсна всё, между сохранением и восстановлением можете творить магию.