Механика времени: как таймер добавляет в расследование напряжение.
Привет. В посте про карту я обмолвился, что про таймер расскажу отдельно. Выполняю. Сегодня - про то, как в моём детективе устроено время, зачем оно вообще нужно и как это работает в коде.
Зачем детективу таймер?
Казалось бы - расследование, вникай себе спокойно, зачем гнать. Но вот в чём фокус: без ограничения времени детектив теряет напряжение. Можешь обыскать каждый угол, опросить всех по десять раз, перепробовать все варианты. Мне кажется, скучно и беззубо.
Время всё меняет. Оно превращает расследование в выбор. У тебя всего 6 часов - и ты физически не успеешь сделать всё. Пойти на маяк или в клуб? Дожать свидетеля или осмотреть комнату? Каждое решение теперь чего-то стоит. Ты не «проходишь контент», ты расставляешь приоритеты, как настоящий следователь под давлением.
И ещё - таймер создаёт ставки. Убийца может уйти. Шторм приближается, паром вот-вот отчалит. Это не абстрактный счётчик в углу, а тикающая угроза.
Время как валюта.
Главный принцип: каждое действие стоит минут. У меня это работает так:
- Задать вопрос персонажу - 10 минут
- Осмотреть предмет, попытка обыска — 2 минуты
- Переход между локациями - тоже расход
Игрок получает бюджет - 360 минут (6 часов) - и тратит его как хочет. Хочешь опросить Фриду по всем темам? Это десятки минут. А их можно было потратить на дорогу к мысу. Вот и думай, что важнее.
Это заставляет играть иначе. Ты не можешь быть перфекционистом. Приходится оставлять что-то неосмотренным - и жить с этим. Как в жизни.
Как это устроено в коде:
Основа до смешного простая - обычная переменная. В StoryInit задаю стартовый бюджет:
State.variables.remaining_minutes = 360;
Дальше каждое действие просто вычитает из неё. Вот как выглядит вопрос Фриде:
<>
<>
Вычли 10 минут, обновили циферблат.
Циферблат, который не просто число.
Показывать время можно и цифрой, но мне хотелось, чтобы оно давило визуально. Поэтому я сделал круговой циферблат, который заполняется по мере расхода времени - как убывающий диск.
Хитрость тут в CSS-свойстве conic-gradient (конический градиент - заливка по кругу). Функция считает, какой процент времени остался, переводит в градусы и рисует сектор:
window.updateClock = function () { var mins = State.variables.remaining_minutes || 0; var pct = Math.max(0, Math.min(1, mins / 360)); var degrees = Math.round(pct * 360); var gradient = "conic-gradient(#ff9900 0deg, #ff9900 " + degrees + "deg, #2a3828 " + degrees + "deg, #2a3828 360deg)"; $("#clockFace").css("background", gradient); $("#clockMinutes").text(mins); };
По-человечески: беру остаток минут, считаю какую долю от 360 он составляет, умножаю на 360 градусов - и рисую оранжевый сектор на этот угол, остальное заливаю тёмным. Чем меньше времени - тем меньше оранжевого. Игрок видит, как круг «съедается».
Режим тревоги.
Отдельная мелочь, которая хорошо работает на нервы. Когда остаётся час или меньше - циферблат переключается в тревожный режим:
if (mins <= 60) {
$(".clock-container").addClass("warning");
} else {
$(".clock-container").removeClass("warning"); }
Просто добавляю класс warning, а дальше уже CSS делает своё - краснота, может пульсация. Игрок сразу чувствует: время на исходе, пора решаться. Это тот самый момент, когда рука тянется наконец предъявить обвинение.
Чтобы таймер обновлялся сам.
Чтобы не дёргать updateClock() вручную на каждом экране, я повесил его на событие перехода между пассажами:
$(document).on(":passageend", function () {
updateClock();
});
:passageend - это встроенное событие SugarCube, которое срабатывает каждый раз, когда игрок попадает на новую страницу. Теперь циферблат сам перерисовывается при любом переходе. Один раз настроил - забыл.
Про баланс - сколько времени дать.
Это оказалось самым сложным, и это не про код, а про геймдизайн. Сколько минут дать игроку?
- Мало - фрустрация. Не успеваешь ничего, злишься, бросаешь.
- Много - таймер не ощущается. Раз времени вагон, зачем он вообще.
Я целюсь в золотую середину: времени должно хватить, чтобы раскрыть дело, но только если не распыляться. Игрок, который ходит по делу и думает - успевает. Игрок, который тыкается наугад во всё подряд - не успевает. Таймер награждает за собранность, а не наказывает за любопытство. Точные цифры я ещё докручиваю на тестах - это подбирается только вживую.
Честность с игроком.
Важный принцип: таймер не должен быть подлым. Игрок всегда видит, сколько осталось (вот он, циферблат в углу). Каждое действие честно показывает цену. Никаких внезапных «упс, время вышло» из ниоткуда.
Хорошее ограничение времени - это не ловушка, а понятные правила игры. Ты знаешь бюджет, знаешь цены, принимаешь решения с открытыми глазами. Напряжение должно рождаться из твоих выборов, а не из обмана.
Вот так время из простой переменной превращается в главный источник напряжения. Одна цифра remaining_minutes - а держит в тонусе всю игру.
А как ты относишься к таймерам в играх? Заводят и держат в тонусе - или бесят и мешают спокойно вникать? Знаю, что тема спорная, интересно мнение 👍