2013-11-26 11 views
10

Ich versuche, eine kreisförmige Maske in einem Sprite Kit-Projekt zu erstellen. Ich schaffe der Kreis wie folgt aus (es in der Mitte des Bildschirms zu positionieren):Kann man im Sprite Kit einen Kreis (SKShapeNode) als Maske verwenden?

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"; 

und den Code weiter unten, habe ich es als Maske für die cropNode:

[cropNode setMaskNode:circleMask]; 

... Aber anstatt dass der Inhalt in einem Kreis angezeigt wird, erscheint die Maske als Quadrat.

Ist es möglich, eine SKShapeNode als Maske zu verwenden, oder muss ich ein Bild verwenden?

Antwort

12

Nach viel Fluchen, das Web und Experimente in Xcode, habe ich eine wirklich hacky Reparatur.

Denken Sie daran, dass dies ein wirklich hässlicher Hack ist - aber Sie können das auf Sprite Kits Umsetzung von SKShapeNode beschuldigen. Hinzufügen einer Füllung auf einem Pfad bewirkt, dass der folgende:

  • fügt einen zusätzlichen Knoten in die Szene
  • der Pfad wird unmaskierbaren - es erscheint ‚über‘ die Maske
  • macht jede nicht SKSpriteNode Geschwisterknoten unmaskierbaren (zB SKLabelNode s)

Kein Idealzustand.

Inspiriert von Tony Chamblee's progress timer, die ‚fix‘ ist mit der Füllung ganz zu verzichten, und verwenden Sie nur den Hub des Weges:

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]; 

Wie kommentiert, müssen Sie den Radius auf die Hälfte von dem, was Sie einstellen würde normalerweise haben, und die Linienbreite, um den Radius zu verdoppeln.

Hoffentlich wird Apple in Zukunft darauf schauen; Für den Moment ist dieser Hack die beste Lösung, die ich gefunden habe (abgesehen von der Verwendung eines Bildes, das nicht wirklich funktioniert, wenn Ihre Maske dynamisch sein muss).

5

Ja, es ist unmöglich, in der aktuellen Sprite-Kit-Realisierung fill-colored shapenode zu verwenden. Es ist ein Fehler, denke ich.

Aber!

Sie können immer die Form zur Textur rendern und sie als Maske verwenden!

Für Beispiel, lassen Sie Rand ist SKShapeNode zuvor erstellt.

Zuerst macht es vor Textur Ansicht Zugabe (in diesem Fall von einem anderen Knoten reinigen wird)

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

Zweitens

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]; 
+0

Und jetzt einige Dinge sind möglich. (iOS 8.1): int deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (deviceOSVersion> = 8.0) treeS.fillTexture = [SKTexture textureWithImage: [UIImage imageNamed: @ "treeS"]]; – djdance

0

zu alpha von Masken Knoten einstellen.0 funktioniert der Trick:

circleMask.alpha = .0; 

EDIT: Scheint nur für Mac OS zu arbeiten.

5

Da ich keinen SKShapeNode als Maske habe ich beschlossen, es zu einem SKSpriteNode umwandeln kann.

Hier ist es meine Swift Code:

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 

Und es funktioniert :)

+0

Es sieht so aus, als müssten Sie der Szene einen unbenutzten Formknoten hinzufügen. Ich schlage vor, dass Sie einen 'UIImage' aus einem' CGPath' oder einem 'UIBezierPath' erstellen. Sie können dann eine Textur aus dem Bild generieren. – 0x141E

+0

Hi 0x141E, eigentlich füge ich der Szene nicht *** shape *** (den SKShapeNode) hinzu. Der einzige Knoten, der gespeichert wird, ist *** sprite ***. –

+2

Dies ist eine viel bessere Lösung als die akzeptierte – 0x141E

1

Es ist eine etwas ungeschickte Lösung für dieses Problem, das ich glaube, ist etwas weniger böse als eine der Diskussion gestellt Hacks um dieses Problem. Wickeln Sie Ihren SKShapeNode einfach in einen SKNode. Ich habe nicht getestet, welche Art von Performance-Hit dies verursachen könnte, aber da SKNode kein Zeichnen ist, hoffe ich, dass es nicht zu wichtig ist.

heißt

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)