加载外部SWF,分配MOUSE_DOWN事件,并防止点击空白区域/子舞台

发布于 2024-10-26 04:25:04 字数 2072 浏览 3 评论 0原文

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

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

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

子 SWF/动画位于单个时间轴上,我使用位图跟踪来删除导入的 PNG 对象周围的空白空间。如果我将舞台大小减小到对象后面,但随后由于舞台大小小于对象而搞乱了加载的 SWF 的大小,则此方法有效。因此,当我为对象指定宽度和高度时,如果舞台较小,则对象会很大。如果我将舞台大小限制为对象的大小,即使作为跟踪位图图像,舞台仍然可单击。我尝试将 MOUSE_DOWN 事件从主 SW​​F 分配给子 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;
    }
}

I've been developing in Flash now for over 15 years, and recently started developing games in Flash Actionscript 3. I am having some difficulties, and need some help. I've spent days trying to find a solution, with no luck.

I have a main SWF, which loads sub SWF animations. One object can have 5 different animations / SWFs associated with it. So lets say I have a chicken, chicken01.swf, chicken02.swf, ...

I assign a MOUSE_DOWN event to the first loaded SWF, then based on the tool used while clicking on the object, it will load the other animations. My problem is that each SWF has empty space around it which becomes clickable. I only need the object clickable, and not the empty space, because some of the objects can overlap each other, which makes it hard to click on the object behind another object.

The Sub SWFs / animations are on a single timeline, and I played with Bitmap Tracing to remove the empty space around the imported PNG objects. This works if I reduce the Stage size to behind the Object, but then screws up the size of the loaded SWF due to the Stage size being smaller than the object. So when I assign a width and height to the object, with a smaller stage, the object is huge. If I constraint the stage size to the size of the object, even as a Traced bitmap image, the stage is still clickable. I tried to assign the MOUSE_DOWN event to the object on the sub SWF, from the Main SWF, but this gives errors.

My goal is to load a sub SWF, assign the MOUSE_DOWN event, and only have the object clickable, and not the Stage, or empty space around the object.

Is this possible? I also played around with creating an invisible button, but this makes it difficult to assign to 300 + objects of different shapes and sizes.

Below is some of the code I'm using.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

诗笺 2024-11-02 04:25:04

创建一个影片剪辑 - 每个 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();
}

Create a movieclip - a vector shape inside each swf, that is the same shape as your clickable area. Set the alpha to 0% on the vector's fill color. Give it and instance name of something like activeArea, and assign your event listener to that instead of the outer shell moveiclip.

Another approach that might work is to use hitTestObject() on a MOUSE_DOWN event, which would allow you to choose to ignore the transparency.

EDIT

Hard to tell exactly what you are trying to do without seeing it. I didn't actually compile this so I'm not sure if this will work just the way it is, but in theory it should be close. Its a slightly different approach than you are using. I used Loader() instead of SWFLoader, and cleaned up the idea a little bit. As a side note, you should avoid the use of root in as3.

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文