Просмотр полной версии : событие соврачивания/закрытия страницы
Есть игра. В процессе игры, при нажатии на Esc выскакивает окошко "Точно выйти?" с кнопками "да/нет". Хотелось бы заставить это же окошко появляться, когда пользователь переходит на другую вкладку в браузере, или сворачивает окно, короче, когда ролик на странице теряет фокус. Это вообще возможно реализовать средствами AS 2.0? Игра заточена под Flash Player 8.
а окошко - javascript?
окошко "Точно выйти"? Нет, окошко - часть игры.
gloomyBrain
17.11.2009, 00:34
Если пользователь переходит на другую вкладку - как он увидит выскочившее окошко? =)
Если даже (в чем я сильно сомневаюсь) это было бы и возможно, я бы немедленно ушел с такой страницы и никогда на нее не возвращался. Браузер есть браузер, а контент, который он отображает - это некая "песочница" - нечто, по определению не должное иметь возможности препятствовать навигации самой программы. Adobe имел бы большие проблемы, если бы допустил такую возможность.
Если пользователь переходит на другую вкладку - как он увидит выскочившее окошко? =) Да по-барабану увидит он его или нет, главное, что игра на паузу встанет. А когда он на вкладку вернется - тогда и увидит, и примет решение - играть дальше или выходить.
не должное иметь возможности препятствовать навигации самой программыЭто где же паузы флеш-ролика препятствует навигации в браузере?
Хотелось бы конструктивных советов, а не обсуждения нужности и важности фичи. Мне это тоже пофигу, но заказчик требует сделать так, или доказать, что это невозможно.
Итак, повторяю вопрос: как отловить событие потери флэш-роликом фокуса (свернули браузер, сменили вкладку, ткнули мышью на странице где-нибудь вне ролика) средствами исключительно AS 2.0 ?
Задавайте вопросы корректно. Как это по-барабану, увидит или нет. Перечитайте свой первый пост. Там ни слова про паузу, а только про показ меню "Точно выйти?".
В первом посте вопрос заключается в возможности отлова внутри ролика события потери роликом фокуса. Пауза и менюшка - это ненужные детали.
Для AS2 нормального решения нет. В AS3 появилось соответствующее событие.
В первом посте вопрос заключается в возможности отлова внутри ролика события потери роликом фокуса. Пауза и менюшка - это ненужные детали.
Тру.
Для AS2 нормального решения нет.Я думаю, мне и ненормальное подойдет, если оно есть конечно. Не подскажете?
Сам решением этого вопроса не занимался, просто видел обсуждения. Люди частично решали проблему использованием JS (не работает во всех браузерах) и проверкой координат мыши (не работает при резком движении).
Координаты мыши в принципе не вариант. Управление в игре клавиатурное, так что мышь вполне могут и убрать из окна, чтобы не мешалась.
С JS я малознаком, поэтому обсуждения мне только общее представление дали. Насколько я понял надо ловить событие OnBlur, но как передавать инфу об улове мувику я так и не понял.
Есть одно решение, несколько громоздкое.
У вас фокус внутри флешки игре как-то задействуется (устанавливается-проверяется) или нет?
Вот сделал работающий пример по вашему вопросу, реализовано все чисто во флеше.
Запустите HTML-ку и посмотрите на поведение игры при сворачивании браузера, переходе на другую вкладку, на другое приложение, да просто клике на той же странице вне области флешки.
Думаю, что принцип понятен, конечно, это грубое решение, к тому же все ваши обстоятельства были неизвестны. При некоторых достаточно серьезных оговорках можно попробовать использовать.
PS. Если у вас какие-то объекты по сценарию также могут приобретать фокус, то на их onKillFocus нужно также прописать функцию, которая используется в примере и учитывать этот факт в самой функции, чтобы не было ложных срабатываний.
Спасибо большое, но мне, похоже требуется небольшое кормление с ложечки, опыта маловато.
1. Что это за загадочный _level0 ?
2. Не совсем понял, к чему вот это ////// БЛОКИРУЮЩЕЕ МЕНЮ ///////////////////////////////////////////
menu_mc.bg.onPress = function () {
//пустой обработчик. По идее, нужно еще отключать функции игры
}
3. Можно ли без потерь этот код повесить не на кадр, а на мувик, отвечающий за логику?
4. При прохождении уровня, игра переходит на кадр выхода из уровня, потом на кадр входа, потом снова на кадр с собственно игрой. Все в пределах одной сцены. Не помешает ли подобное адекватно работать вашему коду? (обработка потери фокуса нужна только во время игры, в остальные моменты - не важно, есть она или нету)
1. _level0 - это сама сцена. В принципе, можно события onEnterFrame вешать на любой мувик.
2. Это к делу не относится - сделано для блокировки активных элементов игры, которые могут находится под блокирующим меню, чтобы пользователь, когда игра на паузе, не нажал чего-нибудь. Ну и слушание клавиатуры надо удалять-ставить (removeListener - addListener).
3. Нет, нельзя, пишите в кадре. Вообще никогда не пишите код на мувиках.
4. Нормально код, без допила, будет работать только в примере, аналогичном моему - два кадра (начало и сама игра) - там же прописан, например, номер кадра (1) и функции стартуют именно в кадре 2.
Идея состоит в том что отслушать потерю фокуса средствами флешки мы можем не всегда - только когда фокус установлен на каком-то объекте (используя onKillFocus).
Когда фокус установлен на null, отследить в AS2 событие потери фокуса никак (по крайней мере мне это неизвестно). Поэтому я сделал перевод фокуса на специальный объект при попадании фокуса на null :
function setFocusOnNullObject () { //принудительная установка фокуса на специальный объект вместо null
if (!focusOnNullSet && Selection.getFocus() == null) {//если фокус переходит на null, переводим его один раз на специальный объект
Selection.setFocus(null_mc);
focusOnNullSet = true ;
}
}
Эта функция вызывается постоянно, когда игра работает (т.е. не поставлена на паузу). Как только игра ставится на паузу, функция onEnterFrame удаляется.
И когда этот объект теряет фокус - в примере считается , что пользователь свернул страницу, ушел на другое приложение и т.д.
Добавлено через 12 минут
Если выкинуть все лишнее (оставив блокирующее меню), все сводится к этому:
function pauseFunc () {
delete _level0.onEnterFrame ;
manageMenu ('on');
}
function startShowCount () {
_level0.onEnterFrame = setFocusOnNullObject;
}
function setFocusOnNullObject () { //принудительная установка фокуса на специальный объект вместо null
if (!focusOnNullSet && Selection.getFocus() == null) {//если фокус переходит на null, переводим его один раз на специальный объект
Selection.setFocus(null_mc);
focusOnNullSet = true ;
}
}
null_mc.onKillFocus = pauseFunc; // при потере фокуса приостанавливают игру
startShowCount(); //установка функции EnterFrame для _level0
////// БЛОКИРУЮЩЕЕ МЕНЮ ///////////////////////////////////////////
menu_mc.bg.onPress = function () {
//пустой обработчик. По идее, нужно еще отключать функции игры
}
menu_mc.bg.useHandCursor = false ;
menu_mc.contin_mc.onRelease = function () {
manageMenu ('off');
startShowCount ();
focusOnNullSet = false ;
}
menu_mc.exit_mc.onRelease = function () {
gotoAndStop(1);
focusOnNullSet = false ;
}
function manageMenu (dir:String) {
switch (dir) {
case 'on':
menu_mc._alpha = 100;
menu_mc._visible = true ;
break;
case 'off':
menu_mc._alpha = 0;
menu_mc._visible = false ;
break;
}
}
manageMenu ('off');
Смысл примера - показать идею. Доработать код под ваш случай в принципе можно, но вы должны сделать это сами, разобравшись в алгоритме.. ну либо выложите исходник, я посмотрю.
Добавлено через 42 минуты
Попробуйте допилить. Запишите все функции в первом кадре, а действия
null_mc.onKillFocus = pauseFunc; // при потере фокуса приостанавливают игру
startShowCount(); //установка функции EnterFrame для _level0
- в кадре текущего уровня.
Мувик null_mc должен находится во всех кадрах уровней (уберите его за границы сцены).
Mooncar, огромное спасибо за возню со мной. Просить сделать все за меня не собираюсь, потому как это ущербная практика и я сам в таком случае так ничему и не научусь. Смотреть на мои исходники вам вряд-ли захочется, потому что на сегодняшний день fla-файл весит 38 метров (подлинкованные музыка/звуки/графика/партиклы и все такое) и состоит из сотен страниц кода, в котором разбираться - врагу не пожелаешь.
Managemenu есть свой (что вполне очевидно, пауза-то реализована давно), а само состояние паузы представлено единственной глобально переменной isPaused : Boolean;
Все слушатели мыши/клавиатуры, все обсчеты движения/столкновений/таймеров/счетчиков и вообще всего, чего только можно зависят от значения этой переменной. То есть, когда я в процессе игры тыкаю на ESC, isPaused принимает значение true и все останавливается, а меню "Выйти? ДА/НЕТ" становится видимым и активным (оно все это время лежало прямо посреди игрового экрана, но пока isPaused == false оно прозрачно, а кнопки !visible и !enabled)
Вообще никогда не пишите код на мувиках.
Хм. Учился работать с AS по учебникам типа "Macromedia Flash MX. Создание игр с помощью ActionScript". Оттуда собственно и идея создавать за пределами сцены мувиклип с логикой.
Мувик null_mc должен находится во всех кадрах уровней
Уровней много, а кадр - один. Генерация/уничтожение объектов окружения/врагов/фона/бонусов и всего такого идет динамически, основываясь на индексе текущего уровня
Попробуйте допилить. Запишите все функции в первом кадре, а действия в кадре текущего уровня.Дело в том, что в кадре текущего уровня есть такая штука как stop(), ибо после него есть еще несколько вспомогательных кадров (анимация завершения уровня, анимация начала уровня, анимация смены левелпака, анимация геймовера). Выходит (если я все правильно понимаю), эти самые действия null_mc.onKillFocus = pauseFunc; // при потере фокуса приостанавливают игру
startShowCount(); //установка функции EnterFrame для _level0не станут выполняться постоянно, а отработают только один раз, пока головка не наткнется на stop(). Значит надо их сунуть в какой-то onEnterFrame видимо, только в какой...
P.S.: Игра уже на 100% готова (за исключением обсуждаемой фичи), поэтому любые изменения структуры кода отметаются сразу, ибо нету времени потом все эти изменения тестировать на предмет каких-нибудь случайных косяков (не говоря уже о том, что возможно придется половину игры переписать, только для того, чтобы в этом злополучном кадре stop() не стоял)
Ваша ситуация понятна...
Я еще упростил код, убрал onEnterFrame и ввел ваш триггер:
function pauseFunc () { //функция паузы
clearInterval (CHK);
isPaused = true ; //тут ваш триггер устанавливается в true
}
function checkFocus () { //функция установки проверки
isPaused = false ;
CHK = setInterval(setFocusOnNullObject, 10);
}
function setFocusOnNullObject () { //принудительная установка фокуса на специальный объект вместо null
if (!isPaused && Selection.getFocus() == null) {//если фокус переходит на null, переводим его один раз на специальный объект
Selection.setFocus(null_mc);
}
}
null_mc.onKillFocus = pauseFunc; // при потере фокуса приостанавливают игру, достаточно объявить ОДИН раз
checkFocus (); //первоначальная установка проверки
Вам нужно записать этот код в первом кадре основного таймлайна.
А вот этот вызов
checkFocus ();
дописать еще там, где у вас идет снятие с паузы для того, чтобы снова активировать перевод фокуса с null на объект null_mc и отслеживание потери фокуса.
И не забудьте про мувик null_mc, я забыл сказать, он должен на сцене быть как Button (как у меня в примере, можете прямо его скопировать).
Для начала хотя бы добейтесь постановки на паузу, снятие во вторую очередь.
Спасибо огромное, все работает. Правда пришлось чуток поработать напильником, чтобы на переходах не выскакивало и в MainMenu у кнопок фокус не отбирало, но теперь все ништяк. Проблема решена.
Есть в этом форуме репа или типа того? Хочу хоть так отблагодарить :)
Правда пришлось чуток поработать напильником, чтобы на переходах не выскакивало и в MainMenu у кнопок фокус не отбирало, но теперь все ништяк.
Именно об этом я и говорил:
Если у вас какие-то объекты по сценарию также могут приобретать фокус, то на их onKillFocus нужно также прописать функцию, которая используется в примере и учитывать этот факт в самой функции, чтобы не было ложных срабатываний.
Хорошо, что разобрались, как это сделать. Может, конечно еще что-то вылезти, это ведь не очень корректное решение.
Репа-не репа, но интересная задачка была, я сперва вообще создавал массив всех объектов, получающих фокус создавал в автоматическом режиме, но только потому что не знал деталей. Всегда лучше всего максимально полно описывать, тогда и вероятность, что помогут, выше. :)
Пора на AS3 переходить, ох пора.
то на их onKillFocus нужно также прописать функцию, которая используется в примере и учитывать этот факт в самой функции, чтобы не было ложных срабатываний.
Я не так далал. Я делал GameState-ы (в игре, в меню, в переходах и т.д.) и в setFocusOnNullObject() добавлял проверку состояния.
Всегда лучше всего максимально полно описывать, тогда и вероятность, что помогут, выше.Ну, это же не хелловорлдная задача, тут здоровенный проект - полноценная космическая казуальная стрелялка, всех нюансов никак не опишешь.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.