Игры с веб-камерой: как я сделал игру про бег от динозавра
Я хотел сделать игру про бег, в которой нажатая клавиша бегом не считается. Остановился сам, значит, остановился и персонаж. Нашёл ещё один рывок, значит, побег должен стать легче. А если игрок просто машет руками перед камерой, игра должна понять, что это не бег.
Из этой идеи родился Dino Survival, браузерная игра, где нужно бежать на месте, чтобы убежать от T-Rex. В одном предложении звучит просто. А на деле пришлось решать куда более сложный вопрос: как заставить веб-камеру превратить движущееся тело в контроллер, которому веришь?
Почему играм с веб-камерой нужен контроллер другого рода
В большинстве бесконечных раннеров движение сведено к кнопке, свайпу или автоматической скорости вперёд. Это удобно, потому что ввод точный: кнопка либо нажата, либо нет.
С телом всё запутаннее. У людей разный рост, разные комнаты, разные углы камеры и разная манера бега. Колени могут уйти за нижний край кадра. Одежда может скрыть сустав. В полумраке точка на камере дрожит, даже когда человек просто стоит.
Поэтому привязать одну позу к одной скорости было нельзя. Нужен был конвейер, который наблюдает за движением во времени, отсекает шум и всё равно отвечает достаточно быстро, чтобы не терялась связь с телом:
- Запросить у браузера доступ к камере.
- Оценить точки тела в каждом кадре видео.
- Измерить попеременные движения ног и движение всего тела.
- Превратить недавние шаги в минуту в устойчивый игровой темп.
- Использовать этот темп, чтобы двигать бегуна и менять разрыв до динозавра.
Разрешение на камеру браузер обрабатывает через MediaDevices.getUserMedia(). Dino Survival запрашивает только видео и использует фронтальную камеру, если она есть. Живые кадры потом обрабатывает модель позы прямо в браузере.
Точки позы ещё не бег
В Dino Survival работает MediaPipe Pose Landmarker в видеорежиме. Модель умеет возвращать 33 точки тела, но больше данных ещё не значит, что контроллер получится лучше.
Для каденса я беру меньшую группу: плечи, бёдра, колени и лодыжки. Плечи и бёдра дают приблизительную ось корпуса. Колени и лодыжки показывают, как двигаются ноги относительно этой оси.
Эти относительные измерения важны. Если бы я мерил только то, как высоко колено оказывается на экране, результат менялся бы от наклона телефона или от того, что игрок стоит не по центру. Когда движение ног проецируется на ось корпуса самого игрока, детектор меньше зависит от того, как закреплена камера.
Игра также проверяет, что оба бедра и оба колена видны. Если нет, она просит отойти назад, а не молча выдумывает темп по неполным данным. В играх с управлением движением честная обратная связь лучше, чем притворство, будто ввод надёжен.
Как попеременные ноги превращаются в каденс
Бег на месте создаёт повторяющийся рисунок. Одно колено поднимается, достигает пика и опускается. Потом то же делает другая нога. Детектор следит за движением колен и лодыжек и ищет эти чередующиеся пики.
Для каждой ноги я использую адаптивные пороги, потому что одно фиксированное число не подходит всем телам и камерам. Высокий игрок может дать на экране гораздо большее движение, чем невысокий, который стоит дальше. Детектор подбирает полезный локальный диапазон, а жёсткий потолок не даёт этой подстройке стать слишком мягкой.
После засчитанного пика та же нога на 130 миллисекунд попадает в короткий рефрактерный период. Он не позволяет дрожанию точек у верхней границы подъёма колена превратиться в два-три выдуманных шага. Засчитанные шаги попадают в скользящее окно в три секунды: достаточно длинное, чтобы сгладить число, и достаточно короткое, чтобы заметить настоящую смену усилий.
Если шагов нет примерно 1,1 секунды, каденс сразу сбрасывается в ноль. Резкий сброс мне нравится больше, чем долгое плавное затухание. Остановился игрок, остановилась и игра.
Как я не дал взмахам рук стать спринтом
Первые системы распознавания движений часто награждают любую активность в кадре. Тут же находится очевидная лазейка: не двигай ногами, шевели руками. А ещё тряска камеры начинает выглядеть как тренировка.
В Dino Survival есть второй барьер, основанный на бёдрах. Он ищет настоящее вертикальное покачивание тела за короткий промежуток. Каденс засчитывается, только когда рисунок попеременных ног и это более широкое движение согласуются.
Оценивать чью-то технику бега игра не пытается. Она лишь требует доказательств, что работает нижняя часть тела. Одни движения рук барьер не открывают, а крошечный шум в оценке позы бегуна вперёд не толкает.
Это один из главных уроков, который я вынес из работы над играми с веб-камерой: хороший ввод означает не поиск как можно большего движения, а поиск правильного движения и понятное объяснение, когда камера его не видит.
От шагов в минуту к погоне за динозавром
Детектор каденса выдаёт шаги в минуту, но играм не нужны лабораторные измерения. Нужен понятный и играбельный сигнал. Я раскладываю результат по трём понятным уровням усилия: трусца около 70 шагов в минуту, бег 120 и спринт 160.
Эти уровни превращаются в нормированный темп. Движок выживания использует его, чтобы продвигать игрока к цели побега в 50 единиц. А у динозавра тем временем своя скорость, которая растёт по ходу забега.
Разрыв меняется в зависимости от разницы между этими двумя скоростями. Бежишь быстрее динозавра: между вами появляется расстояние. Сбавил темп: он начинает догонять. Добежал до джипа: ты спасён. Дал разрыву упасть до нуля: погоня окончена.
Именно это отличает игру от обычной игры про бег от динозавра. Динозавр здесь не таймер с зубами. Он наглядно показывает, какие усилия ты вкладываешь прямо сейчас.
Мир движется, только пока движется игрок
Тропа собрана из последовательности кадров джунглей. Листаются они по накопленной дистанции, а не по часам. Игрок перестал бежать, и окружение замерло. Побежал снова, и тропа поплыла под бегуном.
Видимый размер и положение динозавра привязаны к разрыву. Чем он ближе, тем больше места занимает в сцене. Пыль, линии скорости и индикатор темпа повторяют ту же мысль. Много маленьких сигналов отвечают на один вопрос: ухожу ли я?
Цикл отрисовки использует requestAnimationFrame(): он просит браузер выполнить анимацию перед следующей перерисовкой. По метке времени в колбэке я считаю прошедшее время, так что движение зависит от времени, а не от предположения, что все устройства рисуют одинаковое число кадров в секунду.
Бегуна я рисую заранее, а не вырезаю живого человека из кадра и не вставляю его в сцену каждый раз. Это снижает нагрузку на графику на мобильных устройствах и даёт игре единого персонажа. Веб-камера здесь контроллер, а не готовая картинка.
Почему калибровка часть дизайна игры
Настройка камеры не технический экран, который можно спрятать от игрока. Это первый уровень.
Dino Survival показывает рамку кадрирования и ждёт, пока нужные точки станут видны. Она объясняет, когда нужно отойти назад, и перед погоней даёт игроку короткий обратный отсчёт. В этот момент и заключается договор: держи нижнюю часть тела в кадре, беги на месте, и игра пойдёт за тобой.
Есть и демо на клавиатуре. С ним можно познакомиться с игрой без разрешения на камеру, проверить её на неподдерживаемой конфигурации или просто сначала разобраться в правилах. Полноценный опыт всё равно даёт версия с камерой, потому что смысл игры в физической связи между усилием и побегом.
Что я понял, делая Dino Survival
Трудно было не нарисовать T-Rex. Трудно было решить, что считать шагом.
Надёжному контроллеру тела нужно несколько скромных проверок, работающих вместе. Точки определяют, где находится тело. Чередующиеся пики колен и лодыжек намекают на каденс. Движение бёдер подтверждает, что игрок действительно бежит. Скользящее окно сглаживает результат. Быстрый сброс в ноль не даёт схитрить с остановкой. А игровой движок превращает этот сигнал в разрыв, который игрок понимает без инструкции.
Именно этим мне и нравится управление движением в браузере. Когда обратная связь верна, технологии исчезают. Ты не думаешь о точках, порогах и метках времени кадров. Ты видишь динозавра, слышишь, как он приближается, и бежишь.
О дизайне и исследованиях читай в статье о том, почему я считаю, что Dino Survival правильная игра для тренировки.
Можно бесплатно сыграть в Dino Survival в браузере, скачивать ничего не нужно. А если хочешь увидеть, как тот же конвейер с веб-камерой справляется с движениями верхней части тела, прочитай, как я делал Monster Punch, онлайн-игру про бокс. Больше игр, которые запускаются сразу, ищи в моём обзоре бесплатных игр без загрузки.