11

我正在尝试在 Sprite Kit 项目中创建一个圆形蒙版。我创建这样的圆圈(将其定位在屏幕的中心):

SKCropNode *cropNode = [[SKCropNode alloc] init];

SKShapeNode *circleMask = [[SKShapeNode alloc ]init];
CGMutablePathRef circle = CGPathCreateMutable();
CGPathAddArc(circle, NULL, CGRectGetMidX(self.frame), CGRectGetMidY(self.frame), 50, 0, M_PI*2, YES);
circleMask.path = circle;
circleMask.lineWidth = 0;
circleMask.fillColor = [SKColor blueColor];
circleMask.name=@"circleMask";

并进一步向下代码,我将其设置为掩码cropNode

[cropNode setMaskNode:circleMask];

...但不是显示在圆圈内的内容,而是掩码显示为正方形。

是否可以使用 aSKShapeNode作为蒙版,还是我需要使用图像?

4

5 回答 5

13

经过大量的咒骂,搜索网络和 Xcode 的实验,我有一个非常 hacky 的修复。

请记住,这是一个非常讨厌的 hack - 但您可以将其归咎于 Sprite Kit 的SKShapeNode. 向路径添加填充会导致以下情况:

  • 为您的场景添加一个额外的节点
  • 路径变得不可遮蔽 - 它出现在遮罩“上方”
  • 使任何非SKSpriteNode兄弟节点不可屏蔽(例如SKLabelNodes)

不是理想的事态。

Tony Chamblee 的进度计时器启发,“修复”是完全省去填充,只使用路径的笔划:

SKCropNode *cropNode = [[SKCropNode alloc] init];

SKShapeNode *circleMask = [[SKShapeNode alloc ]init];
CGMutablePathRef circle = CGPathCreateMutable();
CGPathAddArc(circle, NULL, CGRectGetMidX(self.frame), CGRectGetMidY(self.frame), 50, 0, M_PI*2, YES); // replace 50 with HALF the desired radius of the circle
circleMask.path = circle;
circleMask.lineWidth = 100; // replace 100 with DOUBLE the desired radius of the circle
circleMask.strokeColor = [SKColor whiteColor];
circleMask.name=@"circleMask";

[cropNode setMaskNode:circleMask];

如评论所述,您需要将半径设置为通常的一半,并将线宽设置为半径的两倍。

希望苹果将来会考虑这一点;目前,这个 hack 是我找到的最好的解决方案(除了使用图像,如果你的面具需要是动态的,这实际上不起作用)。

于 2013-12-05T08:28:31.603 回答
5

是的,在当前的 Sprite-Kit 实现中不可能使用填充颜色的 shapenode。我认为这是一个错误。

但!

您始终可以将形状渲染为纹理并将其用作蒙版!

例如,let edge是之前创建的 SKShapeNode。

首先,在添加到视图之前将其渲染到纹理(在这种情况下,它将从另一个节点中清除)

SKTexture *Mask = [self.view textureFromNode:edge];
[self addChild:edge]; //if you need physics borders

第二,

SKCropNode *cropNode = [[SKCropNode alloc] init];
[cropNode setMaskNode:[SKSpriteNode spriteNodeWithTexture:Mask]];
[cropNode addChild: [SKSpriteNode spriteNodeWithTexture:rocksTiles size:CGSizeMake(w,h)]];
cropNode.position = CGPointMake(Mask.size.width/2,Mask.size.height/2);
//note, anchorpoint of shape in 0,0, but rendered texture is in 0.5,0.5, so we need to dispose it
[self addChild:cropNode];
于 2014-02-11T16:58:04.510 回答
5

由于我不能使用SKShapeNode作为掩码,我决定将其转换为SKSpriteNode

这是我的 Swift 代码:

let shape : SKShapeNode = ... // create your SKShapeNode
var view : SKView = ... // you can get this from GameViewController

let texture = view.textureFromNode(shape)
let sprite = SKSpriteNode(texture: texture)
sprite.position = ...

cropNode.mask = sprite

它确实有效:)

于 2014-12-27T13:49:42.440 回答
1

这个问题有一个稍微尴尬的解决方案,我认为它比围绕这个问题的任何有争议的黑客攻击都要少一些。只需将您的 SKShapeNode 包装在 SKNode 中。我还没有测试这可能会导致什么样的性能影响,但鉴于 SKNode 是非绘图的,我希望它不会太显着。

IE

let background = SKSpriteNode(imageNamed: "Background")
let maskNode = SKShapeNode(path: MyPath)
let wrapperNode = SKNode()
let cropNode = SKCropNode()

wrapperNode.addChild(maskNode)
cropNode.maskNode = wrapperNode
cropNode.addChild(background)
于 2017-06-05T10:07:57.433 回答
0

将掩码节点的 alpha 设置为 .0 可以解决问题:

circleMask.alpha = .0;

编辑:似乎只适用于 Mac OS。

于 2014-04-18T20:54:51.270 回答