В этом уроке я хочу рассказать о действии Wait. Урок ориентирован на разных пользователей Construct 2: новички смогут понять базовые моменты работы с этим действием, пользователи среднего уровня смогут узнать особенности работы с ним, а профессионалам появиться новая "пища" для мозга, в качестве размышления, как же работает Wait.
Wait
— это системное действие в котором задается определенное значение (промежуток времени), это действие как бы делает "паузу" между действиями. По истечении этого промежутка времени, продолжается выполнение следующих (нижестоящих) событий.
Wait: основы
Я уже немного подготовился к уроку и создал небольшой проект:
Как можно увидеть, в нем есть три объекта: bee (пчела, Sprite), bat (летучая мышь, Sprite) и function (объект функций).
Приступим к изучению основ. Сделаем вот что: при запуске игры (On start of layout) ждем 1 секунду и уничтожаем всех пчел. Это выглядит следующим образом:

Кроме единоразового использования Wait, его можно использовать два и более раз. Например, вот так:

В этом случае выполнится следующее:
- При старте игры, ждем 1 секунду
- Как только проходит 1 секунда, уничтожаем пчел (т.к. у нас здесь не сделана выборка пчел, поэтому уничтожаем всех пчел)
- Затем ждем еще 2 секунды
- После истечения этих 2-х секунд, уничтожаем летучих мышей.
Напомню, что действия выполняются сверху-вниз, т.е. порядок событий имеет значение. Думаю, будет понятным то, что летучие мыши будут уничтожены через 3-и секунды после запуска игры.
Wait: трюки и тонкости
Wait – принимаемые значения
Действие Wait принимает только положительные числа, включая нуль. При этом числа могут быть как целыми, так и дробными (например, не будет разницы между числом 1.0 и 1). Примеры:
20.0 —> Ок, положительное число
5 —> Ок, положительное число
0 —> Ок, нуль не имеет знака
-4 —> Не корректно, отрицательное число
"8" —> Не корректно, строка
Wait – обман с помощью переменной
Если попробовать "обмануть" Wait, введя в него строку/отрицательное число, то Construct 2 сразу нам выдаст ошибку (предупреждение). Но есть и другой способ "обмана" Wait — через стороннюю переменную. Добавим в проект глобальную переменную I (i, числовая переменная, можно задать константой). Для начала зададим переменной значение числа 2. Получиться вот так:
Если проверим — то все будет нормально, пчелы уничтожаться через 2 секунды. Давайте начнем сам "обман".
I = 5 —> Корректно, ждем 5 секунд
I = 2.5 —> Корректно, ждем 2.5 секунды
I = 0 —> Корректно, ждем 0 секунд
I = -5 —> Construct 2 не выдаст тут никакой ошибки, однако, Wait принимает только положительные числа. Construct 2 если встречается с отрицательным числом, то это число заменяется на 0 (нуль)
I = -10.0 —> Тоже самое, что и выше
Далее, давайте попробуем изменить значение I, в то время, когда Wait уже начал выполняться (I не должно быть в этом случае константой), вот так:
Что происходит:
- Старт игры, ждем I секунд (на данный момент I = 2)
- Задаем I = 10
Результат: Wait будет ждать 2 секунды. Почему? Wait просто-напросто не поддерживает динамическое значение переменной и запоминает свое значение только в момент выполнения.
Wait и циклы
Сразу скажу, что если использовать Wait в циклах, то это приводит к странным и непонятным результатом. Пример:

Эти события сделают следующее:
- Начинаем цикл, в каждой итерации (итерация — каждое повторение цикла) подбираем одну копию пчелы (некая вольная имитация цикла For each)
- Каждая итерация: ждем секунду, затем уничтожаем пчелу.
А теперь посмотрим, как эту ситуацию видит человек и как это происходит на самом деле в Construct 2.
Человек:
- Во время каждой итерации, сначала ждем секунду, затем уничтожаем пчелу, затем переходим к следующей итерации
Construct 2:
- Начинаем первую итерацию, натыкаемся на Wait, кладем текущие данные (выборку, время ожидания в Wait, индекс цикла и пр.) в память, для того, чтобы позже сравнивать прошло время в Wait или нет. Как только Construct 2 наткнулся на Wait и положил его в память, то он сразу же приступает к следующей итерации. Фактически, он выполняет все итерации разом, а затем через 1 секунду уничтожаются все пчелы. Иными словами, Construct 2 не прерывает (не приостанавливает) циклы действием Wait.
Wait 0 – бессмыслица со смыслом
Весьма интересным эффектом обладает действие Wait с параметром 0. С первого взгляда может показаться, что это сплошная бессмыслица — зачем ждать ничего? В чем-то тут будет истина, например вот тут:

Проходит 0 секунд и все пчелы уничтожаются. Давайте пока что уберем Wait, добавим в проект объект Browser (браузер) для наглядности и сделаем событие вот таким образом:

Как ни странно, но в окне-сообщении (alert) будет выдано число 3, хотя предыдущим действием мы уничтожили всех пчел. Можно попробовать вынести Browser -> Alert в под-событие или в событие ниже, но результат будет тем же самым. Тут на помощь и приходит Wait 0.

На здравомыслящий взгляд — ничего не поменялось. Но на самом деле, поменялось многое (можете даже проверит). Опять же, хочу показать то, как эту ситуацию видит и должен понимать человек и как это делает Construct 2.
Человек:
- Wait 0 Означает, что все нижестоящие действия должны быть выполнены только тогда, когда выполнены все вышестоящие действия. Очень грубо говоря, Wait 0 в данном случае является неким условным оператором.
- Wait 0 остается таким же Wait, логика этого события не меняется - "Подожди определенный промежуток времени и продолжай выполнять события". Тут я хотел бы остановиться и рассказать о моем предположении работы Wait:
- Как только Construct 2 доходит до Wait, он кладет всю необходимую информацию на данный момент в память (она довольно невелика, поэтому занимает немного объема памяти). Затем Construct 2, в любом случае, прерывает выполнение текущего действия и переходит к выполнению под-событий и событий.
- Как только Construct 2 выполнит все события, т.е. дойдет до последнего события внизу игру, то начнется новый тик игры.
- На новом тике, Construct 2 "вспоминает" про Wait и проверяет его: Construct 2 смотрит, "Ага, Wait 0, у него параметр = 0, а уже прошел тик игры (примечание, 1 тик игры равен системному выражению dt, который приблизительно равен 0.017, в зависимости от устройства и его производительности), сравниваю 0 и dt, значит 0 < dt (0 меньше чем 0.017)". Construct 2 понимает, что нужно "до-выполнить" то событие и возвращается к нему.
- Все вышенаписанное можно представить как вот эту картинку:
Wait и функции
(Для более продвинутых пользователей)
Давайте рассмотрим пример с функцией. Создадим вот такую простую функцию:

Простыми словами, она задает всем пчелам прозрачность, указанную в ее первом параметре. Проверим — работает.

Немного изменим функцию, добавив в нее перед действием задания прозрачности Wait 1.

Проверяем — странно, все пчелы исчезли. Смотрим через отладчик: оказывается, пчелам задалась 0 (нулевая) прозрачность.

Дело вот в чем: по какой-то неизвестной причине, Wait в некоторых случаях (в функциях) просто не запоминает исходные данные, поэтому выражение int(function.Param(0)) возвращает нам нуль. Это не баг, это просто особенность которую стоит учитывать, если используете Wait в функциях.
Как решение этой проблемы на оф. форуме было выдвинуто следующее: создать статичную локальную переменную в функции, загрузить в нее значение параметра/параметров и уже с ней проводить необходимые манипуляции. Например, в данном случае это будет выглядеть вот так:
На этом у меня все, все что знал о Wait я рассказал. Кстати, повторюсь, что теория работы Wait — моя собственная, поэтому ее всю беру на себя (поэтому могут быть недочеты, промахи и не корректности), но в общем, как я думаю, суть я изложил. Точно знает как работает Wait в C2 только Эшли.