【问题标题】:AS3 - dispatch custom event with parameter (not working)AS3 - 使用参数调度自定义事件(不工作)
【发布时间】:2015-01-10 14:02:03
【问题描述】:

我阅读了很多关于调度事件的主题,但我无法让我的代码正常工作。 This topicthis topic 对我想做的事情不感兴趣,但在我的情况下它不起作用。

情况如下:

  • 我的场景是战场,有两艘船
  • 每艘船都知道自己何时被火触碰,因此必须通知包含图形界面的场景
  • 因此船以自身作为参数发送一个自定义事件,因此场景知道何时触摸了船以及哪艘船

我有 3 节课:

  1. 自定义事件类是具有“Ship”属性的事件
  2. EventDispatcher 类
  3. 与我的场景对应的符号类并监听事件

1) 自定义事件类

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) 事件调度器

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

3) 场景

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
    }
}

添加了我的事件监听器,代码通过了 dispatch line,但是没有调用 onShipTouched。

请帮忙,我错过了什么?

我不明白的元素是什么?

这是使用此类事件的好方法吗?还是应该在 Ship 类中设置对场景的引用?

【问题讨论】:

  • 您需要将事件监听器添加到正在调度事件的对象,即您的一艘船。舞台没有调度事件,Ship 的类会这样做。
  • 您很可能正在addEventListenerdispatchEvent 之间更改帧,甚至可能是场景,因此stage 在附加侦听器时和触发事件时是不同的,因此事件到达错误阶段并在没有反应的情况下被丢弃。
  • ship 不是显示对象,因此舞台无法神奇地捕捉到这些事件。顺便说一句:“公共 var 对象:Ship = null;”还有这个“public var object:Ship;”给 ship 相同的值:null。由于 ship 不是显示对象,因此只有 ship 对象可以监听自己的调度。
  • @DodgerThud “您需要将事件监听器添加到正在调度事件的对象中”。我不明白这一点,为什么我需要调度程序上的事件监听器,它已经知道自己发生了什么?
  • @Vesper 我不确定我是否理解,你的意思是 onEnterFrame 方法可能是这里的问题根源吗?我在舞台上添加了一个 KeyboardEvent 侦听器(在我的 Fight 类中),它运行良好。我真的不明白键盘事件的处理方式和我的战斗事件的处理方式之间的区别。

标签: actionscript-3 events


【解决方案1】:

我的逻辑错了:

我正在这样做:eventdispatcher 正在调度事件,而舞台正在监听事件。这是不正确的。

正确的解决方案是:eventdispatcher 正在分发事件,同时也在监听自己分发的事件。 eventlistener 被添加到场景中的 eventdispatcher 中,其中包含要调用的函数。

正如 Vesper 所说,FightEvent 中的参数是无用的,因为 eventdispatcher 实际上是事件目标。

DodgerThud,BotMaster,你给了我这个答案,谢谢你的帮助(看起来我无法将评论设置为“已接受答案”)。

这里是 Fight 类的正确代码:

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
    }
}

【讨论】:

    【解决方案2】:

    您的Ship 类不是MovieClipSprite 或其子类,以便您的活动在显示列表中冒泡,只是因为它们不参与显示列表。因此,您将您的 Ship 更改为 Sprite 子类(这个已经继承了 EventDispatcher),添加图形和 addChild() 都发送到舞台,这样您的舞台将正确接收事件。

    【讨论】:

    • 对象不必是显示对象才能与事件系统正常工作。您的回答有点暗示所有对象都应该是 displayobject 并添加到显示列表中,以便舞台可以捕捉这些事件。这将是一种糟糕的项目编码方式。
    • @BotMaster 看,我同意这种方法在这种情况下是不正确的,但我的意思是为了让事件冒泡到舞台,对象调度此事件应该在显示列表中。显然,在 OP 的代码中情况并非如此。
    猜你喜欢
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多