PDA

Просмотр полной версии : Получить id объекта при hitTest.


Astraport
07.09.2011, 16:20
Программно создаются объекты:

for (var i:uint = 0; i <maxImages; i++){
var newimg:Image = new Image();
newimg.height = 100;
newimg.width = 100;
newimg.x = 100+ i*100;
newimg.y = 200;
newimg.source = 'images/' + i + 'img.png';
newimg.id = i + 'img';
this.addElement(newimg);
}

При инициализации создаю слушатель и двигаю героя. При взаимодействии героя с созданными графическими объектами требуется получить их id:
addEventListener(Event.ENTER_FRAME, startDragging);

protected function startDragging(event:Event):void
{
if (newimg.hitTestPoint(hero.x, hero.y, true)){
trace ('Hero hitTest ' + event.currentTarget.id); //Это понятное дело не работает
}

}

Как лучше это сделать?
Спасибо.

bav
07.09.2011, 16:42
if (newimg.hitTestPoint(hero.x, hero.y, true)) {
newimg.dispatchEvent( /* тут можно какое-нибудь свое событие определить */ );
}

Далее, где вам нужно, ловите это событие и обращаетесь к event.target.

-De-
07.09.2011, 16:43
trace ('Hero hitTest ' + newimg.id);
Как обьекты перебираются-то?

Astraport
07.09.2011, 17:16
Как обьекты перебираются-то?
Не понял. newimg.id - выводит только id последнего объекта.

Далее, где вам нужно, ловите это событие и обращаетесь к event.target.

Я сделал так:
1. Создал новый ивент класс:
package
{
import flash.events.Event;

public class HitTestEvent extends flash.events.Event
{
public static const CONTROL_TYPE:String = "hit";
public var command:String;
public function HitTestEvent(command:String)
{
super(CONTROL_TYPE);
this.command = command;
}
}
}

2. Диспатчу так:
if (newimg.hitTestPoint(hero.x, hero.y, true)) {
newimg.dispatchEvent(new HitTestEvent('hit')); );
}
или так:
if (newimg.hitTestPoint(hero.x, hero.y, true)) {
dispatchEvent(new HitTestEvent(newimg.id));
}
3. При инициализации приложения вешаю слушатель:
addEventListener(HitTestEvent.CONTROL_TYPE, eventHandler);
}

protected function eventHandler(event:HitTestEvent):void
{
trace(event.command);
trace(event.target.id);
trace(event.currentTarget.id);
}

В любом случае трейсится все что угодно, но не id объектов.

bav
07.09.2011, 17:33
if (newimg.hitTestPoint(hero.x, hero.y, true)) {
newimg.dispatchEvent(new HitTestEvent('hit') );
}
// Здесь неясно куда вы вешаете слушатель. Попробуйте перехват событий:
addEventListener(HitTestEvent.CONTROL_TYPE, eventHandler, true);

// А в трейсе выведите event.target
protected function eventHandler(event:HitTestEvent):void
{
trace(event.target); // [object Image] ?
trace((event.target as Image).id);
}

Astraport
07.09.2011, 17:48
bav, спасибо, но проблема не в этом. Только сейчас заметил, что hitTestPoint трейсится только для последнего объекта.
-De- видимо правильно заметил, что нужен перебор объектов. Но как? Все объекты выводятся, но hitTestPoint получается только для последнего из них.

-De-
07.09.2011, 17:50
Ну с кем хиттестится, того айди и выводит. В чем проблема-то?

if (newimg.hitTestPoint(hero.x, hero.y, true)) {
eventHandler(newimg.id);
}
...
protected function eventHandler(id:int):void
{
trace(id); // id
}
Вы это пытаетесь сделать?

Astraport
07.09.2011, 18:14
-De-, я ж говорю - хиттест срабатывает только для последнего созданного объекта. В моем примере, если maxImages = 5, с id = '4img'. Остальные никак не реагируют, хотя если повесить на каждый создаваемый объект слушатель на мышиные события - то они срабатывают (мышиные события).

-De-
07.09.2011, 18:17
Ээ а вы не догадывались, что хиттест будет срабатывать только для тех обьектов, для которых он будет вызываться?

Astraport
07.09.2011, 18:30
Догадывался:) Сбило с толку то, что трейсились события. Оказывается, это от одного объекта исходило, близко расположены.
Хорошо. Я знаю id этих всех объектов. Как мне обратится к объекту зная Id?
getChildByName выдает ошибку Не удается вызвать свойство или метод со ссылкой на объект "null".

bav
07.09.2011, 18:42
Можете, например, хранить ссылки на объекты в массиве, или в объекте, или в словаре. В любом случае ключом будет Id.

Astraport
07.09.2011, 22:03
bav, понятно, но это же будет здорово кушать производительность.

Я правильно понял:
private var imgArray:Array = new Array();

for (var i:uint = 0; i <maxImages; i++){
var newimg:Image = new Image();
newimg.height = 100;
newimg.width = 100;
newimg.x = 100+ i*100;
newimg.y = 200;
newimg.source = 'images/' + i + 'img.png';
newimg.id = i + 'img';
this.addElement(newimg);
imgArray.push(newimg)//добавляем объект в массив

}

Затем:
addEventListener(Event.ENTER_FRAME, startDragging);

protected function startDragging(event:Event):void
{
for (var i:uint = 0; i <maxImages; i++){ //Для каждого кадра!!!
if (imgArray[i].hitTestPoint(hero.x, hero.y, true)){
eventHandler(imgArray[i].id);
}
}

}

private function eventHandler(id:String):void
{
trace("ID " + id);
}

А если у меня maxImages = 500 или того больше?
Нет ли другого решения?

Psycho Tiger
07.09.2011, 22:57
Отсекайте заведомо, которые пересечься не могут.
Например, разделите мысленно экран на сетку размером с этот image. Тогда на hitTest надо будет проверить только 9 смежных клеток.

alex3dsflash
08.09.2011, 12:25
У меня такие же проблемы - раскопировал мувиклипов, а как к ним обратиться не знаю. Вы не решили проблему?

Astraport
08.09.2011, 14:31
Я решил, см. код выше. Но меня смущает производительность (нагрузка на проц и память). Хотя смотрел с 50 объектами - особого повышения загрузки проца нет. Процентов на 3-5% прибавилось.

dimarik
08.09.2011, 15:38
Рекомендую (http://lab.polygonal.de/category/actionscript/page/6/). Есть там и другие статьи по collision detection.