Казахстан, Алматы, Гимназия им. Ахмета Байтурсынова №139, 2008 |
Клипы и ролики. Специальные возможности языка
Детальный разбор алгоритма переключения кадров
Теперь давайте рассмотрим алгоритм переключения кадров более подробно. Сначала поясним общий принцип. При выполнении кода, содержащего команды управления порядком кадров, эти команды не инициируют мгновенного перехода на соответствующий кадр, но все "заказанные" переходы (и соответствующие им переключения режимов проигрывания / остановки) помещаются в очередь. Когда код в данном кадре выполнен до конца, выполняется каждый из переходов, помещенных в очередь. При этом выполняется и код в каждом из кадров, на который мы попадаем (а "заказы на переходы" из этого кадра кладутся в конец очереди).
А теперь на примере работы со сценами закрепим наши знания по механизму переключения кадров. Предположим, в одном и том же кадре вы написали подряд play и stop - кажется, что флэш-плееру даны две взаимоисключающие инструкции. Что произойдет? Нам нужно вспомнить, что все запланированные переходы совершаются в порядке очереди (но после того, как будут выполнены все остальные команды). Кроме того, хотя команды, изменяющие состояние клипа на "остановлен" или "проигрывается", и влияют на это состояние немедленно в момент своего выполнения (или в момент совершения соответствующего им перехода, если это gotoAndPlay или gotoAndStop ), но само состояние будет востребовано лишь к следующему плановому переключению кадров. А к этому времени оно может быть изменено другой командой. Так что все вышеупомянутые инструкции лишь устанавливают текущий кадр (и состояние играть / остановиться), переключение на который произойдет только когда придет время. А это значит, что из нескольких последовательных инструкций, "противоречащих" друг другу, лишь выполненная последней установит реальное состояние, в которое будет переключен клип (или весь ролик ). Однако, в последней фразе важна оговорка "противоречащих друг другу". Скажем, nextScene и stop друг другу, как выясняется, не противоречат. Если вы действительно выполните nextScene, а потом stop, то ролику в качестве следующего кадра будет указан первый кадр следующей сцены, а в качестве следующего состояния - остановленное. То же самое делает, кстати, и nextScene сама по себе. А если вы напишете nextScene, а потом play (в том же кадре ), вы увидите, что команда play перезаписала следующее состояние, но не следующий кадр. То есть в следующем кадре ролик перейдет на новую сцену, но не остановится, а начнет играть дальше. (Если бы play стояло до nextScene, то такого эффекта не было бы - nextScene установило бы будущее состояние как "остановленное", заменив то, которое было установлено командой play ). Наконец, отметим, что вызов метода gotoAndPlay клипа _root после команды nextScene отменяет ее действие. Дело в том, что этот метод, хотя ему, в отличие от одноименного Action, не передается идентификатор сцены, все же устанавливает текущий кадр. И выбирает этот кадр (в соответствии с номером или меткой) в текущей сцене. Тот же эффект будет достигнут, если после nextScene вызывать _root.gotoAndStop.
А теперь рассмотрим более сложный пример, который зато проявляет свойства алгоритма переключения кадров достаточно полно. Давайте сделаем новый флэш-ролик с тремя ключевыми кадрами. В первый из кадров поместим следующий код:
trace(1);
во второй:
trace(2); if (i++ < 5){ gotoAndPlay(3); gotoAndPlay(2); stop(); // Эта команда здесь бесполезна trace("-------") } if (i > 7) stop();
наконец, в третий
trace(3); gotoAndPlay(1);
Запускаем и получаем в консоли такую последовательность:
1 2 ------- 3 2 ------- 1 3 2 ------- 1 3 2 ------- 1 3 2 ------- 1 3 2 1 2 3 1 2
Можем ли мы ее объяснить, исходя из наших представлений об алгоритме переключения кадров? Оказывается, да. В самом деле, мы начинаем с первого кадра (печатается 1), доходим до второго обычным образом (печатается 2), после чего запоминаем, что нам надо будет перейти на кадры 3 и 2. Но это мы пока только запоминаем, а тем временем выводим длинную горизонтальную черту. Затем следует проверка, в которую мы не попадаем, и код в кадре 2 кончается. Поэтому мы начинаем выполнять переходы, которые ждут у нас в очереди. Переходим на кадр 3 и выполняем код, который находится там (выводится число 3, в очередь ставится переход на кадр 1). Затем переходим на кадр 2 (этот переход только что был первым на очереди), в результате печатается двойка, а в очередь попадают переходы на кадры 3 и 2. Затем печатается горизонтальная черта. Код во втором кадре закончился, на очереди у нас переход в кадр 1 (вся очередь выглядит так: 1 - 3 - 2). Переходим (печатается 1), далее на очереди переход в 3 (переходим, печатается 3, в очередь попадает переход в 1), следующий на очереди - переход в 2. После выполнения кадра 2 распечатаются двойка, горизонтальная черта, в очередь добавятся переходы в 3 и 2. Очередь снова приняла вид 1 - 3 - 2, так что дальше все будет происходить циклически до тех пор, пока i не станет больше пяти. Затем кадры начнут идти по порядку, а потом (когда i станет больше 7), все остановится. Мы видим, что именно так все и произошло.
Обратим еще внимание на тот интересный факт, что функция stop(), расположенная во втором кадре после команд переходов, у нас не сработала. Точнее, она срабатывала и даже не один раз. (Мы, кстати, не писали о том, что эта команда тоже попадала в очередь переходов и изменений состояния, но это было именно так.) Но каждый раз после этой команды в очередь попадала команда gotoAndPlay(1) перехода на первый кадр, которая меняла текущий режим проигрывания на "проигрывается". Как проверить, что команда stop() попадает в очередь? Поставить stop() в конце третьего кадра. Переходы из очереди выполняются, когда весь код из кадра уже выполнен. Поэтому, если бы stop() в очередь не попадал, ситуация осталась бы прежней. Однако в этом случае мы увидим, что двух циклов со стандартным порядком кадров (1 - 2 - 3 - 1 - 2 - 3) мы уже не видим. Итак, stop() тоже помещается в очередь. Еще интересно следующее: gotoAndPlay поменяет состояние клипа с "остановлен" на "проигрывается", если указать переход на несуществующий кадр? Теперь закомментируем stop() в третьем кадре и направим gotoAndPlay из этого же кадра на несуществующий кадр (скажем, 111). Переходы на кадр 1 из лога, разумеется, пропадают. Однако циклы со стандартным порядком кадров (1 - 2 - 3 - 1 - 2 - 3) в конце имеются, а это значит, что действие команды stop() отменено переходом gotoAndPlay(111) (и именно им - если сомневаетесь, закомментируйте этот переход и увидите, что циклы со стандартным порядком кадров опять пропали).
Кстати, а что произойдет, если мы попытаемся перейти на тот кадр, на котором уже находимся? Оказывается, не произойдет совершенно ничего (в противном случае это приводило бы к зацикливанию).