Вдохнуть и не дышать - пауза во флеш-играх
04.06.2008, автор Stormit, рубрики: ActionScript, АнимацияВо flash-играх часто возникает необходимость сделать паузу. Подразумевается, что действующие лица перестают двигаться и взаимодействовать между собой. В последнее время это актуально и для игровых баннеров. Людей раздражает постоянно мельтешащая анимация и некоторые сайты выдвигают требование ставить баннер на паузу через 15 секунд. Если эта функциональность не закладывалась с самого начала, то включить паузу не всегда просто и сильно зависит от того, как все устроено.
Мне известно 2 подхода к flash-программированию: структурированный и хаотичный. При первом все символы и объекты организуются в строгую иерархию, управление сосредоточено в одном месте, и этот “мозг” каждый кадр перебирает массив подчиненных ему объектов и вызывает для каждого функцию действия. Все строится по принципам ООП. Таким образом работают, например, движки 2D физики и 3D. Хороший способ, уменьшает вероятность ошибки, но требует основательного подхода и много времени.
Есть еще хаотичное или стихийное программирование, когда для каждого клипа (которому это нужно) задается событие onEnterFrame и он запускается в “свободное плавание” (программисты со стажем сейчас меня нещадно осудят). Это настоящее самоуправление, каждый клип живет в пределах своих фигурных скобок. Друг о друге символы знают мало, обычно разбиваются по группам и заносятся в массивы. Метод тоже хороший, можно все сделать быстро, но есть шанс запутаться и поматерить флэш, который “опять глючит”. Этот метод я обычно использую для задач-однодневок, пока все свежо в памяти.
Есть еще третий метод, который мне нравится больше всего - он сочетает в себе и структуру и свободу выбора - ООП основанное на событиях. Но это уже условное отделение - классы как-никак.
Так вот, возвращаясь к вопросу о глобальной паузе: для структурного подхода все просто: заводится логическая переменная (пауза есть/нет), опираясь на которую, главный клип либо вызывает для всех функцию действия, либо нет. Это что касается кода, остановить твиннинг гораздо сложнее. Например, летит муха, у нее дрожит туловище, она машет крылышками и к тому же моргает. Нужно 3 раза вызвать функцию stop(). А если на сцене символов много, и все они разные? Как минимум для каждого объекта нужно описывать функцию его полной остановки (с событиями кстати также - наследование не поможет если символы разные).Для стихийного подхода к программированию это почти расстрел. В обоих случаях нужно писать много строк Actionscripta. Некоторое время я так и мучался, попутно выдумывая, как это можно упростить. Вот то, что есть у меня на сегодня:
Что может приводить объект в движение? Твиннинг или ActionScript (а точнение событие EnterFrame). SetInterval я во внимание не беру.
Значит должна быть функция которая останавливает проигрывание клипа и отключает для него onEnterFrame.
needBePaused = new Array();//тут хранятся все клипы для ПАУЗЫ _global.addToPause = function(obj){ if(!obj._inPause){//2 раза в ПАУЗУ не добавляем needBePaused.push(obj); obj._inPause = true; } } _global.setPause = function(flag) { isPause = flag;//переменная, на всякий случай var i = needBePaused.length; while(i--) { var curObj = needBePaused[i]; if (flag) { curObj.stop(); curObj.oef = curObj.onEnterFrame;//временно сохраняем curObj.onEnterFrame = null; } else { curObj.onEnterFrame = curObj.oef;//восстанавливаем curObj.play(); } } }
Этот код лучше положить в _root, в первый кадр. Для клипа который должен останавливаться нужно вызвать функцию addToPause(this). Лучше всего прописать ее в самом клипе в первом кадре. Даже если есть анимация воспроизводящая головка много раз пройдется по первому кадру, сработает проверка и 2 раза клип в массив не добавится. Как по мне, это удобный способ. Строка addToPause(this) копируется в буффер, а дальше начинается рейд по символам и Ctrl+v.
Теперь пауза включается из любого места вызовом функции setPause(true). Каждый клип останавливается, а его onEnterFrame сохраняется в переменной oef и обнуляется (на конструкцию onClipEvent это не действует, используйте onEnterFrame = function() {…}). При отключении паузы все происходит в обратной последовательности.
Есть конечно и минусы. Если до паузы клип был остановлен в каком-либо кадре, то после - он запустится. Это решается путем добавления к клипу переменной отражающей его состояние проигрывания, но у меня пока в этом не было необходимости.
Интересно на 80%


Очень хитро
Ничего не понимаю во флеше ) Но что, если эту муху останавливать как объект (типа пусть продолжает махать крыльями, трястись и моргать), делать её “принтскрин” и ставить на верхний слой? - Объекты не перемещаются события не случаются, а картинка это всё просто сверху накрывает.
Хорошее решение, но после нужно снять ролик с паузы и начать проигрывать с того же места. За это время в игре можно проиграть, мультфильм может промотать далеко. Да и звуки будут слышны.
А так интересный ход конечно.
эээ…
Опять же, ничего не понимаю во флэше, но как можно проиграть, если объекты не движутся (только дергаются их детали - это чтобы не тормозить всё “дерево” объекта)?
Ролик снимается тоже вроде просто, или я туплю: нажали кнопку паузы - снимается картинка и одновременно запускается игра.
Да и со звуками та же тема - обычно у игр есть типичное отключение звуков. Это как-то хитро делается?
>>если объекты не движутся (только дергаются их детали)
А каким образом все объекты перестали двигаться? - для всех была вызвана функция stop() (или в цикле их перебрали, или они на событие сами среагировали). Вопрос - как сделать этот процесс проще для разработчика.
ну ладно, пускай тогда это прием только для баннеров работает )
Да он везде может работать.
Особенно там, где изначально пауза не планировалась, а в конце работы вдруг понадобилась (заказчик захотел). А объектов много и все на разном уровне вложенности.
Другое дело что это не догмат, а всего лишь альтернативный способ. Для расширения кругозора, если хотите. А кому-то может быть поможет. Мне помогает
хитро однозначно, респект! пока не приходилось сталкиваться с такой задачей, но иногдя для эстетики можно и добавлять в код этот гениальный кусочек:) пасип
Очень хорошая статья, но можно для начинающих описать “new Array”?
Я понимаю что это какой-то массив… Но, возможно напишите такториал по массивам или порекомендуете где можно изучить доходчиво и на русском?
Кстати, как тема для будущих уроков: “Сохранение игры в любом месте”. Возможно даже с выносом сейв-файла во внешний .txt или .xml
Лучше всего почитать хорошую книгу (автор Колин Мук)
Вот нашел в гугле: http://www.flashdocs.net/modules.php?name=News&file=article&sid=23
>>Сохранение игры в любом месте
Это безусловно интересная задача, но не так сложно сохранить результаты, как восстановить потом по ним все объекты.
Огроменное мерси за ссылку!
Всенепременно изучу.
Ну если не в любом месте, то хотя бы в ключевых точках
И конечно особенно интересно как сделать:
a. Чтобы флеш сохранял сам в себя. Например можно создать и удалить записи, скажем 3-х игроков.
б. Чтобы флеш сам на жестком диске создавал файл (в любом формате) и сохранял все туда.
Мне кажется что между классом Array и сохранением игры очень большой диапазон знаний
Сохранять локально данные можно в объекте Shared Object (это что-то вроде Cookies, только родное, флэшовое).
>>Мне кажется что между классом Array и сохранением игры очень большой диапазон знаний…
Это верно
Просто, обладая базовыми навыками, хочется их расширять… вот стараюсь сделать хоть простую (если не сказать примитивную) игрушку, но сам. Соответственно чем больше я в ней проработаю разных комбинаций, тем лучше буду понимать как их применить в сложных проектах.
>>Сохранять локально данные можно в объекте Shared Object
Думаю это будет полезно, раз уж блог о создании игр.
Просим таториал!
Есть вероятность что народ меня в такой просьбе поддержит
Кстати, пользуясь тем что тема про клики и речь зашла про темы статей…
Есть туча способов назначить на одну кнопку несколько действий (например, чтобы после каждого клика она меняла свой текст, цвет и функции). Так вот, неплохо бы услышать ваши хитрые советы, как можно сделать это максимально быстро и легко, к тому же сэкономив на весе ролика и размерах кода.
Не совсем понял в чем задача.
Максимально быстро и легко обычно получается когда переносишь код и символы из предыдущих проектов.
Если я все-таки правильно понял задачу:
Можно сделать символ из N кадров, в каждом из которых, кнопка (символбез текста) в нужном виде и с нужным кодом. Текст в каждом кадре пишется слоем выше. Наверное это самый быстрый и простой способ для аниматора.
>>Можно сделать символ из N кадров, в каждом из которых,
). Ну а если текст в кнопке динамический? Например есть две версии сайта русский и английский. Название кнопки в каждом имеет денамический текст. Более того, как русская так и английская кнопка имеют два текста и две функции. Например по умолчанию: Текст - “нажать”, функция - пока нету. Нажимаем. Тогда текст: - “нажата”, функция - “играет музыка”. Нажимаем снова и переходим на фазу по умолчанию. Пример взят из головы. Можно усложнить задачу, чтобы бало 3 таких кнопки и при нажатии на одну из них, другие переходили в неактивную или нужную по логике фазу.
>>кнопка (символбез текста) в нужном виде и с нужным кодом.
>>Текст в каждом кадре пишется слоем выше.
Можно и так (по крайней мере я так делаю
Это не универсальная задача, ее можно усложнять и изменять вечно. Я не могу все время давать ответ. Тем более что к флэш-играм это не имеет никакого отношения, а ответы на многие вещи можно найти нажав F1.
Все можно сделать как анимацией, так и программно. Каждый по своему опыту выбирает что лучше, в любом случае решений всегда несколько.
Если у тебя изменяется текст, функции и вид кнопки, логично что нужно как-то описать сначала все состояния (или нарисовать каждое в отдельном кадре) и затем переключать их (изменять текст, цветовые трансформации) и выполнять нужный код по ситуации. При переключении свойству onRelease присваивается другая функция.
Если задействованы 3 кнопки, то логичней центр управления вынести над ними описав некий виртуальный объект “Набор кнопок” (переменные и функции) и обрабатывать в нем нажатие на кнопки. Причем кнопка может при нажатии сама изменить себя, а затем вызвать функцию “набора” чтобы он деактивировал остальные (и запомнил какая нажата, а какие нет). А можно на классах сделать (один для кнопки и один для “набора кнопок”).
Это все не сложно объяснять, но это не по теме блога, это общие знания о флэш-программировании.
Спасибо за развернутый ответ — обязательно воспользуюсь
А про неприминимость к играм вы не правы. Как раз именно в играх много раз вижу, что такие функции у авторов косячат. Особенно часто это бывает когда по-баловству жму многофункциональную кнопку быстро и много раз подряд. Мувики не разбирал — не знаю с чем это связано, но доставляет массу хлопот.