2015-03-22 26 views
6

GUI elements example imageVincolare le proporzioni degli elementi GUI in Spritekit gioco

Mi scuso in anticipo a causa della enorme post, ma tutti coloro che mai provato a fare un qualche tipo di applicazione universale, sa che questa è roba abbastanza problematico, quindi per favore non affaticare me ...

L'obiettivo

Quello che sto cercando di realizzare (indicato sul immagine qui sopra) è quello di utilizzare @ 2x attivi sia su iPhone 5 e 6, e mantenere lo stesso aspetto di un app. E se possibile, fare tutto ciò senza calcolare manualmente le proprietà di scala e posizione dei nodi in base al dispositivo rilevato ... In breve, in che modo ottenere quell'app automaticamente vincola le proporzioni e tra gli elementi (e la scena)? Inoltre mi piacerebbe avere lo stesso aspetto di un'app su iPhone 6+ usando le risorse @ 3x, ma per semplicità mi sono concentrato solo su iPhone 5 e 6.

Quello che ho trovato sul web è che alcune persone dicendo che questo (downsampling) viene fatto automaticamente dal iOS, ad esempio, essi suggeriscono questo:

"Make @ attivi 2x le dimensioni per iPhone 6, e poi iOS farà downscaling automaticamente per iPhone 5".

Ma ovviamente non è vero quando si parla di scena di Spritekit o mi manca qualcosa.

Il problema

Anche se iPhone 6 e iPhone 5 hanno lo stesso rapporto di aspetto e lo stesso PPI, utilizzando la stessa attività non guardare la stessa rispetto alla dimensione scena (menu sguardo sprite il 1 ° e 2 ° immagine rispetto alla dimensione della scena) perché i PPI sono legati alla densità dei pixel, e iPhone 6 ha più spazio (diagonale più grande, più pollici), il che significa che ha più pixel di iPhone 5. E questo è da dove proviene il mio problema e io non so quale sarebbe un modo efficace per gestirlo.

Quello che ho fatto finora

La seconda immagine non è un problema per la GUI, ma per un gioco, nel mio caso lo è, perché voglio stesso aspetto su dispositivi diversi. Guarda solo la prima e la terza immagine.

Grazie a Skyler Lauren's suggerimento Sono riuscito ad avere lo stesso aspetto di un app in tutti iPhone 5 dispositivi sia su 7.1 o 8.1 sistemi, nonché su iPhone 6. Così ora, il problema è come adattare questo codice per funziona con iPhone 6+ utilizzando trame @ 3x e iPhone 4s. Ecco la soluzione per iPhone 5 e 6:

Vista controller.m

GameScene *scene = [GameScene sceneWithSize:CGSizeMake(375,677)];//fixed instead of view.bounds.size 
scene.scaleMode = SKSceneScaleModeAspectFill; 

dimensione Così la scena sempre è fissato a iPhone 6 dimensioni e taglie cambia secondo dispositivo. Sto usando il catalogo delle risorse per le immagini di avvio e non il file xib. Le immagini sono ridotte alle dimensioni consigliate: 640x960px per 4s, 640x1136px per 5, 750x1334px per 6 e 1242x2208 per il modello 6+. Le risorse sono dimensionate per iPhone 6, quindi per quel modello non esiste alcun ridimensionamento.

Relativo al modello 4s, quando sto usando questo metodo sopra descritto, ci sono due barre nere da ciascun lato ...

Finora l'ho provato solo su simulatore e dispositivo iPhone 6 (quello che vedo è simile alla prima immagine sul dispositivo o sul simulatore).

Domanda

Per ora, come ho detto tutto funziona su iPhone 4s (con due barre nere a causa dei differenti formati), 5, 6 utilizzando @ beni 2x, ma come rendere il tutto per lavorare con iPhone 6 + usando le risorse @ 3x? Se uso 375x667 dimensioni per la scena, allora tutto è posizionato correttamente e ha buone proporzioni, ma la qualità soffre (a causa di upscaling @ 2x)

+0

Hai mai provato a ridimensionare un nodo, in base al dispositivo, quando lo aggiungi per la prima volta? Qualsiasi animazione successiva (modifiche alla trama) porterà il fattore di scala preimpostato. – sangony

+0

Certo, e questo è quello che sto cercando di evitare se possibile, ma questa è certamente una possibilità per gestirlo. Sto solo cercando una soluzione più semplice/automatica che mi consenta di risparmiare molti calcoli/impostare manualmente le proprietà della scala in base al dispositivo, ecc. – Whirlwind

+0

Stai ridimensionando la tua scena o la tua scena e la tua vista hanno dimensioni uguali (io no ridimensionamento). –

risposta

4

GUI uniforme e di gioco

Per quanto posso indica il modo migliore per gestire una GUI uniforme e il gioco è quello di impostare le dimensioni della scena (indipendentemente dal dispositivo) e lasciare che SpriteKit scala da lì.

GameScene *scene = [GameScene sceneWithSize:CGSizeMake(375,677)];//fixed instead of view.bounds.size 
scene.scaleMode = SKSceneScaleModeAspectFill; 

cioè i punti per un iPhone 6. Poiché SpriteKit lavora a punti, ma i dispositivi di visualizzazione in pixel la dimensione scena sarà 750px x 1354px pixel per @ 2x dispositivi e 1125px x 2031px per l'iPhone 6+ (la il dispositivo in pixel è effettivo 1080 x 1920).

Come funziona con le risorse?

Bene, funziona piuttosto bene per le risorse 1x e 2x in una cartella .atlas. Ancora una volta, poiché tutto è convertito in punti, puoi avere button.png e [email protected] in un atlante di texture e il posizionamento sarà lo stesso e avrà lo stesso aspetto per tutti gli iPhone.

Che dire di @ 3x?

Questa è una domanda migliore per Apple. Apparentemente SpriteKit non supporta le immagini @ 3x in un atlante di texture. Ci sono già alcune domande su SO che hanno cercato di risolvere questo problema.

Un esempio ...

Spritekit - not loading @3x images from SKTextureAtlas

Sembra che non è stato risolto in Xcode 6.2 neanche. Se stai leggendo questo e vuoi @ 3x, potrebbe valere la pena archiviare un radar con Apple. Una cosa da notare è che non ho visto da nessuna parte nei documenti affermando che gli atlanti di texture suppongono di supportare @ 3x (o anche @ 2x per quella materia) Quando sono supportati non dovrai apportare alcuna modifica al tuo codice . Basta lanciare le risorse @ 3x nelle tue cartelle .atlas.

Cosa posso/dovrei fare per le risorse @ 3x?

Il mio consiglio è di non preoccuparsi e di eseguire 2x asset. SpriteKit fa un lavoro decente per ridimensionare le immagini e ci sono un sacco di app che non supportano @ 3x. Come proprietario di iPhone 6+, è solo qualcosa con cui ho imparato a convivere al momento. Spero che Apple supporti le immagini @ 3x nella cartella .atlas molto presto.

Avvertenze

Si stanno chiedendo tutti i dispositivi in ​​scala verso il basso con l'eccezione di iPhone 6 (e scaling up iPhone 6+) Nella maggior parte dei casi non si dovrebbe notare una grande differenza nella vostra arte (o prestazioni dai miei test), ma come sai, se riduci le immagini, potrebbero sembrare leggermente diverse. Inoltre c'è il problema della barra nera sui 4 che non ho una soluzione per te al momento.

chiusura Punti

Si otterrà lo stesso esatto aspetto e sentire nella vostra applicazione su tutti i dispositivi se si imposta la dimensione scena e impostare la scena per SKSceneScaleModeAspectFill tuttavia si sta chiedendo dispositivi più vecchi per scalare verso il basso. Risparmia un sacco di tempo e pianifica con piccoli inconvenienti per quanto vedo.

Speriamo che questo aiuti e buona fortuna per la tua app.

+0

Grazie per la risposta Skyler, sì proprio ora sembra che qualcosa non funzioni con il simulatore iPhone 6+ quando si tratta dell'uso di atlanti. La verità è che le differenze non sono così evidenti quando si usano le risorse @ 2x, ma sarebbe meglio se questo fosse corretto perché quando un'immagine di bitmap ad alto dettaglio viene ridimensionata, possono verificarsi artefatti. Ho provato soluzioni da questi link, e molti altri, ma anche quando utilizzo Texturepacker che genera correttamente gli atlanti, o scegliendo l'atlante corretto in base al fattore di scala dello schermo, sembra che al simulatore dell'iPhone 6+ piacciono solo le immagini x2. – Whirlwind

+0

Per evitare artefatti durante il ridimensionamento, ho intenzione di utilizzare il vettore di modulo di generazione di immagini dinamiche. Innanzitutto, creo le immagini usando PaintCode. Quindi il codice corrispondente viene esportato per generare una vista dimensionata in base alle esigenze. Finalmente un file png viene creato da questa vista e poi usato sulle trame. – Domsware

+0

Infatti, l'ultima versione di PaintCode, 2.3.2 porta già la fase di generazione! – Domsware

5

I tuoi problemi principali sembrano gestire le varie dimensioni dello schermo in relazione alle risorse dell'immagine e alle coordinate dell'oggetto schermo.

La mia soluzione è scrivere il codice come se si stesse codificando per l'iPhone 6 plus. Crea tutte le tue immagini sulla dimensione 3x e le coordinate del tuo schermo per le dimensioni dello schermo dell'iPhone 6.

Con solo un po 'di codice sono riuscito a ottenere un layout uniforme per le dimensioni dello schermo dell'iPhone 6 plus, 6, 5 e 4. Ho incluso schermate per ciascuno di essi. L'immagine del personaggio è 300x300. Le immagini dei 2 pulsanti sono 100x100.

static const float kIphone6PlusScaleFactorX = 1.0; 
static const float kIphone6PlusScaleFactorY = 1.0; 
static const float kIphone6ScaleFactorX = 0.9; 
static const float kIphone6ScaleFactorY = 0.9; 
static const float kIphone5ScaleFactorX = 0.772; 
static const float kIphone5ScaleFactorY = 0.772; 
static const float kIphone4ScaleFactorX = 0.772; 
static const float kIphone4ScaleFactorY = 0.652; 

#import "GameScene.h" 

@implementation GameScene { 
    float scaleFactorX; 
    float scaleFactorY; 

    SKSpriteNode *node0; 
    SKSpriteNode *node1; 
    SKSpriteNode *node2; 
    SKLabelNode *label0; 
} 

-(void)didMoveToView:(SKView *)view { 
self.backgroundColor = [SKColor blackColor]; 

    if(view.frame.size.height == 736) { 
     NSLog(@"iPhone 6 plus"); 
     scaleFactorX = kIphone6PlusScaleFactorX; 
     scaleFactorY = kIphone6PlusScaleFactorY; 
    } 
    if(view.frame.size.height == 667) { 
     NSLog(@"iPhone 6"); 
     scaleFactorX = kIphone6ScaleFactorX; 
     scaleFactorY = kIphone6ScaleFactorY; 
    } 
    if(view.frame.size.height == 568) { 
     NSLog(@"iPhone 5"); 
     scaleFactorX = kIphone5ScaleFactorX; 
     scaleFactorY = kIphone5ScaleFactorY; 
    } 
    if(view.frame.size.height == 480) { 
     NSLog(@"iPhone 4"); 
     scaleFactorX = kIphone4ScaleFactorX; 
     scaleFactorY = kIphone4ScaleFactorY; 
    } 

    node0 = [SKSpriteNode spriteNodeWithImageNamed:@"Pic"]; 
    node0.position = CGPointMake(self.size.width/2, self.size.height/2); 
    [node0 setScale:scaleFactorX]; 
    [self addChild:node0]; 

    node1 = [SKSpriteNode spriteNodeWithImageNamed:@"button0"]; 
    node1.position = CGPointMake(100*scaleFactorX, 100*scaleFactorY); 
    [node1 setScale:scaleFactorX]; 
    [self addChild:node1]; 

    node2 = [SKSpriteNode spriteNodeWithImageNamed:@"button1"]; 
    node2.position = CGPointMake(314*scaleFactorX, 100*scaleFactorY); 
    [node2 setScale:scaleFactorX]; 
    [self addChild:node2]; 

    label0 = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue-Bold"]; 
    label0.text = @"Big Game Menu"; 
    label0.fontSize = 48*scaleFactorX; 
    label0.fontColor = [SKColor whiteColor]; 
    label0.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter; 
    label0.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter; 
    label0.position = CGPointMake(207*scaleFactorX,690*scaleFactorY); 
    [self addChild:label0]; 
} 

iPhone 4

enter image description here

iPhone 5

enter image description here

iPhone 6

enter image description here

iPhone 6+

enter image description here

Si noti come anche l'etichetta di testo è stata ridotta in modo corretto, non solo per la dimensione del carattere, ma anche la posizione.

Per riferimento, ho utilizzato il codice standard nel mio GameViewController perché trovo più semplice lavorare con una versione più semplice. Questo è il codice che ho usato per presentare il mio SKView:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    SKView * skView = (SKView *)self.view; 
    SKScene *scene = [GameScene sceneWithSize:skView.bounds.size]; 
    scene.scaleMode = SKSceneScaleModeAspectFill; 
    [skView presentScene:scene]; 
} 
+1

Bella soluzione. L'unico problema sarebbe che devi usare scaleFactorX e scaleFactorY per ogni posizione. Pensi che una categoria lo renderebbe ancora più semplice? –

+0

@sangony Intendi realizzare tutte le immagini con suffisso 3x? O solo per renderli alle dimensioni delle immagini 3x e per utilizzare la denominazione standard come per 1x? Mi piace la soluzione perché sembra che il posizionamento e il ridimensionamento siano eseguiti correttamente e anche su 4s tutto sembra come dovrebbe (niente barre nere). Unico svantaggio è il consumo di memoria a causa di risorse 3x e di una codifica in più, ma testerò anche questo per vedere i risultati. – Whirlwind

+0

@Whirlwind - Nessun suffisso immagine 3x. Basta creare tutte le dimensioni delle immagini come se dovessero essere usate per 3x. Il ridimensionamento del codice si occupa del resto senza alcuna perdita evidente di risoluzione. Questo ti permette anche di usare un atlante di texture con questo metodo. – sangony