2014-12-31 7 views
7

Sto ancora giocando con l'apprendimento di SpriteKit in iOS & ho fatto un sacco di letture di & lotti di sperimentazione. Sono confuso da qualcos'altro che ho trovato * per quanto riguarda le coordinate, i frame dei nodi &.Confusione su coordinate, frame e nodi figlio in SpriteKit su iOS?

Si consideri questo frammento di codice, in cui sto cercando di disegnare una casella verde intorno alla mia nave spaziale sprite a scopo di debug:

func addSpaceship() 
{ 
    let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") 
    spaceship.name = "spaceship" 

    // VERSION 1 
    spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) 

    let debugFrame = SKShapeNode(rect: spaceship.frame) 

    debugFrame.strokeColor = SKColor.greenColor() 
    spaceship.addChild(debugFrame) 

    // VERSION 2 
    //  spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) 

    spaceship.setScale(0.50) 


    self.addChild(spaceship) 
} 

Se aggiungo il set lo sprite nave spaziale con la linea marcata "VERSIONE 1" di cui sopra, ottengo questo:

Version 1

che è chiaramente sbagliata. Ma se io commento fuori la linea marcata "VERSIONE 1" di cui sopra, e di utilizzare invece la linea marcata "VERSIONE 2", ottengo ciò che voglio:

Version 2

Si noti che il codice vero e proprio per le linee marcato Versione 1 & Versione 2 è identico: spaceship.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMidY (self.frame))

Allora perché è importante quando ho impostato la posizione dello sprite astronave?

A mio modo di pensare, la posizione dello sprite navicella spaziale è irrilevante per il posizionamento del del debugFrame, perché il debugFrame è un figlio della nave spaziale sprite & quindi, è coordinate dovrebbero essere relativo al telaio del sprite astronave - destra?

Grazie WM

* Questo è in qualche modo legati ad una domanda ho chiesto ieri:

In SpriteKit on iOS, scaling a textured sprite produces an incorrect frame?

ma a) capisco che uno ora, e b) si tratta di una sufficiente che diverso merita la sua stessa domanda.

UPDATE:

Hmmm - grazie, ragazzi per le idee di seguito, ma io ancora non capisco & forse questo sarà di aiuto.

ho modificato il mio codice per stampare le posizioni relavant & cornici:

func addSpaceship() 
{ 
    let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") 
    spaceship.name = "spaceship" 
    println("Spaceship0 Pos \(spaceship.position) Frame = \(spaceship.frame)") 

    // VERSION 1 (WRONG) 
    spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) 
    println("Spaceship1 Pos \(spaceship.position) Frame = \(spaceship.frame)") 

    let debugFrame = SKShapeNode(rect: spaceship.frame) 
    println("DEBUG Pos \(debugFrame.position) Frame = \(debugFrame.frame)") 

    debugFrame.strokeColor = SKColor.greenColor() 
    spaceship.addChild(debugFrame) 

    // VERSION 2 (RIGHT) 
//  spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) 
//  println("Spaceship2 Pos \(spaceship.position) Frame = \(spaceship.frame)") 

    spaceship.setScale(0.50) 


    self.addChild(spaceship) 
} 

Poi, mi sono imbattuto in entrambi i modi hanno ottenuto questi risultati. Dal momento che capisco la versione 2, iniziamo da lì.

Correndo con la "versione 2 (DESTRA)" Codice, ho ottenuto:

Spaceship0 Pos (0.0,0.0) Frame = (-159.0,-300.0,318.0,600.0) 
DEBUG Pos (0.0,0.0) Frame = (-159.5,-300.5,319.0,601.0) 
Spaceship2 Pos (384.0,512.0) Frame = (225.0,212.0,318.0,600.0) 

Il nodo astronave inizia, per impostazione predefinita, con la sua posizione in basso a sinistra dello schermo (Spaceship0). La sua cornice è espressa anche in termini di punto di ancoraggio (centro) impostato nella parte inferiore sinistra dello schermo, quindi i numeri negativi per l'origine del suo frame rect.

Il frame di debug viene quindi creato con la sua posizione impostata su 0, 0 per impostazione predefinita & il frame impostato per essere uguale a quello dell'astronave.

Il codice (Spaceship2) sposta il nodo della navicella spaziale in una posizione nelle coordinate della vista (384.0,512.0) e l'origine della sua cornice viene spostata aggiungendo la nuova posizione all'origine precedente (vale a dire 384 + -159 = 225).

Tutto va bene.

Purtroppo, ancora non capisco Versione 1.

Quando eseguo con la "versione 1 (sbagliato)," Codice, ottengo

Spaceship0 Pos (0.0,0.0) Frame = (-159.0,-300.0,318.0,600.0) 
Spaceship1 Pos (384.0,512.0) Frame = (225.0,212.0,318.0,600.0) 
DEBUG Pos (0.0,0.0) Frame = (0.0,0.0,543.5,812.5) 

Come sopra, inizia nodo spaziale , per impostazione predefinita, con la sua posizione in basso a sinistra dello schermo (Spaceship0). La sua cornice è espressa anche in termini di punto di ancoraggio (centro) impostato nella parte inferiore sinistra dello schermo, quindi i numeri negativi per l'origine del suo frame rect.

Il codice (Spaceship1) sposta il nodo della navicella spaziale in una posizione nelle coordinate della vista (384.0,512.0) e l'origine della sua cornice viene spostata aggiungendo la nuova posizione all'origine precedente (ad).

Il frame di debug viene quindi creato con la sua posizione impostata su 0, 0 per impostazione predefinita & il suo frame impostato per avere una larghezza strana (543,5) & un'altezza strana (812,5). Dato che sto inizializzando il debugFrame.frame con spaceship.frame (i penso che sia che è quello che fa l'inizializzatore di default), mi aspetterei che il nuovo debugFrame.frame sia lo stesso del frame dell'astronave - ma non lo è! I valori di altezza del riquadro di debug & apparentemente provengono dall'aggiunta della larghezza effettiva & all'altezza del frame del nodo dell'astronave (543,5 = 225 + 318,5). Ma se questo è il caso, perché l'origine del frame è ancora 0, 0 & non la stessa aggiunta (225.0 + 0 = 225.0) ???

Non capisco.

+1

registro spaceship.frame, si noterà la sua origine dipende dalla posizione. poiché la forma è un figlio dell'astronave, la posizione della forma è relativa ad essa. Quindi se frame.origin è 0,0 tutto va bene, ma se è 200.200 la forma sarà compensata di conseguenza. – LearnCocos2D

+0

Grazie mille - ma temo di non averlo ancora capito. Vedi il mio aggiornamento sopra. – WonderMonster

risposta

7

Si sta creando il nodo forma utilizzando la cornice dello sprite, che è in coordinate di scena. Poiché la forma sarà figlia dello sprite, dovresti creare il nodo nelle coordinate dello sprite. Ad esempio, se si crea la SKShapeNode per dimensione spaziale

let debugFrame = SKShapeNode(rectOfSize: spaceship.size) 

invece di utilizzare la cornice della nave spaziale, debugFrame sarà centrato sulla nave spaziale indipendentemente da quando si imposta la posizione della nave. Inoltre, debugFrame verrà ridimensionato/spostato in modo appropriato con la nave.

+0

Questo è quello che ho spiegato: non usare il frame che contiene una posizione ... –

0

Questo è quasi lo stesso problema che nell'altra domanda che hai citato. frame è una proprietà che contiene position e size. Entrambi sono soggetti al ridimensionamento del loro nodo antenato. Leggi la sezione "Un nodo applica molte delle sue proprietà ai suoi discendenti" in https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Nodes/Nodes.html#//apple_ref/doc/uid/TP40013043-CH3-SW13

Ancora: non applicare mai il ridimensionamento a un nodo, non spostare mai un nodo prima di aver costruito completamente la sua gerarchia, tranne se si desidera un effetto speciale o strano.

+0

Ma non eseguo il ridimensionamento fino a quando non ho completamente costruito la mia gerarchia di nodi in entrambi i casi. L'unica cosa che ho fatto è spostata dove ho impostato la posizione dei genitori? – WonderMonster

+0

Giusto, ho fatto un errore. Ma il tuo problema è lo stesso di prima: supponi che X, Y siano la posizione iniziale della tua astronave (normalmente 0,0 Penso), nella versione 1 ti sposti quindi su X = S/2, Y = S/2. Quindi crei un debugframe in posizione S/2, S/2 e riduci l'intero, ma il ridimensionamento non scala la posizione del nodo ma ridimensiona le posizioni dei suoi discendenti, quindi il tuo debugframe si trova nella posizione S/4, S/4 (relativamente all'astronave). Nella versione 2, il debugframe viene avviato a 0,0, quando si sposta l'astronave si sposta su S/2, S/2 e il frame di debug è a 0,0 relativamente all'astronave. –

+0

Grazie mille - ma temo di non averlo ancora capito. Vedi il mio aggiornamento sopra. – WonderMonster

1

In risposta al tuo "Io non capisco". Il tuo codice è ok ma ha un problema logico. Il 'frame' viene contato rispetto alle coordinate padre.Ti preghiamo di capire che il genitore dell'astronave e il genitore della finestra di debug sono diversi nel tuo codice.

due modi per risolvere il problema:

  1. Aggiungi uno zero offset per la finestra di debug e utilizzare l'astronave come il genitore. Il vantaggio di questo è che la finestra di debug si muoverà, scala con la nave spaziale: let rectDebug = CGRectMake(0, 0, spaceship.frame.size.width, spaceship.frame.size.height) let debugFrame = SKShapeNode(rect:rectDebug) spaceship.addChild(debugFrame)
  2. Aggiungere la finestra di debug con 'frame' l'astronave coordina al genitore della nave spaziale (che è 'auto'). Lo svantaggio di questo, è che si deve spostare, ridimensionare la finestra di debug da soli nel codice, dal momento che non sarà collegato alla navicella spaziale .: let debugFrame = SKShapeNode(rect:spaceship.frame) self.addChild(debugFrame)

Entrambe le soluzioni sono ampiamente utilizzati. Dovresti scegliere quello che è meglio per te nel tuo caso. Altri tre problemi potrebbero sorgere:

1.Ci sono errori di codice nel mio codice, ho semplicemente inserito questi direttamente nella finestra Web senza il controllo della sintassi xcode.

2. I punti di ancoraggio dei due oggetti potrebbero essere diversi. Quindi potresti aver bisogno di un allineamento nel tuo codice per questo.

3. La posizione z degli oggetti deve essere presa in considerazione, in modo che questi oggetti non vengano nascosti sotto altri oggetti.

In risposta al problema che si sta tentando di risolvere, forse showPhysics aiuterebbe:

skView.showsFPS = YES; 
    skView.showsNodeCount = YES; 
    skView.showsPhysics = YES;