防止影片剪辑重叠

时间:2013-09-05 03:44:50

标签: actionscript-3 flash screensaver

我正在创建一个屏幕保护程序,需要根据屏幕的大小将一个影片剪辑加载到舞台上的随机位置,然后逐渐淡出(我将影片剪辑中的所有动画都作为补间) )

我遇到了路障,无法弄清楚如何防止影片剪辑相互重叠。如果有的话,我希望他们出现在另一个不会引起重叠的随机点上。

这是我项目的所有代码:

 stop();

import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
var greystoneLogos:Array = new Array  ;
var countTimeArray:Array = new Array  ;
var previousLogos:Array = new Array  ;
var xpoint:int;
var ypoint:int;


function getNewSymbols()
{
    previousLogos = new Array  ;
    greystoneLogos = new Array  ;
    var i:int;
    for (i=0; i < 3; i++)
    {
        greystoneLogos[i] = new GreystoneLogo1();
        greystoneLogos[i].width = 100;
        greystoneLogos[i].height = 60;
        addSymbolToStage(greystoneLogos[i],i*2000);

    }
}

getNewSymbols();



function addSymbolToStage(currentLogo:MovieClip,waitTime:int)
{


    var i3:int;
    var i4:int;
var logoBoundaries:Array = new Array()
var XandY:Array = new Array()
    for (i3=0; i3 < greystoneLogos.length; i3++)
    {
        if (greystoneLogos[i3] !== currentLogo)
        {

            xpoint = randomRange(this.stage.stageWidth - (currentLogo.width * 4.8));
            ypoint = randomRange(this.stage.stageHeight - (currentLogo.height * 6.9));
            logoBoundaries = getOffDimensions(currentLogo)

                for (i4=0; i4 < logoBoundaries.length; i4++)
    {
        XandY = logoBoundaries[i4].split(":")

        while ((xpoint <= (Number(XandY[0]) + Number(currentLogo.width * 4.8)) &&  xpoint >= (Number(XandY[0]) - Number(currentLogo.width * 4.8))) && (ypoint <= (Number(XandY[1]) + Number(currentLogo.height * 6.9)) &&  ypoint >= (Number(XandY[1]) - Number(currentLogo.height * 6.9)))){

        xpoint = randomRange(this.stage.stageWidth - (currentLogo.width * 4.8));
        trace(XandY[0] + " And " + (Number(currentLogo.width * 4.8)))
        trace(xpoint + " And " + (Number(XandY[0]) + Number(currentLogo.width * 4.8)))
        ypoint = randomRange(this.stage.stageHeight - (currentLogo.height * 6.9));
        }
    }




        }
        else
        {
            continue;
        }

    }

    previousLogos.push(currentLogo);
    currentLogo.x = xpoint;
    currentLogo.y = ypoint;
    stage.addChild(currentLogo);
    currentLogo.gotoAndStop(1);
    var countTime:Timer = new Timer(waitTime,1);
    countTime.addEventListener(TimerEvent.TIMER, function(){

       currentLogo.gotoAndPlay(1);
       currentLogo.addFrameScript ( currentLogo.totalFrames - 1 , function(){
        currentLogo.stop()
     stage.removeChild(currentLogo)
     if(stage.numChildren <= 1){

    getNewSymbols(); 

     }

       }) ;

       });
    countTime.start();
}

function getOffDimensions(currentLogo:MovieClip){
    var i3:int;
    var tempArr:Array = new Array()
    for (i3=0; i3 < greystoneLogos.length; i3++)
    {
        if (greystoneLogos[i3] !== currentLogo){
        tempArr[i3]=greystoneLogos[i3].x +":"+ greystoneLogos[i3].y
        }
    }
    return tempArr
}

function randomRange(max:Number, min:Number = 0):Number
{
    return Math.random() * (max - min) + min;
}

在代码上跟我说话。这是一个相当快速和肮脏的工作。

也有一些未使用的变量来自我一直在尝试的多个事物。

我发布的代码将使影片剪辑根据出现的最后一个影片剪辑显示在随机位置。因此,假设我们有3个影片剪辑(用户将能够更改显示的剪辑数量)1出现在0,0,另一个出现在400,400,最后一个出现在10,10,因为我无法保存在while循环中要比较的先前值。

我希望这更清楚一点

修改

根据下面显示的功能,我添加了这个:

for (i3=0; i3 < greystoneLogos.length; i3++)
    {
        if (greystoneLogos[i3] !== currentLogo && greystoneLogos[i3] != null)
        {

            while(currentLogo.hitTestObject(greystoneLogos[i3]) == true){  

            xpoint = randomRange(this.stage.stageWidth - (currentLogo.width));
            ypoint = randomRange(this.stage.stageHeight - (currentLogo.height));
            i3 = 0
             }
        }else{
            continue;
        }

    }

这导致一个相当糟糕的循环以及徽标仍然重叠在彼此之上

2 个答案:

答案 0 :(得分:0)

我能想到解决这个问题的最快方法是在新的MovieClip上进行命中测试(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#hitTestObject()),如果它返回true,再次运行放置代码

答案 1 :(得分:0)

好的,这是最快捷方式的实施。 您可以通过.numChildren属性跟踪当前的displayObject。您甚至不需要一系列徽标或东西。假设您有一个功能,可以在屏幕上添加新的movieClip。它知道你可以拥有多少个剪辑(MovieClipDummy只是我的测试类 - 它绘制一个具有指定半径的圆。它应该被你的对象替换。)

private function addAnotherMovieClip(): void {
    if (_currentDummmiesCount < _dummmiesCount) {
        var newDummy: MovieClipDummy = new MovieClipDummy(90);
        addChild(newDummy);
        //If we get a stackoverflow error (see below)
        //we just remove our object from the screen as it will most likely just won't fit
        if (checkForEmptySpace(newDummy) != "") {
            removeChild(newDummy);
            return;
        }
    } else {
        //Do nothing or do something
    }
}

它调用另一个函数checkForEmptySpace,它试图放置你的movieclip,使它不会与其他对象重叠。这是:

private function checkForEmptySpace(newClip: Sprite): String {
    //you should store your screen width somewhere.
    //you can also call stage.stageWidth instead, but first make sure that you
    //always have a link to the stage or it will throw an error
    newClip.x = Math.random() * _screenWidth;
    newClip.y = Math.random() * _screenHeight;
    //===========================
    //Important part - we try to check all the present children of our container
    //numChildren is a property of the DisplayObjectContainer
    for (var i: int; i < numChildren; i++) {
        //We need a try here because we will get a StackOverflow error if there's no empty space left
        try {
            //We need to check if our current display object, received with getChildAt()
            //is not the same as the one we've just added to the screen
            //And if our new object intersects with ANY other object on the stage - we
            //call THIS function once again.
            //We do recursion because we can easily catch an error and remove this object from
            //the screen
            if (newClip != getChildAt(i) && newClip.hitTestObject(getChildAt(i))) {
                //If our recursive function returns an error - we should pass it further
                if (checkForEmptySpace(newClip) != "") {
                    return "error";
                }
            }
            //The only error that can go here is stackoverflow error. So when we get one
            //we return this error string
        } catch (error: Error) {
            trace(error);
            return "error";
        }
    }
    //We only return this empty string if we don't have stackoverflow error
    //so there's possibly no space left for another movieclip
    return "";
}

您可以在没有递归的情况下执行此操作,但您必须使用其他逻辑检查空白区域。

而且,您可以使用Minkowski addition更专业地执行此操作。您应该考虑存储影片剪辑的“边界”点数组(假设每个影片剪辑都是一个矩形),当您向屏幕添加新对象时,您可以计算此Minkowsky的添加。它会在屏幕上显示一些“自由”点,表示新动画片段的任何可能坐标。实现类似的东西是非常有趣的,因为准确性将是惊人的。但如果你没有时间 - 只需使用递归放置功能