每次我用谷歌搜索这个问题时,我都会看到关于面具和混合物的令人困惑的信息,这些信息似乎都没有直接适用于我认为应该是一件容易的事情......
这里涉及三个精灵……最低层的精灵几乎是一个背景。我想在背景上覆盖一个半透明的 Sprite,然后我想让第三个,最上面的 Sprite 作为一个洞,这样第三个 Sprite 内部的区域是完全透明的,这样背景 Sprite 就完全可见了。
我将如何动态地执行此操作(即使用 Actionscript 图形调用动态绘制掩蔽精灵和孔)?
每次我用谷歌搜索这个问题时,我都会看到关于面具和混合物的令人困惑的信息,这些信息似乎都没有直接适用于我认为应该是一件容易的事情......
这里涉及三个精灵……最低层的精灵几乎是一个背景。我想在背景上覆盖一个半透明的 Sprite,然后我想让第三个,最上面的 Sprite 作为一个洞,这样第三个 Sprite 内部的区域是完全透明的,这样背景 Sprite 就完全可见了。
我将如何动态地执行此操作(即使用 Actionscript 图形调用动态绘制掩蔽精灵和孔)?
我知道这已经是很久以前的事了,但仅适用于可能寻找相同问题的人。这实际上很容易(只要用图形类绘制你的 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,否则将不起作用。
我希望这可以帮助某人
如果我没记错的话,如果你在同一个图形上绘制两个重叠的对象而不停止填充,它们的工作原理很像 blendmode.erase。伪代码如下所示:
graphics.beginFill (any color, any alpha);
graphics.drawRect(0,0,256, 256);
graphics.drawRect(128,128,64, 64);
graphics.endfill ();
如果这确实有效(我想我多年前使用过这个解决方案,并且最近才看到 SVG 文件以这种方式工作),这应该会给您带来更好的性能。
编辑:我刚刚在我的一个游戏中使用了这个。
如果有人需要渐变孔,可以使用 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();
椭圆将完全匹配孔,像素完美。
不是 AS 开发人员,但看看这个:http ://code.google.com/p/gpcas/
这应该使您能够对两个多边形进行布尔“剪切”操作。
看看这个方法,它允许一个可选的“hole”参数。这可以在 flex 框架的 ProgrammaticSkin 类中找到。
/**
* 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();
}
}
好的,我想要的可以像在半透明层上调用两次drawRect一样简单......一次绘制半透明矩形,再次绘制“洞”
详情在这里: http ://www.actionscript.org/forums/showthread.php3?p=965632
不完全是面具,但足以满足我的目的。