是否可以在Sprite Kit中使用圆圈(SKShapeNode)作为遮罩?

时间:2013-11-26 22:05:29

标签: objective-c iphone ios7 sprite-kit skcropnode

我试图在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作为遮罩,还是需要使用图像?

5 个答案:

答案 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。