Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   hitTestPoint глючит (http://www.flasher.ru/forum/showthread.php?t=137718)

sltt 21.03.2010 10:19

hitTestPoint глючит
 
Вложений: 1
Не могу понять в чем дело, подскажите кто знает.

Есть 2 объекта ss1 и ss2.
Хочу узнать находится ли мышка над ними.

Но не непрямую, а через объект higlight, который выравнивается сначала с ss1 и проверяется на пересечение с мышкой, а потом выравнивается с ss2 и тоже проверяется на мышку.

Глюк в том что первая проверка на мышку не срабатывает. Точнее срабатывает только тогда, когда мышь находится на пересечении фигур :(

Код AS3:

import flash.geom.ColorTransform;
var color:ColorTransform = new ColorTransform();;
 
//Выравнивание с ss1
higlight.x = ss1.x;
higlight.y = ss1.y;
//Проверка на мышку и подсветка
        if (higlight.hitTestPoint(mouseX,mouseY,true)) {
                color.redOffset  = 50;
                ss1.transform.colorTransform = color;
        } else {
                color.redOffset  = 0;
                ss1.transform.colorTransform = color;
        }
 
//Выравнивание с ss2
higlight.x = ss2.x;
higlight.y = ss2.y;
//Проверка на мышку и подсветка
        if (higlight.hitTestPoint(mouseX,mouseY,true)) {
                color.redOffset  = 50;
                ss2.transform.colorTransform = color;
        } else {
                color.redOffset  = 0;
                ss2.transform.colorTransform = color;
        }


Этот код может работать так как нужно, только если в hitTestPoint свойство shapeFlag поставить в false, но мне нужно именно true для большей точности.

NBVestal 22.03.2010 11:13

Проблема в том, что скрипт выполняется ВЕСЬ и сразу, то есть фактически

Код AS3:

higlight.x = ss1.x;
higlight.y = ss1.y;

эта часть пропускается (точнее она выполняется, но тут же идёт переопределение):

Код AS3:

higlight.x = ss2.x;
higlight.y = ss2.y;

поэтому код выполняется лишь в том случае, когда мышка над объектом ss2

Предлагаю вам ввести слушатели событий, типа MOUSE_OVER

Добавлено через 5 минут
И кстати, наверняка у вас возникнут проблемы с индексами, ибо рамка выделения всегда будет сверху, посоветую использовать swapChildren и свойство mouseEnabled = false - тем самым оно будет игнорировать объекты на "мышкабельность" и щелчок и наведение мыши будут проходить насквозь

sltt 22.03.2010 16:55

Цитата:

Сообщение от NBVestal (Сообщение 894716)
Проблема в том, что скрипт выполняется ВЕСЬ и сразу

Но если вместо
higlight.hitTestPoint(mouseX,mouseY,true)
написать
higlight.hitTestPoint(mouseX,mouseY,false)
то оно работает

NBVestal 22.03.2010 19:09

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

Добавлено через 24 минуты
Только просмотрите код ВНИМАТЕЛЬНО, вообще по логике вам не нужен hitTestPoint

Код AS3:

import flash.geom.ColorTransform;
var color:ColorTransform = new ColorTransform();
 
 
function ss1_nad(event:MouseEvent):void {
        //Выравнивание с ss1
        higlight.x = ss1.x;
        higlight.y = ss1.y;
 
        color.redOffset = 50;
        ss1.transform.colorTransform = color;
}
 
function ss1_nad_out(event:MouseEvent):void        {
        color.redOffset = 0;
        ss1.transform.colorTransform = color;
}
 
 
function ss2_nad(event:MouseEvent):void {
        //Выравнивание с ss2
        higlight.x = ss2.x;
        higlight.y = ss2.y;
 
        color.redOffset = 50;
        ss2.transform.colorTransform = color;
}       
 
function ss2_nad_out(event:MouseEvent):void {
        color.redOffset = 0;
        ss2.transform.colorTransform = color;
}
 
 
ss1.addEventListener(MouseEvent.MOUSE_OVER, ss1_nad);
ss2.addEventListener(MouseEvent.MOUSE_OVER, ss2_nad);
//добавляем двум объектам слушателей события "мышь над объектом"
 
ss1.addEventListener(MouseEvent.MOUSE_OUT, ss1_nad_out);
ss2.addEventListener(MouseEvent.MOUSE_OUT, ss2_nad_out);
//добавляем двум объектам слушателей события "мышь за пределами объекта"
//соответствующие функции см выше
 
higlight.mouseEnabled = false;
//это ОЧЕНЬ важный пункт - это свойство позволяет мыши как бы пройти НАСКВОЗЬ
//объекта higlight, для того, чтобы мышка взаимодействовала только с ss1 и ss2

если есть вопросы по коду, задавайте...

и ещё одно...все три объекта, естественно, имеют три разных индекса отображения (я про передний и задний план), чтобы подсветка правильно выполнялась, надо постоянно менять местами индексы объектов. Поэкспериментируйте с функцией swapChildren

Добавлено через 34 минуты
И да, не забудьте оставить в своём ролике только ОДИН кадр - первый ключевой

sltt 22.03.2010 20:00

Да, этот код работает, но не в ту сторону.

Как я уже писал, мне нужно определить не момент MOUSE_OVER, MOUSE_OUT на ss1 и ss2, а узнать, находится ли в данный момент мышка над объектом higlight, который выровнян с ss1,ss2.

Поясню для чего это вообще нужно.
Есть куча полупрозрачных png. Все они двигаются.
Мне нужно узнать над какими находится мышка, не учитывая область полупрозрачности.
Я знаю что есть библиотеки для таких случаев, но при размере каждого рисунка 100:100px и их количестве в 50 штук, мувик начинает заметно грузить процессор даже на хорошей машине.

Поэтому изобретаю велосипед.
Есть куча PNG, и одна векторная маска, которая по очереди выравнивается с каждым из рисунков и проверяется на мышку. :wacko:

NBVestal 22.03.2010 20:37

Так в чём проблема? Если нужно узнать, находится ли в данный момент мышка над объектом higlight, то просто добавить слушатель события этому объекту, и сделать тогда проверку на равенство координат с помощью if

а чтобы процессор не грузился, нужно весь код распределить по классам, да к тому же пользоваться addChild() и removeChild() с удалением всех ссылок, чтобы работал сборщик мусора, к тому же можно удалять слушатели события в случае ненадобности (removeEventListener), а то при многократном прохождении кода процессор начинает грузиться, и чем меньше в нём лишнего, и чем динамичней все объекты, тем лучше

а этот способ "векторная маска, которая по очереди выравнивается с каждым из рисунков и проверяется на мышку" это очень нерентабельно с точки зрения программирования, и, естественно, при такой прогонке процессор нереально загружен, поэтому данная проверка должна вызываться, когда мышка находится над экземпляром желаемого объекта, то есть MOUSE_OVER. А прогонять проверку по всем элементам с помощью постоянного обновления кадров или слушателя ENTER_FRAME - это огромная и абсолютно лишняя затрата памяти

sltt 22.03.2010 21:15

Цитата:

Сообщение от NBVestal (Сообщение 894902)
а этот способ "векторная маска, которая по очереди выравнивается с каждым из рисунков и проверяется на мышку" это очень нерентабельно с точки зрения программирования, и, естественно, при такой прогонке процессор нереально загружен

Вы знаете менее затратный способ проверки полупрозрачных PNG на пересечение, нежели перемещение 1-го Sprite и его проверка HitTestPoint?

NBVestal 22.03.2010 21:37

я не понимаю смысл использования HitTestPoint, если вы всё равно накладываете спрайт на объект с точно такими же координатами. гораздо удобнее, по-моему, использовать hitTestObject в этом случае, всё равно тут нет явной проверки на точку. И от прозрачности это не зависит, они всё равно пересекаются границей прямоугольного контейнера, а не фактической графикой...

Или взглянем на этот вопрос по другому...то есть, вам нужно, чтобы объект higlight прошёлся по всем графическим объектам, и в каждом случае выполнялась проверка? Только вот зачем это? Тогда надо задавать какой то интервал, а то все эти перемещения будут мгновенными и незримыми. Ведь можно же просто поставить событие на наведение мышки, которое будет проверять, пересекается ли higlight с объектом, или нет...

Можно, например, задать в конструкторе объекта флаг, который будет меняться, если higlight равен данному объекту, и мышка находится над ним

sltt 22.03.2010 22:08

Вложений: 1
Цитата:

Сообщение от NBVestal (Сообщение 894920)
я не понимаю смысл использования HitTestPoint, если вы всё равно накладываете спрайт на объект с точно такими же координатами. гораздо удобнее, по-моему, использовать hitTestObject в этом случае, всё равно тут нет явной проверки на точку. И от прозрачности это не зависит, они всё равно пересекаются границей прямоугольного контейнера, а не фактической графикой...

public function hitTestPoint(x:Number, y:Number, shapeFlag:Boolean = false):Boolean
shapeFlag:Boolean (default = false) — Указывает, следует ли выполнять тестирование по фактическим пикселам объекта (true) или по рамке (false).

Цитата:

Сообщение от NBVestal (Сообщение 894920)
то есть, вам нужно, чтобы объект higlight прошёлся по всем графическим объектам, и в каждом случае выполнялась проверка? Только вот зачем это? Тогда надо задавать какой то интервал, а то все эти перемещения будут мгновенными и незримыми.

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


Короче я так подумал, что самым оптимальным будет при создании Sprite с рисунком, запихивать туда-же "маску". Потом каждый шаг времени проверять пересечения спрайта и мышки методом hitTestPoint(x,y,false) и если они пересекаются, проверять маску методом hitTestPoint(x,y,true).

NBVestal 22.03.2010 22:22

Цитата:

Сообщение от sltt (Сообщение 894929)
public function hitTestPoint(x:Number, y:Number, shapeFlag:Boolean = false):Boolean
shapeFlag:Boolean (default = false) — Указывает, следует ли выполнять тестирование по фактическим пикселам объекта (true) или по рамке (false).

Знаю, но вы же проверяете не пересечение точки с объектом, а объекта с объектом...

К тому же, маску можно задать с помощью кода, параметр mask, если я не ошибаюсь

Я просто не понимаю, зачем проходиться по всем объектам, если можно добавить в конструкторе класса этого слушатель, и если уж какая то особо узкая специфика, создать своё событие, или отправлять конкретное событие с помощью dispatchEvent();

и чего я уж тем более не понимаю, ЗАЧЕМ проверять пересечение спрайта и мышки методом пересечения точки и спрайта, когда в том же классе можно добавить проверку на нахождение курсора над мышкой...это и проще, и понятнее, и быстрее работает, и не требует ежесекундной проверки, и маска - это не точка, поэтому лучше проверять hitTestObject'ом

Добавлено через 26 минут
просто, возможно, вам нужно взглянуть на вашу задачу с другой стороны, найти альтернативный подход к решению?


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

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