【问题标题】:Load External SWF, assign MOUSE_DOWN event, and prevent empty space / sub stage from being clicked加载External SWF,分配MOUSE_DOWN事件,防止空白/子舞台被点击
【发布时间】:2011-03-24 04:30:45
【问题描述】:

我已经使用 Flash 开发超过 15 年,最近开始使用 Flash Actionscript 3 开发游戏。我遇到了一些困难,需要一些帮助。我花了几天时间试图找到解决方案,但没有成功。

我有一个主 SWF,它加载子 SWF 动画。一个对象可以有 5 种不同的动画/SWF 与之关联。所以假设我有一只鸡,chicken01.swf,chicken02.swf,...

我为第一个加载的 SWF 分配了一个 MOUSE_DOWN 事件,然后根据单击对象时使用的工具,它将加载其他动画。我的问题是每个 SWF 周围都有空白区域,可以点击。我只需要可点击的对象,不需要空白空间,因为有些对象可以相互重叠,这使得点击另一个对象后面的对象很难。

子 SWF / 动画位于单个时间轴上,我使用位图跟踪来删除导入的 PNG 对象周围的空白区域。如果我将舞台大小减小到对象后面,则此方法有效,但由于舞台大小小于对象,因此会增加加载的 SWF 的大小。因此,当我为对象分配宽度和高度时,使用较小的阶段,对象就很大。如果我将舞台大小限制为对象的大小,即使是跟踪位图图像,舞台仍然是可点击的。我试图从主 SW​​F 将 MOUSE_DOWN 事件分配给子 SWF 上的对象,但这会产生错误。

我的目标是加载一个子 SWF,分配 MOUSE_DOWN 事件,并且只有对象可点击,而不是舞台或对象周围的空白区域。

这可能吗?我也尝试过创建一个不可见的按钮,但这使得分配给 300 多个不同形状和大小的对象变得很困难。

以下是我正在使用的一些代码。

var loadimage = foreground_list[i].imagelocation + foreground_list[i].image;

var loader:SWFLoader = new SWFLoader(loadimage,{container:tn_mc,x:current_tn_x,y:current_tn_y,name:current_name,alpha:1,width:current_tn_w,height:current_tn_h,rotation:0});

loader.load();
tn_mc.buttonMode = true;

tn_mc.addEventListener( MouseEvent.MOUSE_DOWN, tn_down );
tn_mc.addEventListener( MouseEvent.MOUSE_UP, tn_up );

addChild( tn_mc );


function tn_down(e:MouseEvent):void
{
    switch (MovieClip(this.root).PointerTool)
    {
        case "move" :

            stage.addEventListener(MouseEvent.MOUSE_UP, stage_up );

            e.target.startDrag();
            break;
        case "play" :

            var loader4:SWFLoader = new SWFLoader(foreground_list.imagelocation + foreground_list.playimage,{container:tn_mc,name:e.target.name,x:foreground_list.setx,y:foreground_list.sety,width:foreground_list.setw,height:foreground_list.seth,rotation:0});
            tn_mc.removeChildAt(0);
            tn_mc.addEventListener( MouseEvent.MOUSE_DOWN, tn_down );
            tn_mc.addEventListener( MouseEvent.MOUSE_UP, tn_up );

            loader4.load();
            loader4.addEventListener(Event.COMPLETE, completeactionHandler);
            break;

        default :
            //Some other animation
            break;
    }
}

【问题讨论】:

  • 您应该在加载的 SWF 中定位一个实例,而不是整个 SWF。

标签: actionscript-3 mouseevent loader stage


【解决方案1】:

创建一个影片剪辑 - 每个 swf 内的矢量形状,与您的可点击区域的形状相同。将矢量填充颜色的 alpha 设置为 0%。给它和类似 activeArea 之类的实例名称,并将您的事件侦听器分配给它而不是外壳 moveiclip。

另一种可行的方法是在 MOUSE_DOWN 事件上使用 hitTestObject(),这将允许您选择忽略透明度。

编辑

如果没有看到它,很难准确地说出你想要做什么。我实际上并没有编译它,所以我不确定它是否会按原样工作,但理论上它应该很接近。它与您使用的方法略有不同。我使用 Loader() 而不是 SWFLoader,并稍微清理了这个想法。附带说明一下,您应该避免在 as3 中使用 root

var _swfLoader:Loader;

var loadimage = foreground_list[i].imagelocation + foreground_list[i].image;

var loader:SWFLoader = new SWFLoader(loadimage,{container:tn_mc,x:current_tn_x,y:current_tn_y,name:current_name,alpha:1,width:current_tn_w,height:current_tn_h,rotation:0});

loader.load();
tn_mc.buttonMode = true;

tn_mc.addEventListener( MouseEvent.MOUSE_DOWN, tn_down );

addChild( tn_mc );

function tn_down(e:MouseEvent):void
{
    tn_mc.addEventListener( MouseEvent.MOUSE_UP, tn_up );

    switch (MovieClip(this.root).PointerTool)
    {
        case "move" :

            stage.addEventListener(MouseEvent.MOUSE_UP, stage_up );
            e.target.startDrag();

        break;

        case "play" :

            _swfLoader = new Loader();
            var req:URLRequest = new URLRequest(foreground_list.imagelocation + foreground_list.playimage);
            _swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, animationLoaded);

            _swfLoader.load(req);

        break;

        default :

            //Some other animation

        break;
    }
}

function tn_up(e:MouseEvent):void
{
    tn_mc.removeEventListener( MouseEvent.MOUSE_UP, tn_up );
}

function animationLoaded(evt:Event):void
{
    _swfLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, animationLoaded);

    tn_mc.removeChildAt(0);

    var loadedSwf = evt.target.content;
    loadedSwf.x = foreground_list.setx;
    loadedSwf.y = foreground_list.sety;
    loadedSwf.width = foreground_list.setw;
    loadedSwf.height = foreground_list.seth;
    loadedSwf.rotation = 0;

    loadedSwf.addEventListener(MouseEvent.MOUSE_DOWN, onAnimationStart);

    // might wanna add theses to an array to keep track of them and run clean up later on

    // now add to some display list
}

function onAnimationStart(evt:MouseEvent):void
{
    loadedSwf.addEventListener(MouseEvent.MOUSE_UP, onAnimationStop);

    // play your animation or whatever else
    evt.target.play();
}

function onAnimationStop(evt:MouseEvent):void
{
    loadedSwf.removeEventListener(MouseEvent.MOUSE_UP, onAnimationStop);

    // stop your animation or whatever else
    evt.target.stop();
}

【讨论】:

  • 我会尝试两种方法,看看哪一种效果最好。你能举例说明如何使用 hitTestObject() 函数吗?这会进入 MOUSE_DOWN 函数吗?感谢您的快速回复。所以习惯了旧的 AS2 日子,并于去年开始使用 AS3。我喜欢它,但是在 AS2 中如此简单的事情,在 AS3 中似乎需要更多时间来构建。
  • 我只是对 hittest 做了一个快速测试,不会工作,坚持第一个想法。但是要回答您的问题,有两种方法 hitTestPoint,它将一个点与一个对象进行比较:myMovieClip.hitTestPoint(stage.mouseX, stage.mouseY)。另一个是 hitTestObject,它比较两个对象是否重叠:myMovieClip.hitTestObject(MyOtherMovieClip)。它们都有一个可选的第三个布尔参数,表示是包含动画剪辑的边界区域(包括透明度),还是只关注可见像素。
  • 两种方法都试过了,但都没有成功。使用 0 alpha 创建了矢量轮廓,但必须转换为符号才能应用实例名称,除非有另一种添加实例名称的方法。我只是不知道如何从主 SW​​F 应用点击事件。无论我点击哪里,hitTest 总是返回错误。使用 mouseX 和 mouseY,但没有帮助。关于这些函数的代码的任何想法。对 hitTest 进行了研究,并尝试了一些没有运气的示例。
  • 只是为了帮忙,我压缩了一个示例,并将其上传到一个站点供您查看。 yourcrib.net/testchicken.zip 这也有源 fla 文件。我将继续测试,只是认为这会有所帮助。这不包括矢量轮廓。如果您有任何问题或发现什么,请告诉我。
  • 我用另一种方法编辑了我的答案。看看,我会同时看看你的代码。
猜你喜欢
  • 1970-01-01
  • 2014-09-01
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 1970-01-01
  • 2015-04-28
  • 2010-12-07
相关资源
最近更新 更多