4

每次我用谷歌搜索这个问题时,我都会看到关于面具和混合物的令人困惑的信息,这些信息似乎都没有直接适用于我认为应该是一件容易的事情......

这里涉及三个精灵……最低层的精灵几乎是一个背景。我想在背景上覆盖一个半透明的 Sprite,然后我想让第三个,最上面的 Sprite 作为一个洞,这样第三个 Sprite 内部的区域是完全透明的,这样背景 Sprite 就完全可见了。

我将如何动态地执行此操作(即使用 Actionscript 图形调用动态绘制掩蔽精灵和孔)?

4

6 回答 6

7

我知道这已经是很久以前的事了,但仅适用于可能寻找相同问题的人。这实际上很容易(只要用图形类绘制你的 Sprite)。

1)不灵活的孔切割:

this.graphics.beginFill(0x666666);
this.graphics.drawRect(0,0,256, 256);
this.graphics.drawCircle(128,128,32);
this.graphics.endFill();

这将创建一个 256 x 256 的矩形,其中有一个 64px 的孔。

2) 柔性孔切割:

显然,当您不使用图形类时,这将不起作用。在那种情况下,我会选择BlendMode.ERASE.

var spr:Sprite = new Sprite();
var msk:Sprite = new Sprite();

addChild(spr);
spr.addChild(msk)

spr.graphics.beginFill(0x666666);
spr.graphics.drawRect(0,0,256, 256);
spr.graphics.endFill();

msk.graphics.beginFill(0x000000);
msk.graphics.drawEllipse(0,0,64,64);
msk.graphics.endFill();
msk.x = 128;
msk.y = 128;

spr.blendMode = BlendMode.LAYER;
msk.blendMode = BlendMode.ERASE;

使用 BlendMode.ERASE 时,您必须始终将父容器的混合模式设置为 BlendMode.LAYER,否则将不起作用。

我希望这可以帮助某人

于 2012-03-28T15:24:18.840 回答
2

如果我没记错的话,如果你在同一个图形上绘制两个重叠的对象而不停止填充,它们的工作原理很像 blendmode.erase。伪代码如下所示:

graphics.beginFill (any color, any alpha);
graphics.drawRect(0,0,256, 256);
graphics.drawRect(128,128,64, 64);
graphics.endfill ();

如果这确实有效(我想我多年前使用过这个解决方案,并且最近才看到 SVG 文件以这种方式工作),这应该会给您带来更好的性能。

编辑:我刚刚在我的一个游戏中使用了这个。

于 2013-07-04T14:14:04.023 回答
0

如果有人需要渐变孔,可以使用 Raimundas 的技巧。假设您想要从内到外的椭圆渐变(内半径 alpha = 0,外半径 alpha = 1)。

先画出没有椭圆的背景

var gfx:Graphics;
gfx.clear();
gfx.beginFill(color, alpha );
gfx.drawRect(0, 0, width, height); // fullscreen

gfx.drawEllipse(e_x, e_y, e_width, e_height); // trick - drawn in the same beginFill

gfx.endFill();

然后在结果孔内绘制渐变椭圆!

var mat : Matrix = new Matrix();
mat.createGradientBox(width, height, 0, e_x, e_y);

gfx.lineStyle(); // I think it resets lineStyle
gfx.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, mat);
gfx.drawEllipse(e_x, e_y, width, height);
gfx.endFill();

椭圆将完全匹配孔,像素完美。

于 2014-04-17T09:06:09.590 回答
0

不是 AS 开发人员,但看看这个:http ://code.google.com/p/gpcas/

这应该使您能够对两个多边形进行布尔“剪切”操作。

于 2010-02-03T22:32:43.937 回答
0

看看这个方法,它允许一个可选的“hole”参数。这可以在 flex 框架的 ProgrammaticSkin 类中找到。

http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/frameworks/projects/framework/src/mx/skins/ProgrammaticSkin.as

/**
     *  Programatically draws a rectangle into this skin's Graphics object.
     *
     *  <p>The rectangle can have rounded corners.
     *  Its edges are stroked with the current line style
     *  of the Graphics object.
     *  It can have a solid color fill, a gradient fill, or no fill.
     *  A solid fill can have an alpha transparency.
     *  A gradient fill can be linear or radial. You can specify
     *  up to 15 colors and alpha values at specified points along
     *  the gradient, and you can specify a rotation angle
     *  or transformation matrix for the gradient.
     *  Finally, the rectangle can have a rounded rectangular hole
     *  carved out of it.</p>
     *
     *  <p>This versatile rectangle-drawing routine is used by many skins.
     *  It calls the <code>drawRect()</code> or
     *  <code>drawRoundRect()</code>
     *  methods (in the flash.display.Graphics class) to draw into this
     *  skin's Graphics object.</p>
     *
     *  @param x Horizontal position of upper-left corner
     *  of rectangle within this skin.
     *
     *  @param y Vertical position of upper-left corner
     *  of rectangle within this skin.
     *
     *  @param width Width of rectangle, in pixels.
     *
     *  @param height Height of rectangle, in pixels.
     *
     *  @param cornerRadius Corner radius/radii of rectangle.
     *  Can be <code>null</code>, a Number, or an Object.
     *  If it is <code>null</code>, it specifies that the corners should be square
     *  rather than rounded.
     *  If it is a Number, it specifies the same radius, in pixels,
     *  for all four corners.
     *  If it is an Object, it should have properties named
     *  <code>tl</code>, <code>tr</code>, <code>bl</code>, and
     *  <code>br</code>, whose values are Numbers specifying
     *  the radius, in pixels, for the top left, top right,
     *  bottom left, and bottom right corners.
     *  For example, you can pass a plain Object such as
     *  <code>{ tl: 5, tr: 5, bl: 0, br: 0 }</code>.
     *  The default value is null (square corners).
     *
     *  @param color The RGB color(s) for the fill.
     *  Can be <code>null</code>, a uint, or an Array.
     *  If it is <code>null</code>, the rectangle not filled.
     *  If it is a uint, it specifies an RGB fill color.
     *  For example, pass <code>0xFF0000</code> to fill with red.
     *  If it is an Array, it should contain uints
     *  specifying the gradient colors.
     *  For example, pass <code>[ 0xFF0000, 0xFFFF00, 0x0000FF ]</code>
     *  to fill with a red-to-yellow-to-blue gradient.
     *  You can specify up to 15 colors in the gradient.
     *  The default value is null (no fill).
     *
     *  @param alpha Alpha value(s) for the fill.
     *  Can be null, a Number, or an Array.
     *  This argument is ignored if <code>color</code> is null.
     *  If <code>color</code> is a uint specifying an RGB fill color,
     *  then <code>alpha</code> should be a Number specifying
     *  the transparency of the fill, where 0.0 is completely transparent
     *  and 1.0 is completely opaque.
     *  You can also pass null instead of 1.0 in this case
     *  to specify complete opaqueness.
     *  If <code>color</code> is an Array specifying gradient colors,
     *  then <code>alpha</code> should be an Array of Numbers, of the
     *  same length, that specifies the corresponding alpha values
     *  for the gradient.
     *  In this case, the default value is <code>null</code> (completely opaque).
     *
     *  @param gradientMatrix Matrix object used for the gradient fill. 
     *  The utility methods <code>horizontalGradientMatrix()</code>, 
     *  <code>verticalGradientMatrix()</code>, and
     *  <code>rotatedGradientMatrix()</code> can be used to create the value for 
     *  this parameter.
     *
     *  @param gradientType Type of gradient fill. The possible values are
     *  <code>GradientType.LINEAR</code> or <code>GradientType.RADIAL</code>.
     *  (The GradientType class is in the package flash.display.)
     *
     *  @param gradientRatios (optional default [0,255])
     *  Specifies the distribution of colors. The number of entries must match
     *  the number of colors defined in the <code>color</code> parameter.
     *  Each value defines the percentage of the width where the color is 
     *  sampled at 100%. The value 0 represents the left-hand position in 
     *  the gradient box, and 255 represents the right-hand position in the 
     *  gradient box. 
     *
     *  @param hole (optional) A rounded rectangular hole
     *  that should be carved out of the middle
     *  of the otherwise solid rounded rectangle
     *  { x: #, y: #, w: #, h: #, r: # or { br: #, bl: #, tl: #, tr: # } }
     *
     *  @see flash.display.Graphics#beginGradientFill()
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    protected function drawRoundRect(
                            x:Number, y:Number, width:Number, height:Number,
                            cornerRadius:Object = null,
                            color:Object = null,
                            alpha:Object = null,
                            gradientMatrix:Matrix = null,
                            gradientType:String = "linear",
                            gradientRatios:Array /* of Number */ = null,
                            hole:Object = null):void
    {
        var g:Graphics = graphics;

        // Quick exit if weight or height is zero.
        // This happens when scaling a component to a very small value,
        // which then gets rounded to 0.
        if (width == 0 || height == 0)
            return;

        // If color is an object then allow for complex fills.
        if (color !== null)
        {
            if (color is uint)
            {
                g.beginFill(uint(color), Number(alpha));
            }
            else if (color is Array)
            {
                var alphas:Array = alpha is Array ?
                                   alpha as Array :
                                   [ alpha, alpha ];

                if (!gradientRatios)
                    gradientRatios = [ 0, 0xFF ];

                g.beginGradientFill(gradientType,
                                    color as Array, alphas,
                                    gradientRatios, gradientMatrix);
            }
        }

        var ellipseSize:Number;

        // Stroke the rectangle.
        if (!cornerRadius)
        {
            g.drawRect(x, y, width, height);
        }
        else if (cornerRadius is Number)
        {
            ellipseSize = Number(cornerRadius) * 2;
            g.drawRoundRect(x, y, width, height, 
                            ellipseSize, ellipseSize);
        }
        else
        {
            GraphicsUtil.drawRoundRectComplex(g,
                                   x, y, width, height,
                                   cornerRadius.tl, cornerRadius.tr,
                                   cornerRadius.bl, cornerRadius.br);
        }

        // Carve a rectangular hole out of the middle of the rounded rect.
        if (hole)
        {
            var holeR:Object = hole.r;
            if (holeR is Number)
            {
                ellipseSize = Number(holeR) * 2;
                g.drawRoundRect(hole.x, hole.y, hole.w, hole.h, 
                                ellipseSize, ellipseSize);
            }
            else
            {
                GraphicsUtil.drawRoundRectComplex(g,
                                       hole.x, hole.y, hole.w, hole.h,
                                       holeR.tl, holeR.tr, holeR.bl, holeR.br);
            }   
        }

        if (color !== null)
            g.endFill();
    }       
}
于 2010-02-08T03:08:52.953 回答
0

好的,我想要的可以像在半透明层上调用两次drawRect一样简单......一次绘制半透明矩形,再次绘制“洞”

详情在这里: http ://www.actionscript.org/forums/showthread.php3?p=965632

不完全是面具,但足以满足我的目的。

于 2010-02-04T00:12:52.870 回答