Часть 3. Оживляем карту.
Разумеется, на обычной водной глади смена дня и ночи выглядит не особо интересно. В принципе, я могу бы сейчас начать реализовывать целое микропоселение, каждый житель которого имеет свой распорядок дня, однако это уже достаточно хорошо сделала AnnTenna. Я же заострю внимание на нескольких фичах, которые относительно легко реализуются в данной механике.
Для начала, впрочем, есть смысл всё-таки сделать небольшой населённый пункт, в котором будут реализованы все эти возможности. Маппер из меня не ахти, так что в итоге получилось вот что.
Как видите, здесь имеются три НПЦ, каждый из которых реализует определённую возможность.
Самое простое – это девушка возле дома. Пообщавшись с ней, герой удалится вместе с ней в дом, после чего время пойдёт гораздо быстрее.
Что происходит в этом ивенте? Первая его страница активируется, когда герой подходит к девушке и заговаривает с ней (клавишей выбора), при этом активируется свитч №1, и вместе с ним запускается основная, вторая, страница.
На второй странице графика девушки и героя заменяется на прозрачную («ушли в дом»), после чего параметр «скорость» становится равным 5 и остаётся таковым до нажатия произвольной клавиши (Wait: ForKeyPress), после чего всё возвращается, как было изначально. Аналогичным образом можно реализовать и замедление времени – только тогда придётся изначально скорость ставить больше единицы, т.к. дробных значений в RM2k3 не предусмотрено.
Для реализации двух других особенностей потребуется немного подправить параллельный ивент. Рассмотрим сначала волшебницу в правом нижнем углу.
При разговоре с ней можно остановить или снова запустить время, а также сделать время суток таким, как тебе хочется. Заметьте, что время суток ставится не напрямую, а косвенно – через установку предыдущего времени суток и нулевого оставшегося времени. Если просто установить значение переменной «время суток» на нужное вам, то получится, что до конца нового, только что установленного времени суток останется столько же шагов параллельного эвента, сколько оставалось бы до конца имевшегося, что не всегда желательно (хотя, если с таким побочным эффектом можно смириться - может быть смысл делать "в лоб").
Для остановки, в свою очередь, требуется скорректировать параллельный эвент. Вся конструкция параллельного эвента теперь помещена под одно условие: если время не остановлено, т.е. если сброшен свитч номер 3, устанавливаемый в диалоге с волшебницей. Если же оно остановлено (свитч поставлен), то параллельный ивент исполняться не будет.
Внимательные читатели могут меня сейчас поправить – получается, что при остановленном времени предыдущий эвент с той же самой волшебницей, устанавливающий время суток, не будет работать корректно! Да, это действительно так, и я могу предложить два варианта решения. Первый – указанный выше – напрямую установить время суток при обращении к волшебнице, без работы с таймером. Второй, возможно, более изящный: поместить под условие «Время не остановлено» только сам таймер:
Если сделать таким образом, то времена суток будут меняться параллельным ивентом в любом случае при обнулении таймера, но, если стоит свитч «время остановлено», таймер не будет уменьшаться «своим ходом». В некоторых случаях есть смысл поступить наоборот: поместить под условие только действия при обнулении таймера. Тогда при снятии блокировки необходимое действие может произойти моментально.
Ещё один, возможно, даже более простой вариант остановки времени – банальная установка скорости на 0. В этом случае не потребуется никакой правки параллельного процесса, зато понадобится делать более разветвлённую конструкцию диалога с волшебницей, а именно, делить ветку «Остановить/запустить время» на две в зависимости от того, нулевой или ненулевой является скорость. Однако я предпочитаю такой вариант, какой указан здесь; почему – скажу чуть позже.
И третий ивент – с мужчиной у гексаграммы.
У самого мужчины я никаких действий не ставил – только вывод сообщения. Действие (причём совершенно элементарное) помещено непосредственно на гексаграмму:
а на клетки вокруг неё помещены ивенты, сбрасывающие этот свитч.
Теперь добавляем нехитрую конструкцию всё в тот же параллельный ивент:
Теперь, наступив на гексаграмму, мы услышим частые щелчки – если быть точным, десять раз в секунду, как и изменение таймера. Заметьте, что при остановленном времени, т.е. тогда, когда не работает таймер, нет и звукового эффекта – что вполне согласуется со словами мужчины о «звуке Небесных Часов», слышном с этого места. Сойдя же с гексаграммы, мы слышать эти щелчки перестанем, поскольку свитч будет сброшен. Таким же образом можно реализовать любые периодические события, привязанные к этому же таймеру – разумеется, с частотой не менее одной десятой секунды, поскольку меньше RM2k3 просто не поддерживает.
Но, допустим, нам нужно, чтобы что-то происходило не каждую десятую долю секунды, а реже. Оказывается, есть способ сделать событие, происходящее через любой интервал, на том же самом таймере. Для примера давайте сделаем Небесные часы посекундными.
Исправления потребует только параллельный процесс – правда, универсальное решение довольно-таки нетривиально.
Действует эта конструкция следующим образом. Переменная «кратность скорости» - это период между двумя событиями в десятых долях секунды при скорости 1, делённый на скорость. Именно здесь и может ждать очевидный подвох при остановке времени методом обнуления скорости. Далее текущее значение таймера (скопированное в переменную «доли секунды») делится с остатком на «кратность скорости» и берётся остаток (операция Mod), и этот остаток, в свою очередь, сверяется с нулём. Совпадение и означает требуемый шаг. В данном случае, правда, надо быть осторожным: если период события может не делиться на скорость (к примеру, если бы в доме время ускорялось не в 5, а в 3 раза), то большая часть периодических событий не сработает; и если период сброса счётчика (в данном случае – смены времени суток) не делится на частоту события, то при сбросе период между событиями будет меньше.
Если частота события не должна зависеть от скорости игрового времени, то изменение ещё больше упрощается: убирается переменная «кратность скорости», вместо неё в выражение с Mod подставляется необходимая константа.
Какие ещё возможны варианты? Например, если есть желание облегчить параллельный эвент, мало теряя в гибкости конструкции, можно сделать счётчик не по десятым долям секунды, а по секундам: для этого просто надо заменить Wait:0.1 sec на Wait:1.0 sec и соответствующим образом установить счётчики. Кроме того, аналогичную систему можно использовать для обратного отсчёта времени перед некоторым событием – для этого потребуется один эвент, построенный по рассмотренной можели, один свитч, запускающий этот эвент и вместе с ним обратный отсчёт, и счётчик, который перед запуском эвента можно инициализировать любым значением. После этого получившуюся конструкцию можно использовать в очень широком интервале возможных значений без каких-либо изменений; фактически, имеется эвентовая реализация таймера.
И ещё много-много случаев, когда нам могут не помешать собственноручно сконструированные часы
Ну и, наконец, обещанная демка.
narod.ru/disk/56032921001.8dcfbcc823b2ba...acca2/Clock.zip.html
Готов выслушать, где я был неправ