如何在精灵中获得形状的最顶部x和y值?

时间:2010-07-30 18:17:02

标签: flash actionscript-3

我完全在树林里 - 我有一个画在那里的形状(在这个例子中有两个不同的精灵。)在任何给定的点,我需要获得最高点的x和y值的形状。精灵旋转,所以它也会在任何时候发生变化。我甚至不知道从哪里开始 - 帮忙?

http://paulmignard.com/stackoverflow/pieces.PNG

2 个答案:

答案 0 :(得分:2)

循环所有像素可能相当昂贵。根据经验,只要有可能,让玩家检查像素就更好了。这是我的方法:

function getTopMost(dpo:DisplayObject,global:Boolean = false):Point {
    var bounds:Rectangle = dpo.getBounds(dpo);
    var bmd:BitmapData = new BitmapData(bounds.width,1,true,0);
    var mat:Matrix = new Matrix();
    mat.translate(-bounds.x,-bounds.y);
    bmd.draw(dpo,mat);
    var colRect:Rectangle = bmd.getColorBoundsRect(0xff000000,0,false);
    bmd.dispose();
    var point:Point = new Point(bounds.x + colRect.x,bounds.y + colRect.y);
    var transfMatrix:Matrix = global ? dpo.transform.concatenatedMatrix : dpo.transform.matrix;
    return transfMatrix.transformPoint(point);
}

首先,我们得到显示对象的边界矩形。这样我们就可以立即丢弃任何透明像素。现在,该矩形已经为您提供了精灵的“最低”y(上限),所以现在我们只需要找到相应x偏移的值来获得我们正在寻找的点。此时我们必须测试像素,所以我们需要一个BitampData对象。我们只需要绘制显示对象的可见部分(bounds包围的区域)。但是既然我们已经知道y的值,那么1 px的高度就足够了。这个BitmapData应该允许透明度,我们将在绘制之前用透明的黑色像素填充它(所以我们可以检测到之后的非透明像素;这里我们考虑透明一个alpha值为0且不透明的像素;你可以如果您愿意,可以使用阈值;它需要对代码进行一些小的更改)。在绘制时,我们应用平移仅绘制我们想要的部分,沿着上边界的1 px高度的虚构“线”,与对象的边界一样宽。

一旦我们绘制了BitmapData,我们就会得到一个使用getColorBoundsRect包围所有非透明像素的矩形。这个矩形的x值是我们要寻找的x。现在我们有x和y。那些坐标是相对于对象可见区域(bounds),所以我们必须用bounds的x和y来抵消它们。这是精灵中形状的最左上角。

但这是一个未转换的点,所以如果旋转或缩放精灵,这一点将不会反映这些转换。但是,改变这一点很容易。只需使用精灵的变换矩阵,即可获得相对于其父亲的点。或者,如果您想要一个考虑了从此对象到舞台的所有变换的全局点,请使用精灵的连接矩阵。

修改

一个与上面相同的函数但让你指定一个0到255范围内的alpha阈值。它使用了我之前解释的相同的想法,虽然它的实现有点复杂。

function getTopMostThreshold(dpo:DisplayObject,alphaVal:int,global:Boolean = false):Point {
    if(alphaVal < 0) {
        alphaVal = 0;
    }
    if(alphaVal > 0xff) {
        alphaVal = 0xff;
    }
    var alphaThreshold:uint = alphaVal << 24;
    var dpoBounds:Rectangle = dpo.getBounds(dpo);
    //  draw all pixel with alpha > 0
    var boundsBmd:BitmapData = new BitmapData(dpoBounds.width,dpoBounds.height,true,0);
    var mat:Matrix = new Matrix();
    mat.translate(-dpoBounds.x,-dpoBounds.y);
    boundsBmd.draw(dpo,mat);
    //  any pixel with alpha >= threshold will be set to alpha = 0xff
    boundsBmd.threshold(boundsBmd,
            new Rectangle(0,0,boundsBmd.width,boundsBmd.height),
            new Point(0,0),
            ">=",
            alphaThreshold,
            0xff000000,
            0xff000000);
    //  this rect encloses all pixels that passed the threshold (and hence were set to alpha = 0xff)
    //  With this, we have the value for y
    var alphaBounds:Rectangle = boundsBmd.getColorBoundsRect(0xff000000,0xff000000,true);   
    //  now, let's find the value for x; we know y, so 1 px height will be enough
    var aux:BitmapData = new BitmapData(alphaBounds.width,1,true,0);
    //  again, any pixel with alpha >= threshold will be set to alpha = 0xff
    aux.threshold(boundsBmd,
            alphaBounds,
            new Point(0,0),
            ">=",
            alphaThreshold,
            0xff000000,
            0xff000000);
    //  this rect will gives us the x value
    var colRect:Rectangle = aux.getColorBoundsRect(0xff000000,0xff000000,true);
    boundsBmd.dispose();
    aux.dispose();
    //  now, just add up the offsets: 
    //      the bounds of the dpo (that is, every px with alpha > 0)
    //      the area that encloses every px with alpha >= threshold
    //      the color bounds rect of the aux bmd we used to find x 
    var point:Point = new Point(dpoBounds.x + alphaBounds.x + colRect.x,
                                dpoBounds.y + alphaBounds.y + colRect.y);
    var transfMatrix:Matrix = global ? dpo.transform.concatenatedMatrix : dpo.transform.matrix;
    return transfMatrix.transformPoint(point);
}

答案 1 :(得分:1)

嘿,我觉得你正在尝试使用这个精灵。如果是这样,我建议您在该位置设置注册点,即在该特定点设置图像的原点。然后可以很容易地使用精灵。使用x&amp; amp; y坐标。

  • 如果你动态地这样做,即 你正在通过as3绘制图像 然后从那一点开始画画。 您的注册点将保留 与原产地相同。
  • 如果您使用闪光灯来绘制 图像设置图像使点 发生在0,0。