我试图在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];
...但是,除了显示在圆圈内的内容外,面具显示为正方形。
是否可以使用SKShapeNode
作为遮罩,还是需要使用图像?
答案 0 :(得分:12)
经过多次咒骂,搜索网页以及在Xcode中进行实验,我有一个非常糟糕的修复方法。
请记住,这是一个非常讨厌的黑客 - 但你可以责怪Sprite Kit的SKShapeNode
实现。将填充添加到路径会导致以下结果:
SKSpriteNode
兄弟节点无法屏蔽(例如SKLabelNode
s)不是理想的事态。
受Tony Chamblee's progress timer的启发,'修复'是完全免除填充,只需使用路径的笔划:
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];
如评论所示,您需要将半径设置为通常的半径,并将线宽设置为半径的两倍。
希望Apple将来会考虑这个问题;现在,这个hack是我发现的最好的解决方案(除了使用图像,如果你的面具需要是动态的,它就不会真正起作用)。
答案 1 :(得分:5)
是的,在当前的Sprite-Kit实现中不可能使用填充色的shapenode。我想这是一个错误。
但是!
您始终可以将形状渲染为纹理并将其用作蒙版!
对于ex,让 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];
答案 2 :(得分: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
它确实有效:)
答案 3 :(得分:1)
对于这个问题,有一个稍微尴尬的解决方案,我认为这个问题比任何关于这个问题的骚扰都要少一些。只需将SKShapeNode包装在SKNode中即可。我没有测试过这可能造成什么样的性能损失,但考虑到SKNode是非绘图的,我希望它不会太重要。
即
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)
答案 4 :(得分:0)
将掩码节点的alpha设置为.0可以解决问题:
circleMask.alpha = .0;
编辑: 似乎只适用于Mac OS。