Можно ли использовать круг (SKShapeNode) в качестве маски в Sprite Kit?
Я пытаюсь создать круговую маску в проекте 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];
[email protected]"circleMask";
и далее вниз код, я установил его как маску для cropNode
:
[cropNode setMaskNode:circleMask];
... но вместо содержимого, отображаемого внутри круга, маска отображается как квадрат.
Можно ли использовать SKShapeNode
в качестве маски, или мне нужно использовать изображение?
Ответы
Ответ 1
После долгих ругательств, чистки веб-страниц и экспериментов в Xcode у меня есть действительно хакерское исправление.
Имейте в виду, что это действительно неприятный взлом, но вы можете обвинить его в реализации Sprite Kit SKShapeNode
. Добавление заливки в путь вызывает следующее:
- добавляет дополнительный node к вашей сцене
- путь становится немасштабируемым - он отображается над маской
- делает невозможным доступ к нескольким узлам не-t21 > (например,
SKLabelNode
s)
Не идеальное положение дел.
Вдохновленный Тоном прогресса Tony Chamblee, 'fix' состоит в том, чтобы обойтись без заполнения и просто использовать ход пути:
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];
[email protected]"circleMask";
[cropNode setMaskNode:circleMask];
Как прокомментировано, вам нужно установить радиус на половину того, что вы обычно имели, и ширину линии, чтобы удвоить радиус.
Надеюсь, Apple будет смотреть на это в будущем; на данный момент этот хак - лучшее решение, которое я нашел (кроме использования изображения, которое на самом деле не работает, если ваша маска должна быть динамичной).
Ответ 2
Да, в текущей реализации Sprite-Kit невозможно использовать полноцветный шейенид. Думаю, это ошибка.
Но!
Вы всегда можете сделать фигуру текстурой и использовать ее как маску!
Для примера, пусть 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];
Ответ 3
Поскольку я не могу использовать 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
И он работает:)
Ответ 4
Есть немного неудобное решение этой проблемы, которое, по моему мнению, немного менее противное, чем любой из обсуждаемых хаков по этой проблеме. Просто оберните 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)
Ответ 5
Настройка альфы маски node на .0 делает трюк:
circleMask.alpha = .0;
EDIT:
Кажется, работает только для Mac OS.