2013-11-26 11 views
10

Sto provando a creare una maschera circolare in un progetto Sprite Kit. Creo il cerchio simili (posizionandolo al centro dello schermo):È possibile utilizzare un cerchio (SKShapeNode) come maschera in 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"; 

e più in basso il codice, ho impostato come maschera per la cropNode:

[cropNode setMaskNode:circleMask]; 

... ma invece del contenuto che mostra all'interno di un cerchio, la maschera appare come un quadrato.

È possibile utilizzare uno SKShapeNode come maschera o è necessario utilizzare un'immagine?

risposta

12

Dopo aver giurato molto, perlustrando il Web e sperimentato in Xcode, ho una soluzione davvero incisiva.

Tenete a mente che questo è un hack davvero brutto - ma si può dare la colpa che sull'attuazione di Sprite Kit di SKShapeNode. Aggiunta di un riempimento a un percorso provoca il seguente:

  • aggiunge un nodo in più per la vostra scena
  • il percorso diventa non mascherabile - sembra 'sopra' la maschera
  • fa alcuna non SKSpriteNode fratello nodi non mascherabile (es. SKLabelNode s)

Non uno stato ideale di cose.

Ispirato Tony Chamblee's progress timer, la 'correzione' è di fare a meno del riempimento del tutto, e basta usare la corsa del percorso:

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

Come commentato, è necessario impostare la distanza per la metà di quello che si normalmente e la larghezza della linea per raddoppiare il raggio.

Speriamo che Apple guardi a questo in futuro; per ora, questo hack è la soluzione migliore che ho trovato (oltre all'uso di un'immagine, che non funziona se la tua maschera deve essere dinamica).

5

Sì, è impossibile utilizzare lo shapenode di colore riempimento nella realizzazione corrente di Sprite-Kit. È un insetto, penso.

Ma!

È sempre possibile rendere la forma da tessere e usarla come maschera!

Ad esempio, lasciare il prefisso prima creato da SKShapeNode.

primo luogo, rendono a trama prima aggiunta alla visualizzazione (in questo caso pulirà da altri nodi)

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

secondo luogo,

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

Ed ora alcune cose sono possibili. (iOS 8.1): int deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (deviceOSVersion> = 8.0) treeS.fillTexture = [SKTexture textureWithImage: [UIImage imageNamed: @ "treeS"]]; – djdance

0

Impostazione alfa del nodo maschera.0 fa il trucco:

circleMask.alpha = .0; 

EDIT: sembra funzionare solo per Mac OS.

5

Dal momento che non è possibile utilizzare un SKShapeNode come maschera ho deciso di convertirlo in un SKSpriteNode.

Qui è il mio codice 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 

E funziona :)

+0

Sembra che sarà necessario aggiungere un nodo di forma non utilizzato alla scena. Vi suggerisco di guardare a creare una 'UIImmagine' da un' CGPath' o un 'UIBezierPath'. È quindi possibile generare una trama dall'immagine. – 0x141E

+0

Ciao 0x141E, in realtà non sto aggiungendo *** forma *** (il SKShapeNode) alla scena. L'unico nodo che verrà salvato è *** sprite ***. –

+2

Questa è una soluzione molto migliore rispetto a quella accettata – 0x141E

1

C'è una soluzione un po 'scomodo a questo problema che credo sia un po' meno brutto di tutti gli hack mooted intorno a questo problema. Basta avvolgere il tuo SKShapeNode in un SKNode. Non ho ancora testato il tipo di prestazioni che questo potrebbe causare, ma dato che SKNode è non-disegno, spero che non sia troppo significativo.

cioè

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) 
Problemi correlati