Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   событие соврачивания/закрытия страницы (http://www.flasher.ru/forum/showthread.php?t=132567)

azazul 17.11.2009 04:23

Координаты мыши в принципе не вариант. Управление в игре клавиатурное, так что мышь вполне могут и убрать из окна, чтобы не мешалась.

С JS я малознаком, поэтому обсуждения мне только общее представление дали. Насколько я понял надо ловить событие OnBlur, но как передавать инфу об улове мувику я так и не понял.

mooncar 17.11.2009 11:25

Есть одно решение, несколько громоздкое.
У вас фокус внутри флешки игре как-то задействуется (устанавливается-проверяется) или нет?

mooncar 17.11.2009 12:35

Вложений: 1
Вот сделал работающий пример по вашему вопросу, реализовано все чисто во флеше.
Запустите HTML-ку и посмотрите на поведение игры при сворачивании браузера, переходе на другую вкладку, на другое приложение, да просто клике на той же странице вне области флешки.
Думаю, что принцип понятен, конечно, это грубое решение, к тому же все ваши обстоятельства были неизвестны. При некоторых достаточно серьезных оговорках можно попробовать использовать.
PS. Если у вас какие-то объекты по сценарию также могут приобретать фокус, то на их onKillFocus нужно также прописать функцию, которая используется в примере и учитывать этот факт в самой функции, чтобы не было ложных срабатываний.

azazul 17.11.2009 13:48

Спасибо большое, но мне, похоже требуется небольшое кормление с ложечки, опыта маловато.
1. Что это за загадочный _level0 ?
2. Не совсем понял, к чему вот это
Код AS1/AS2:

////// БЛОКИРУЮЩЕЕ МЕНЮ ///////////////////////////////////////////
menu_mc.bg.onPress = function  () {
        //пустой обработчик. По идее, нужно еще отключать функции игры
}

3. Можно ли без потерь этот код повесить не на кадр, а на мувик, отвечающий за логику?

4. При прохождении уровня, игра переходит на кадр выхода из уровня, потом на кадр входа, потом снова на кадр с собственно игрой. Все в пределах одной сцены. Не помешает ли подобное адекватно работать вашему коду? (обработка потери фокуса нужна только во время игры, в остальные моменты - не важно, есть она или нету)

mooncar 17.11.2009 13:58

1. _level0 - это сама сцена. В принципе, можно события onEnterFrame вешать на любой мувик.
2. Это к делу не относится - сделано для блокировки активных элементов игры, которые могут находится под блокирующим меню, чтобы пользователь, когда игра на паузе, не нажал чего-нибудь. Ну и слушание клавиатуры надо удалять-ставить (removeListener - addListener).
3. Нет, нельзя, пишите в кадре. Вообще никогда не пишите код на мувиках.
4. Нормально код, без допила, будет работать только в примере, аналогичном моему - два кадра (начало и сама игра) - там же прописан, например, номер кадра (1) и функции стартуют именно в кадре 2.

Идея состоит в том что отслушать потерю фокуса средствами флешки мы можем не всегда - только когда фокус установлен на каком-то объекте (используя onKillFocus).
Когда фокус установлен на null, отследить в AS2 событие потери фокуса никак (по крайней мере мне это неизвестно). Поэтому я сделал перевод фокуса на специальный объект при попадании фокуса на null :
Код AS1/AS2:

function  setFocusOnNullObject () { //принудительная установка фокуса на специальный объект вместо null
        if (!focusOnNullSet && Selection.getFocus() == null) {//если фокус переходит на null, переводим его один раз  на специальный объект
                Selection.setFocus(null_mc);
                focusOnNullSet = true ;
        }
}

Эта функция вызывается постоянно, когда игра работает (т.е. не поставлена на паузу). Как только игра ставится на паузу, функция onEnterFrame удаляется.
И когда этот объект теряет фокус - в примере считается , что пользователь свернул страницу, ушел на другое приложение и т.д.

Добавлено через 12 минут
Если выкинуть все лишнее (оставив блокирующее меню), все сводится к этому:
Код AS1/AS2:

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 минуты
Попробуйте допилить. Запишите все функции в первом кадре, а действия
Код AS1/AS2:

null_mc.onKillFocus = pauseFunc; // при потере фокуса приостанавливают игру
startShowCount(); //установка функции EnterFrame для _level0

- в кадре текущего уровня.
Мувик null_mc должен находится во всех кадрах уровней (уберите его за границы сцены).

azazul 17.11.2009 15:28

Mooncar, огромное спасибо за возню со мной. Просить сделать все за меня не собираюсь, потому как это ущербная практика и я сам в таком случае так ничему и не научусь. Смотреть на мои исходники вам вряд-ли захочется, потому что на сегодняшний день fla-файл весит 38 метров (подлинкованные музыка/звуки/графика/партиклы и все такое) и состоит из сотен страниц кода, в котором разбираться - врагу не пожелаешь.

Managemenu есть свой (что вполне очевидно, пауза-то реализована давно), а само состояние паузы представлено единственной глобально переменной isPaused : Boolean;
Все слушатели мыши/клавиатуры, все обсчеты движения/столкновений/таймеров/счетчиков и вообще всего, чего только можно зависят от значения этой переменной. То есть, когда я в процессе игры тыкаю на ESC, isPaused принимает значение true и все останавливается, а меню "Выйти? ДА/НЕТ" становится видимым и активным (оно все это время лежало прямо посреди игрового экрана, но пока isPaused == false оно прозрачно, а кнопки !visible и !enabled)
Цитата:

Сообщение от mooncar
Вообще никогда не пишите код на мувиках.

Хм. Учился работать с AS по учебникам типа "Macromedia Flash MX. Создание игр с помощью ActionScript". Оттуда собственно и идея создавать за пределами сцены мувиклип с логикой.
Цитата:

Сообщение от mooncar
Мувик null_mc должен находится во всех кадрах уровней

Уровней много, а кадр - один. Генерация/уничтожение объектов окружения/врагов/фона/бонусов и всего такого идет динамически, основываясь на индексе текущего уровня
Цитата:

Сообщение от mooncar
Попробуйте допилить. Запишите все функции в первом кадре, а действия в кадре текущего уровня.

Дело в том, что в кадре текущего уровня есть такая штука как stop(), ибо после него есть еще несколько вспомогательных кадров (анимация завершения уровня, анимация начала уровня, анимация смены левелпака, анимация геймовера). Выходит (если я все правильно понимаю), эти самые действия
Код AS1/AS2:

null_mc.onKillFocus = pauseFunc; // при потере фокуса приостанавливают игру
startShowCount(); //установка функции EnterFrame для _level0

не станут выполняться постоянно, а отработают только один раз, пока головка не наткнется на stop(). Значит надо их сунуть в какой-то onEnterFrame видимо, только в какой...

P.S.: Игра уже на 100% готова (за исключением обсуждаемой фичи), поэтому любые изменения структуры кода отметаются сразу, ибо нету времени потом все эти изменения тестировать на предмет каких-нибудь случайных косяков (не говоря уже о том, что возможно придется половину игры переписать, только для того, чтобы в этом злополучном кадре stop() не стоял)

mooncar 17.11.2009 16:18

Ваша ситуация понятна...
Я еще упростил код, убрал onEnterFrame и ввел ваш триггер:
Код AS1/AS2:

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 (); //первоначальная установка проверки

Вам нужно записать этот код в первом кадре основного таймлайна.
А вот этот вызов
Код AS1/AS2:

checkFocus ();

дописать еще там, где у вас идет снятие с паузы для того, чтобы снова активировать перевод фокуса с null на объект null_mc и отслеживание потери фокуса.
И не забудьте про мувик null_mc, я забыл сказать, он должен на сцене быть как Button (как у меня в примере, можете прямо его скопировать).

Для начала хотя бы добейтесь постановки на паузу, снятие во вторую очередь.

azazul 17.11.2009 19:25

Спасибо огромное, все работает. Правда пришлось чуток поработать напильником, чтобы на переходах не выскакивало и в MainMenu у кнопок фокус не отбирало, но теперь все ништяк. Проблема решена.
Есть в этом форуме репа или типа того? Хочу хоть так отблагодарить :)

mooncar 17.11.2009 20:52

Цитата:

Сообщение от azazul (Сообщение 866265)
Правда пришлось чуток поработать напильником, чтобы на переходах не выскакивало и в MainMenu у кнопок фокус не отбирало, но теперь все ништяк.

Именно об этом я и говорил:
Цитата:

Если у вас какие-то объекты по сценарию также могут приобретать фокус, то на их onKillFocus нужно также прописать функцию, которая используется в примере и учитывать этот факт в самой функции, чтобы не было ложных срабатываний.
Хорошо, что разобрались, как это сделать. Может, конечно еще что-то вылезти, это ведь не очень корректное решение.
Репа-не репа, но интересная задачка была, я сперва вообще создавал массив всех объектов, получающих фокус создавал в автоматическом режиме, но только потому что не знал деталей. Всегда лучше всего максимально полно описывать, тогда и вероятность, что помогут, выше. :)
Пора на AS3 переходить, ох пора.

azazul 17.11.2009 22:29

Цитата:

то на их onKillFocus нужно также прописать функцию, которая используется в примере и учитывать этот факт в самой функции, чтобы не было ложных срабатываний.
Я не так далал. Я делал GameState-ы (в игре, в меню, в переходах и т.д.) и в setFocusOnNullObject() добавлял проверку состояния.
Цитата:

Всегда лучше всего максимально полно описывать, тогда и вероятность, что помогут, выше.
Ну, это же не хелловорлдная задача, тут здоровенный проект - полноценная космическая казуальная стрелялка, всех нюансов никак не опишешь.


Часовой пояс GMT +4, время: 21:19.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.