Pallina - Creiamo un'applicazione che usa l'accelerometro dell'iPhone [parte 1]

Pubblicato il 07/07/2009 in Tutorial iPhone SDK Object-c
[b][code]In questo nuovo tutorial andrò a spiegarvi come creare un'applicazione che sfrutti l'accelerometro dell'iPhone per muovere una pallina (UIImageView) a seconda dell'inclinazione del telefono nello schermo, senza uscire ovviamente da esso.
Il risultato sarà come da video sopra.

Illustro prima la struttura di questa applicazione: avremo fondamentalmente 2 oggetti che lavoreranno insieme per muovere la pallina.
Il primo oggetto sarà quello che si occupa di muovere la pallina. Quindi tutti gli altri oggetti si dovranno rivolgere a lui per muovere la pallina, solo lui è in grado di muoverla, lanciarla, fermarla etc. (in questo tutorial vedremo solo come muoverla, per lanciarla, per esempio, ce ne occuperemo più avanti)
Il secondo oggetto sarà quello che dirà al primo di muovere la pallina secondo le sue esigenze. Questo oggetto sarà il delegato dell'accelerometro (vedi qui per il delegato) che a seconda di come sarà inclinato l'iPhone darà delle indicazioni all'oggetto che sposterà la pallina.

Procediamo subito con la creazione del nostro nuovo progetto


Ora apriamo il file .xib per modificarne la grafica

Aggiungiamo un oggetto UIViewController che servirà come vista della nostra applicazione nonché oggetto che gestirà la nostra pallina.

Notare che ho spuntato "Wants Full Screen" e ho eliminato la status bar. In questo modo la vista coprirà tutto lo schermo.
La vista all'interno l'ho configurata così (nulla di rilevante)

Ora torniamo a Xcode e aggiungiamo un file al progetto; aggiungiamo un'immagine, quella della pallina. (se volete potete usare anche voi questa)

Aggiungiamo alla view un oggetto UIImageView e configuriamolo in questo modo

La mia pallina misura 50x50 quindi

Selezioniamo ora l'oggetto UIViewController e da questo creiamo un nuovo oggetto che io ho chiamato "PallController" ovvero l'oggetto che controllerà i movimenti della pallina. Negli Outlet mettiamo il riferimento alla pallina.

Come al solito indichiamogli quale è questa pallina

Ora creiamo il file dell'oggetto, come al solito



Prima di proseguire settiamo come vista all'avvio questa appena creata (vi ricordo la guida più dettagliata qui)
Aggiungiamo il nostro controller

Nascondiamo la status bar all'avvio e aggiungiamo la nostra vista sopra la window

Indichiamo in fine nell'Interface Builder qual è l'oggetto che dovrà avviarsi..


Se ora testate l'applicazione vi ritroverete con una pallina che non fa nulla.

Torniamo al nostro oggetto appena creato e iniziamo la sua configurazione.
Nel nostro file .h aggiungiamo una variabile di tipo float che sarà il nostro coefficiente di attrito (spero tutti capiate quale sarà il suo scopo) e aggiungiamo i nostri 3 metodi per la gestione della pallina

Il primo metodo riceverà due valori (raggruppati in uno CGPoint *) che indicheranno di quanto e in quale direzione deve spostarsi la pallina.
Il secondo serve a modificare il valore di attrito e il terzo serve ad ottenerlo, nel caso qualche oggetto volesse saperlo (questi due metodi li tratteremo nella seconda parte).
Analizziamo ora l'implementazione.
Nel file .m iniziamo col configurare il coefficiente di attrito
/* appena caricata la grafica setto il coefficiente d'attrito */
-(void)awakeFromNib {
[self setAttrito:10.0];
}

non penso serva commentare queste linee, solo preciso che 10 è un buon valore, sotto la pallina va troppo lenta, penso comunque che 20 sia ancora meglio.
Analizziamo ora gli ultimi due metodi che sono veramente semplici
-(void)setAttrito:(float)coeff {
attrito = coeff;
}

-(float)getAttrito {
return attrito;
}

Questi non li commento, semplicemente uno setta l'attrito e l'altro lo restituisce a chi chiede.
Il metodo fondamentale per il movimento della pallina... bhé io ci ho messo tutto il mio impegno, il risultato finale non è male, ma si può sempre migliorare.
Il vero problema di questo metodo è gestire il movimento della pallina appena va a cozzare contro le pareti dello schermo, se non ne discutiamo la pallina uscirà dallo schermo, quindi bisogna fare in modo che ciò non avvenga.
Io ho risolto così:
-(void)muovi:(CGPoint)coord {
/* modifico i valori di entrata a seconda dell'attrito */
coord.x *= attrito;
coord.y *= -attrito;

/* varibili necessarie solo per questo metodo */
float newX = pallina.center.x + coord.x;
float newY = pallina.center.y + coord.y;

/* verifichiamo che le nuove coordinate non vadano fuori dallo schermo */
/* se sbatte a destra */
if(pallina.center.x + coord.x >= 295) {
float avanzoX = 295 - pallina.center.x;
newX = pallina.center.x + avanzoX;
}
/* altrimenti a sinistra */
else if(pallina.center.x + coord.x <= 25) {
float avanzoX = pallina.center.x - 25;
newX = pallina.center.x + avanzoX;
}
/* se sbatte in basso */
if(pallina.center.y + coord.y >= 455) {
float avanzoY = 455 - pallina.center.y;
newY = pallina.center.y - avanzoY;
}
/* altrimenti in alto */
else if(pallina.center.y + coord.y <= 25) {
float avanzoY = pallina.center.y - 25;
newY = pallina.center.y + avanzoY;
}

pallina.center = CGPointMake(newX,newY);
}


Precisiamo giusto un paio di punti: le coord vengono moltiplicate per l'attrito (come da legge fisica) in modo che possano conservare il segno; la coord.y è invertita quindi l'ho moltiplicata per -attrito.
Le due variabili newX e newY saranno le nuove coordinate del centro della pallina che si ottengono sommando le coordinate attuali della pallina sommate ai punti che vendono dati dall'argomento del metodo. Queste due variabili però assumeranno un altro valore se la pallina va a urtare contro i margini dello schermo, quindi ho aggiunto degli "if" per i 4 casi.
Il calcolo che ho fatto non è dei più intuitivi, ma dopo diverse sperimentazioni è il migliore che ho potuto ottenere.
Semplicemente il codice dice: se la pallina, con queste nuove coordinate, andrebbe fuori dallo schermo, allora calcola quanto gli manca per arrivare sul bordo dello schermo e falla arrivare li invece che fuori.
La viaribile avanzo è la misura tra la pallina e il bordo.
Notare che si lavora col centro della pallina, quindi bisogna calcolare che il bordo di essa è a +-25x +-25y (nel mio caso che la pallina è 50x50).

Siamo quasi alla fine, ora basta creare l'oggetto che gestisce l'accelerometro e il gioco è fatto.
Ricordo ancora che per la creazione dell'oggetto delegato accelerometro qui c'è la guida.
Andiamo in IB e aggiungiamo un oggetto NSObject, chiamiamolo ad esempio "AccController" e configuriamolo come in figura

Indichiamogli chi è PallController

Facciamo come al solito File>Write Class File e nel file di .h inseriamo


Ora l'implementazione, molto semplice:
settiamo il delegato e la velocità di aggiornamento dell'accelerometro (0.01 è la massima velocità) più velocità = più consumo energetico
-(void)awakeFromNib {
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:0.01];
}

Poi il metodo usato ogni volta che l'accelerometro ha un nuovo valore
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
CGPoint accelerazione = CGPointMake(acceleration.x,acceleration.y);
[pallController muovi:accelerazione];
}

Come potete notare richiama il metodo dell'oggetto creato prima e gli indica di quanto spostare la pallina, ovvero di spostarla a seconda delle accelerazioni dell'iPhone.

Abbiamo concluso il tutorial, ora c'è un problemino: per testare l'applicazione... serve l'accelerometro, cosa che il simulatore non ha, quindi occorre installare l'applicazione sul dispositivo, ma ciò Apple non lo consente se non si paga una certa cifra...
Esistono delle vie traverse, ma per il 3.0 io non le conosco e non mi interessa :D

In caso di problemi ecco il mio progetto
Visite all'articolo: 82
Vota l'articolo (media attuale su 0 voti: )


Vuoi aggiungere un commento?
Il tuo nome
La tua email (non verrà pubblicata)
Commento
Francesco Burelli © 2009 tutti i diritti riservati.