ПрограммированиеФорумОбщее

ActionScript 3.0. События мышки для Sprite. Есть проблема.

Страницы: 1 2 3 4 Следующая »
#0
11:48, 9 фев 2012

Всем доброго утра!

У меня имеется базовый класс для всех выводимых объектов RenderObject:

package d.game.render
{
  import d.game.map.MapObject;
  import flash.display.Bitmap;
  import flash.display.DisplayObject;
  import flash.display.MovieClip;
  import flash.display.Sprite;
  
  // Объект для вывода
  public class RenderObject extends Sprite
  {
    public static const STATIC_OBJECT    :uint  = 0;
    public static const DYNAMIC_OBJECT    :uint  = 1;
    
    public var type:uint=0;                    // Тип объекта
    public var desc:MapObject=null;                // Описание объекта на карте
    
    // Конструктор
    public function RenderObject(_displayObject:DisplayObject)
    {
      if(_displayObject is Bitmap)
      {
        var bitmapSource:Bitmap=_displayObject as Bitmap;
        var bitmapDuplicate:Bitmap=new Bitmap(bitmapSource.bitmapData);
        
        addChild(bitmapDuplicate);
      }
      else if(_displayObject is MovieClip)
      {
        var movieClipSource:Class=Object(_displayObject).constructor as Class;
        var movieClipDuplicate:MovieClip=new movieClipSource();
        
        addChild(movieClipDuplicate);
      }
    }
    
  }

}

Собственно из кода видно что туда я засовываю либо рисунок (Bitmap), либо клип (MovieClip). Каждый такой класс я подписываю на события мышки:

renderDynamicObject.addEventListener(MouseEvent.MOUSE_OUT,OnMouseOutDynamicObject);
renderDynamicObject.addEventListener(MouseEvent.MOUSE_OVER,OnMouseOverDynamicObject);

И вот обработка:

private function OnMouseOutDynamicObject(_event:MouseEvent):void
{
  var renderDynamicObject:RenderDynamicObject=_event.currentTarget as RenderDynamicObject;
      
  renderDynamicObject.filters=null;
}
    
private function OnMouseOverDynamicObject(_event:MouseEvent):void
{
  var renderDynamicObject:RenderDynamicObject=_event.currentTarget as RenderDynamicObject;
      
  renderDynamicObject.filters=Game.mapFilter.objectFilter;
}

Если кому интересно, то RenderDynamicObject унаследован от RenderObject:

package d.game.render
{
  import d.game.map.MapDynamicObject;
  import flash.display.DisplayObject;
  
  // Вывод динамического объекта
  public class RenderDynamicObject extends RenderObject
  {
    // Конструктор
    public function RenderDynamicObject(_desc:MapDynamicObject,_displayObject:DisplayObject)
    {
      type=DYNAMIC_OBJECT;
      
      desc=_desc;
      super(_displayObject);
    }
    
  }

}

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

Изображение

На рисунке пугало - это Bitmap. Я мышкой ещё не навёл на объект, а он уже подсветился. Такое ощущение что он активирует наводку даже на прозрачном месте.

Как это исправить? Чтобы он тютельку в тютельку наводил.

#1
12:08, 9 фев 2012

s3dworld
Ты можешь в OnMouseOverDynamicObject(_event:MouseEvent) проверять альфу битмапа? Т.е. из евента получить координаты курсора и проверить эту точку - прозрачна она или нет в битмапе?

#2
12:13, 9 фев 2012

не. так криво получится.

#3
12:27, 9 фев 2012

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

#4
12:31, 9 фев 2012

Подкинули мне ссылку на InteractivePNG. Скачал. Вот тут документация. Но если честно, я таки не понял как этот класс использовать. Ну да я его создам. Но как в него рисунок запихать я так и не понял.

Есть какие-то соображения?

#5
13:02, 9 фев 2012

s3dworld
да сделай свой класс.
у тебя есть битмап дата. дак вот при наведении мышью включай проверку по прозрачности пиксели в каждом кадре. ну и всё будет.

#6
13:07, 9 фев 2012

ИПавлов
чем это отличается от того, что я предложил в #1 ?
На AS никогда не писал, какие нюансы?

#7
13:21, 9 фев 2012

В общем я так и сделал как предложил Помеха. Подписываю на три события (хотя одно пока лишнее):

renderDynamicObject.addEventListener(MouseEvent.MOUSE_OUT,renderDynamicObject.OnMouseOut);
renderDynamicObject.addEventListener(MouseEvent.MOUSE_OVER,renderDynamicObject.OnMouseOver);
renderDynamicObject.addEventListener(MouseEvent.MOUSE_MOVE,renderDynamicObject.OnMouseMove);

И обрабатываю:

// Увели с динамического объекта
public function OnMouseOut(_event:MouseEvent):void
{
  filters=null;
}
    
// Навели на динамический объект
public function OnMouseOver(_event:MouseEvent):void
{
}
    
// Водим по динамическому объекту
public function OnMouseMove(_event:MouseEvent):void
{
  if(graphType==BITMAP)
  {
    var color:uint=bitmap.bitmapData.getPixel32(_event.localX,_event.localY);
        
    var colorAlpha:uint  = color  >>>  24      ;
    var colorRed:uint  = color  >>>  16  & 0xFF  ;
    var colorGreen:uint  = color  >>>  8  & 0xFF  ;
    var colorBlue:uint  = color      & 0xFF  ;
        
    if(colorAlpha>0)
      filters=Game.mapFilter.objectFilter;
    else
      filters=null;
  }
}

Работает на ура! Хотя прибавилось ещё две проблемы. Сейчас расскажу Вам о них...

#8
13:24, 9 фев 2012

да никакой разницы, только овер обрабатывается один раз при наведении. и надо обрабатывать при перемещении.
да и нафига брать все цвета, если надо только альфу. ну в общемто всё.

я бы ещё по другому сделал вместо
(_event.localX,_event.localY);
я бы
bitmap.mouseX,bitmap.mouseY,

#9
13:50, 9 фев 2012

Карта в игре изометрическая (2.5D).

Изображение

При обращении к ячейке карты первым параметром я указываю номер столбца, а затем номер строки. Вывод полей идёт по простому алгоритму - перебор от столбцов к полям (конечно у меня все поля рисуются на один общий Bitmap и затем он выводится на экран). Что касается объектов (статические, динамические, монстры и NPC), то для них предусмотрен другой слой, который лежит поверх Bitmap с ячейками карты. Для вывода объектов (то есть кто поверх кого стоит) написана функция сортировки (ведь не все объекты имеют размер в 1x1 ячейки). К статическим же объектам я не применяют никаких операций, они просто выводятся и сортируются при изменении состояния мира, а так же для них я отключаю свойство mouseEnabled, чтобы они не мешали другим объектам обрабатывать события мышки. Что касается динамических объектов, то они могут быть либо подгружаемым Bitmap, либо подгружаемым SWF (то есть MovieClip). Собственно для вывода всего есть общий корень RenderObject:

+ Показать


Каждый выводимый динамический объект является классом RenderDynamicObject:

+ Показать

А теперь посмотрите на рисунок:

Изображение

Обратите внимание на дерево и сундук. Это два динамических объекта с которыми можно взаимодействовать. Дерево подгружается через Loader как Bitmap, сундук - SWF (MovieClip). Что касается подсвечивания Bitmap, я с Вашей помощью разобрался. Теперь всю внимание на MovieClip...

На рисунке выше сундук будет поверх дерева (это всё верно). При наведении на сундук, он будет выделяться даже тогда, когда я навёл на его прозрачные пиксели. А вот это мне не понятно, я считал что MovieClip весь из себя интерактивный и всё умеет понимать. Как мне для него сделать так, чтобы он понимал что не нужна мне обводка при наведении на прозрачные пиксели?

Вторая проблема заключается в том, что сундук перекрывает часть дерева (да, на рисунке так и не скажешь, но невидимые пиксели перекрывают), и когда хочешь выделить дерево наведением на его ствол, выделяется сундук.

Какие есть идеи?

#10
13:59, 9 фев 2012

тоже самое, только вместо ГетПиксель делаешь
object.hitTestPoint(object.mouseX,object.mouseY,true);

так можно было и в первом случае делать.

хотя нет. снова фигня.

#11
14:11, 9 фев 2012

ИПавлов
Так?

public function OnMouseMove(_event:MouseEvent):void
{
  if(graphType==BITMAP)
  {
    var color:uint=bitmap.bitmapData.getPixel32(_event.localX,_event.localY);
        
    var colorAlpha:uint  = color  >>>  24      ;
    var colorRed:uint  = color  >>>  16  & 0xFF  ;
    var colorGreen:uint  = color  >>>  8  & 0xFF  ;
    var colorBlue:uint  = color      & 0xFF  ;
        
    if(colorAlpha>0)
      filters=Game.mapFilter.objectFilter;
    else
      filters=null;
  }
  else
  {
    if(movieClip.hitTestPoint(movieClip.mouseX,movieClip.mouseY,true))
      filters=Game.mapFilter.objectFilter;
    else
      filters=null;
  }
}

Не работает!

#12
14:19, 9 фев 2012

Работает так:

if(movieClip.hitTestPoint(_event.stageX,_event.stageY,true))
  filters=Game.mapFilter.objectFilter;
else
  filters=null;

Но аналогично что и просто наведению.

#13
14:21, 9 фев 2012

попробуй не
movieClip.mouseX,movieClip.mouseY
а
mouseX,mouseY

movieClip.hitTestPoint(_event.stageX,_event.stageY,true))
он там в экранных координатак считает.

#14
14:23, 9 фев 2012

ИПавлов
if(movieClip.hitTestPoint(mouseX,mouseY,true)) не пашет.

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.