0
votes

I read a lot of topics about dispatching event but I can't make my code work. This topic and this topic are closed to what I would like to do, but it's not working in my case.

Here is the situation :

  • My scene is a battle field and has two ships
  • Each ship knows when it is touched by a fire, so it has to inform the scene that contains the graphic interface
  • So the ship dispatch a custom event with itself as parameter, so the scene knows when a ship is touched and which ship

I have 3 classes :

  1. The custom event class is an event that has a property "Ship"
  2. The EventDispatcher class
  3. The symbole class that corresponds to my scene and listen to the event

1) CustomEvent class

public class FightEvent extends Event
    {
        public static const SHIP_TOUCHED:String = "SHIP_TOUCHED"; //type
        public var object:Ship = null; //object to pass

        public function FightEvent(type:String, pObject:Ship, bubbles:Boolean=true, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
            object = pObject;
        }

        public override function clone():Event
        {
            return new FightEvent(type, object, bubbles, cancelable);
        }
    }

2) EventDispatcher

public class Ship extends EventDispatcher
{
    private function updateDamages():void
    {
        //compute damages
        dispatchEvent( new FightEvent( FightEvent.SHIP_TOUCHED, this ) );
    }
}

3) Scene

public class Fight extends customMovieClip
{
    private var playerShip:Ship; //I have two ships, player and enemy
    private var enemyShip:Ship;

    public function init():void
    {
         stage.addEventListener(FightEvent.SHIP_TOUCHED, onShipTouched);
         //I made a test : the event listener is correctly added
    }

    private function onShipTouched(e:FightEvent):void
    {
        //update the graphic interface to show damages
    }
}

My event listener is added, the code passes on the dispatch line, but onShipTouched is not called.

Please help, what did I miss ?

What is the element I didn't understand ?

Is it a good way to use events like this ? or should I set a reference to the scene inside the Ship class ?

2
You need to add the eventlistener to the object that is dispatching the event, that is, one of your ships. the stage is not dispatching the event, the Class Ship does that. - user2655904
Most likely you are changing frames between addEventListener and dispatchEvent, or probably even scenes, thus the stage is different at the time of attaching the listener and the time when the event is fired, so the event reaches wrong stage and is dropped with no reaction. - Vesper
ship is not a displayobject so stage can't magically catch those events. btw this: "public var object:Ship = null;" and this "public var object:Ship;" give ship the same value: null. Since ship is not a displayobject only ship object can listen to their own dispatch. - BotMaster
@DodgerThud "You need to add the eventlistener to the object that is dispatching the event". I don't understand this, why would I need an eventlistener on the dispatcher that already know what is happening to itself ? - Tari-Green
@Vesper I am not sure if I understand, do you mean that the onEnterFrame method could be a source of problem here ? I have a KeyboardEvent listener added to the stage (in my class Fight), and it works perfectly. I don't really get the difference between the way the keyboard event is handled and the way my fight event is handled. - Tari-Green

2 Answers

0
votes

Your Ship class is not a MovieClip, Sprite or their subclass in order for your event to bubble up the display list, just because they don't participate in a display list. So, you change your Ship to Sprite subclass (this one already inherits EventDispatcher), add graphics and addChild() both ships to the stage, this way your stage will receive events properly.

0
votes

My logic was wrong :

I was doing this : the eventdispatcher is dispatching the event, and the stage is listening to the event. That is incorrect.

The right solution is : the eventdispatcher is dispatching the event, and is also listening to its own dispatched event. The eventlistener is added to the eventdispatcher in the scene, that contains the function to call.

As Vesper said, the parameter in FightEvent is useless, as the eventdispatcher is actually the event target.

DodgerThud, BotMaster, you gave me this answer, thank you for your help (Looks like I can't set a comment as "answer accepted").

Here the right code for the Fight class :

public class Fight extends customMovieClip
{
    private var playerShip:Ship; //I have two ships, player and enemy
    private var enemyShip:Ship;

    public function init():void
    {
        enemyShip.addEventListener(FightEvent.SHIP_TOUCHED, onShipTouched);
        playerShip.addEventListener(FightEvent.SHIP_TOUCHED, onShipTouched);
    }

    private function onShipTouched(e:FightEvent):void
    {
        //e.target == the ship that dispatched the event
    }
}