L’accelerometro è uno dei componenti più importanti e di successo del nostro iPhone / iPod Touch (e presto iPad), ad oggi sfruttato in molte applicazioni e videogiochi presenti in App Store. Se vi accingete, infatti, a programmare giochi per iPhone, sicuramente non potete sottovalutare questo componente hardware. Per questo motivo, nel tutorial di oggi, vi guiderò all’uso (semplicissimo) di questo fantastico strumento creando una piccola applicazione che, sfruttando questo componente, vi permetterà di muovere una pallina a seconda dell’inclinazione che darete al vostro dispositivo mobile.
Iniziamo col progettare la nostra piccola applicazione, essendo essa molto semplice ci servirà:
- un componente che ci dia l’inclinazione, quindi l’accelerometro. Classe: UIAccelerometer;
- una classe che gestisca il movimento della pallina;
- la pallina 🙂
Piccola nota: quasi mai si troverà un programma come Interface Builder che ti costruisce l’interfaccia grafica con il drag&drop quindi, in questo tutorial, creeremo la grafica via codice, il che è più divertente e molto più “dinamico” a mio parere.
Apriamo Xcode e creiamo un nuovo progetto “Window-Based Application”.
Iniziamo con una cosa banale, inseriamo l’immagine della nostra pallina.
Potete usare la mia, che trovate giusto qui sopra, oppure potete crearne una voi, molto più carina!
Inseriamola nella cartella “Resources”.
Creiamo la nostra classe per la gestione del movimento della pallina, quindi aggiungiamo una nuova classe nella cartella “Classes” figlia di UIViewController (quale classe migliore):
Iniziamo a scrivere nel file di intestazione .h (l’header) i campi che ci serviranno: l’immagine della pallina e una variabile che ci servirà per impostare la sensibilità del nostro accelerometro:
Passiamo quindi al file di implementazione (.m) di questa classe. Notiamo molti metodi già costruiti per noi da Xcode, anche se gran parte di loro sono racchiusi in tag di commenti. Leggendo si può capire a cosa servano, nel nostro caso useremo il metodo -(void)loadView che viene chiamato non appena viene richiesto di visualizzare la view di questo UIViewCotroller. Eliminiamo quindi i tag di commento per questo metodo e scriviamo il codice per inizializzare la vista di questa nostra classe:
- (void)loadView {
// creiamo l'immagine della pallina
pallinaView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"pallina.png"]];
// creiamo la vista del nostro UIViewController
UIView *controllerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
// aggiungiamo la pallina alla nostra vista (di modo che sia visibile)
[controllerView addSubview:pallinaView];
// impostiamo la vista creata, come la vista di questo UIViewController
[self setView:controllerView];
// rilasciamo l'oggetto che ormai non ci serve più
[controllerView release]; // notare che l'oggetto rimarrà "vivo" perchè il nostro controller ha fatto un "retain" quando abbiamo fatto "setView:"
Visto che abbiamo allocato la pallinaView e non rilasciata, ricordiamoci di farlo nel dealloc:
- (void)dealloc {
[pallinaView release];
[super dealloc];
}
La grafica è fatta! Molto semplice vero? Non è necessario scomodare Interface Builder.
Ora passiamo al cuore dell’applicazione: l’accelerometro! Come si può leggere dalla documentazione Apple, per richiamarlo basta scrivere [UIAccelerometer sharedAccelerometer] e usare uno dei due metodi elencati.
Sempre nel loadView attiviamo l’accelerometro in questo modo:
// attiviamo l'accelerometro
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:0.001];
// impostiamo la sensibilità a 4
sensibilita = 4;
}
Impostando il delegato (colui che riceverà i dati dell’accelerometro) a self e compilando a questo punto, ci verrà restituito un warning, per risolvere, basterà correggere l’header in questo modo:
Ora dobbiamo aggiungere il metodo del delegato, cercando nella documentazione Apple eccolo qua:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration;
Ogni volta che l’accelerometro avrà delle informazioni da darci, ce le passerà qui, e noi le sfrutteremo per spostare la pallina.
Per il movimento ho scritto un semplice algoritmo che mi limito a riportare commentato, è molto semplice. Calcola semplicemente la posizione che avrà la pallina e se dovesse uscire dallo schermo la “blocca”. Eccovi il codice:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
// ricaviamo lo spostamento che avrà la pallina nelle due direzioni
CGPoint spostamento = CGPointMake(acceleration.x * sensibilita, acceleration.y * sensibilita * -1);
// calcoliamo se la pallina, con tale spostamento, finirà fuori dallo schermo
CGRect pallinaFrame = pallinaView.frame;
// impostiamo le coordinate che dovrebbe avere
pallinaFrame.origin.x += spostamento.x;
pallinaFrame.origin.y += spostamento.y;
// se la pallina uscisse a sinistra
if (pallinaFrame.origin.x < 0)
pallinaFrame.origin.x = 0;
// se uscisse a destra
if (pallinaFrame.origin.x > (pallinaView.superview.frame.size.width - pallinaFrame.size.width))
pallinaFrame.origin.x = (pallinaView.superview.frame.size.width - pallinaFrame.size.width);
// se uscisse in alto
if (pallinaFrame.origin.y < 0)
pallinaFrame.origin.y = 0;
// se uscisse in basso
if (pallinaFrame.origin.y > (pallinaView.superview.frame.size.height - pallinaFrame.size.height))
pallinaFrame.origin.y = (pallinaView.superview.frame.size.height - pallinaFrame.size.height);
// sposto la pallina
pallinaView.frame = pallinaFrame;
}
Tutto a posto, ora la classe dovrebbe funzionare a dovere. Ultima cosa da fare è che qualcuno ora la chiami ‘sta classe!
Andiamo quindi in nomeprogettoAppDelegate.h e importiamo la nostra classe:
E implementiamo a dovere:
Ricordatevi, infine, di rilasciare l’oggetto nel dealloc!
Potete scaricare il mio progetto completo da questo link.
43 Responses to “T#029 – Muoviamo una pallina tramite l’accelerometro”
1 Aprile 2010
spinorickyComplimenti per il tutorial! Mi piace!
2 Aprile 2010
lucaOttimo: esauriente, semplice ed essenziale
6 Aprile 2010
hackuCiao.. io non posso provarlo perchè non possiedo ancora un iphone (e nel simulator come tutti sapete non funziona l’accelerometro)
volevo sapere se si comportava come quelle dei giochi tipo labyrinth, cioè che sfrutta la fisica diciamo.
comunque grazie, è interessante questo tutorial!
7 Aprile 2010
MarcelloCiao
Ma non dovrebbe funzionare anche in emulazione con i tasti cmd -> e cmd <- ?
Mi aspettavo di vedere la pallina che cascava a picco…
grazie
Marcello
29 Aprile 2010
Matteoscusatemi, ma nel tut originale sembra che venga creata una nuova classe che nel progetto scaricato nn esiste, scusate ma nn l’ho capita.. per quello nn mi esce l’ex…
29 Aprile 2010
Francesco BurelliCiao, la nuova classe creata è “PallinaViewController” sottoclasse di “UIViewController” e nel progetto è presente.
Spiega meglio cosa non hai capito.
29 Aprile 2010
Matteociao, nel tut, alla schermata “Schermata-2010-03-31-a-10.50.10-300×258.png” sembra che andate a integrare l’app con una nuova sottoclasse cosa che io nn faccio.
o meglio la mia app si chiama pallina e scrivo tutto nelle classi che mi genera di default.
29 Aprile 2010
Francesco BurelliInfatti, viene inserita una nuova classe, cosa indispensabile. Di default l’unica classe presente è “nomeprogettoAppDelegate” che è il delegato dell’applicazione. Volendo si potrebbe scrivere il codice lì, ma, a mio parere, è controproducente. Infatti Apple consiglia di non usare la window per qualsiasi vista, ma di usare un’altra vista disposta sopra la window, ma per inserire una vista (UIView) conviene usare un UIViewController.
Se vuoi puoi scrivere il tutto nel file “nomeprogettoAppDelegate”, ma quando ti ritroverai con applicazioni grosse troverai comodo scrivere il codice su più file.
E comunque ripeto che se vuoi visualizzare una qualsiasi cosa sulla window (come in questo caso la pallina) devi creare un UIViewController nel quale inserire tutto e attraverso quello gestire gli oggetti di quella vista.
Spero di essermi spiegato.
30 Aprile 2010
Matteono probabilmente sono io ottuso, anzi sicuramente…
in breva se io creo un nuovo progetto nella cartella classes mi crea:
nomeprogappdelegate.h
nomeprogappdelegate.m
e
nomeprogviewcontroller.h
nomeprogviewcontroller.m
e fin qui c siamo, ma se poi io creo un’altra classe tipo “test” lui nella cartella classe mi crea:
test.h
test.m
cio vuol dire ceh se io creo una nuova classe avro nella cartella 6 files….
se vuoi scaricate il vs progetto nn ha 6 files ma ne ha solo 4, cosa vuol dire?
ripeto nn sono qua a criticare, ma voglio solo capire come funziona.
grazie in anticipo per la risposta.
M.
30 Aprile 2010
Francesco BurelliFacciamo un po’ di ordine:
Creando un nuovo progetto nella cartella “classes” avrai solo 2 file: “nomeprogettoAppDelegate.h” e “nomeprogettoAppDelegate.m” che è una classe, più precisamente la classe delegate dell’applicazione (vedi UIApplicationDelegate nella documentazione Apple).
Questa classe non è adatta per scriverci sopra cosa deve fare la pallina, quindi si crea una nuova classe in questo caso io ho creato una classe sottoclasse di UIViewController e l’ho chiamata PallinaViewController ma potevo anche chimarla ControllerDellaPallina…
Ogni classe ha il suo file header (.h) e il file di implementazione (.m) quindi ovviamente avrai 2 file per classe. Nel progetto del tutorial ci sono 4 file, 2 per la classe creata in automatico dal progetto e 2 per la mia nuova classe dove ho descritto il comportamento della pallina.
30 Aprile 2010
Matteoche ti avevo detto prima?? che sono ottuso….
in effetti hai ragione, insistevo con i files perche ho selezionato“View-Based Application” invece che “Window-Based Application”, e in effetti il primo ne crea di default 4 come ti avevo descritto, ma il progetto da voi creato è di “Window-Based Application”…
chiedo scusa….
M.
1 Maggio 2010
Francesco Burelliaaah ok non ti preoccupare, sono sempre comunque disponibile nel aiutarvi.
Ciao!
1 Maggio 2010
intenzionato a diventare programmatorescusate quando tento di inserire lo sfondo dove far muovere la pallina non mi visualizza lo sfondo.
La pallina si vede ma lo sfondo che è molto grande no mi potreste aiutare?
2 Maggio 2010
Francesco BurelliCome hai inserito lo sfondo?
Io ti consiglio: nel “-(void)loadView” crea una UIImageView con un’immagine esistente nella cartella “Resources” e poi aggiungi questo oggetto nella UIView che ho già creato io ([controllerView addSubview:laTuaUIImageView]).
2 Maggio 2010
intenzionato a diventare programmatoreIo ho inserito lo sfondo nello stesso modo della pallina.
Ora provo il tuo metodo
2 Maggio 2010
intenzionato a diventare programmatoregrazie ci sono riuscito
2 Maggio 2010
intenzionato a diventare programmatoree se dovessi spostare la pallina nella strada che deve seguire dovrei
1)mettere l’ immagine della strada
2)nel punto //sposto la pallina dovrei mettere : pallinaView.frame = stradaFrame;
2 Maggio 2010
intenzionato a diventare programmatore?????
4 Maggio 2010
Francesco BurelliAttento: leggi nella documentazione che cosa è il frame…
Se metti uno sfondo con disegnata una strada… Bhe sarà difficile far rispettare quest’ultima dalla pallina. Piuttosto inserisci dei “muri” e con degli “if” puoi controllare le collissioni con le viste inserite.
Ma il tutto e piuttosto laborioso ed è la strada sbagliata: qui ci addentriamo nel mondo dei videogiochi quindi io consiglio di impararsi un po’ di OpenGL e poi creare tutti i giochini che ti vengono in mente.
4 Maggio 2010
mac usergrazie.Dove posso trovare questa documentazione?
4 Maggio 2010
Francesco BurelliIntendo la documentazione Apple… da Xcode Help > Developer Documentation …
Perché scrivere “pallinaView.frame = stradaFrame” è concettualmente molto sbagliato per quello che intendi fare, per questo ti consiglio vivamente di informarti su cosa sia il frame.
Per quanto riguarda l’OpenGL invece esiste in rete il Red Book (in inglese).
4 Maggio 2010
startitScusate, lo so che non è pertinente a quest’area, ma volevo chiedere una cosa a Francesco Burelli…..hai ricevuto per caso la mia email, inviata dal tuo form sul tuo sito ?
Grazie.
Scusate di nuovo.
Saluti.
Massimo Bonechi.
21 Maggio 2010
intenzionato a diventare programmatoreho scoperto un metodo per mettere le app nel iphone , ma quando la metto e cerco di aprirla nell’ iphone appare una schermata nera e poi si chiede mi puoi aiutare?
21 Maggio 2010
intenzionato a diventare programmatoreho scoperto un metodo per mettere le app nel iphone , ma quando la metto e cerco di aprirla nell’ iphone appare una schermata nera e poi si chiede mi puoi aiutare?
21 Maggio 2010
Francesco BurelliApple non permette di installare le applicazioni sull’iPhone se non sei iscritto al programma developer e non hai pagato la tassa annuale. Quindi il metodo che hai trovato, ne deduco, è un metodo non “ufficiale”.
Quindi tiro ad indovinare:
L’applicazione è scritta in modo sbagliato e crasha appena parte, oppure il tuo metodo per installare le app sull’iPhone non funziona.
Testa se funziona il metodo con altre applicazioni. In caso usa il debugger per verificare dove crasha l’app.
21 Maggio 2010
intenzionato a diventare programmatoreallora provo con un app completa
31 Maggio 2010
intenzionato a diventare programmatorevabbe in quel modo no ci sono riuscito ma perchè usando isimulate non funziona?
31 Maggio 2010
Francesco BurelliSpiacente, in questo non posso aiutarti, ti posso dare la dimostrazione che la mia “app” funziona: vedi qua http://www.youtube.com/watch?v=lgNDLmzPeqM&feature=player_embedded
di isimulate e simili non so nulla.
ciao
31 Maggio 2010
intenzionato a diventare programmatorebello, provo a risolvere
5 Agosto 2010
intenzionato a diventare programmatoreScusa se scrivo qui e non nel forum ma quando clicco su nuova discussione mi dice che non ho i permessi per farlo O.o
Comunque quando faccio un progetto opengl es application e faccio buld en run mi esce un quadrato con i colori arcobaleno che va su e giù, mi pui dire come toglierlo?
10 Settembre 2010
LucaCome fai a vederla sul’iphone?
11 Settembre 2010
Francesco BurelliIntendi come fare per installare l’app su iPhone? devi acquistare la licenza mi pare di ricordare… (non lo ricordo perché io ho la licenza, non so se puoi senza)
Altrimenti penso ci siano vie “secondarie”… ma non le conosco
2 Novembre 2010
wasciao francesco,
mi da un errore accanto a – (void)loadview
reimplementation of class “PallinaViewController”
ho provato anche a copiare tutto il tuo progetto, ma niente…
grazie in anticipo
2 Novembre 2010
Francesco BurelliMi dispiace, dovrei vedere il codice che hai scritto, prova a confrontarlo con il mio di esempio (il progetto completo).
Dall’errore sembra ci siano due implementazioni di “PallinaViewController” sicuro che nel copia incolla non hai scritto due volte “@implementation PallinaViewController” o che esistano due file PallinaViewController.m? o che il metodo -(void)loadView sia scritto una sola volta? hai chiuso la graffa di quest’ultimo metodo?
è un errore di sintassi questo, se non vedo il codice posso aiutarti poco, mi dispiace.
2 Novembre 2010
wasecco appunto, avevo messo due volte @implentation e non me ne ero accorto…l’avevo anche copiato due volte…un fenomeno, in pratica!!
grazie mille e scusami, ma sono troppo niubbo… :))
19 Marzo 2011
Stefanociao, sono un giovane studente che sta cercando di creare le sue prime applicazioni. Come prima cosa volevo complimentarmi con voi con la semplicità e la chiarezza con cui spiegate e gestite il sito devApp comunque volevo chiederti se volessi ridurre il campo d’azione della pallina a direttamente solo una striscia dello schermo,dovrei modificare queste righe del codice:
” // ricaviamo lo spostamento che avrà la pallina nelle due direzioni
CGPoint spostamento = CGPointMake(acceleration.x * sensibilita, acceleration.y * sensibilita * -1);
// calcoliamo se la pallina, con tale spostamento, finirà fuori dallo schermo
CGRect pallinaFrame = pallinaView.frame;
// impostiamo le coordinate che dovrebbe avere
pallinaFrame.origin.x += spostamento.x;
pallinaFrame.origin.y += spostamento.y;
// se la pallina uscisse a sinistra
if (pallinaFrame.origin.x (pallinaView.superview.frame.size.width – pallinaFrame.size.width))
pallinaFrame.origin.x = (pallinaView.superview.frame.size.width – pallinaFrame.size.width);
// se uscisse in alto
if (pallinaFrame.origin.y (pallinaView.superview.frame.size.height – pallinaFrame.size.height))
pallinaFrame.origin.y = (pallinaView.superview.frame.size.height – pallinaFrame.size.height);
// sposto la pallina
pallinaView.frame = pallinaFrame;”
giusto?ma come?
e poi un ultima domanda come dovrei fare per inserire un timer ed un contatore (qui io userei un ciclo ma mi faresti un po di chiarezza)
GRAZIE!!!!!!!!! 🙂
5 Aprile 2011
fabianoIntanto grazie per i vostri tutorial sono veramente molto utili!! il codice è sempre molto chiaro ed esaustivo. Sto provando ad aggiungere una funzionalità a questa app ma con scarsi risultati. Vorrei far ruotare l’immagine della pallina in base alla direzione. Avete qlc indicazione da darmi? E’ un giorno intero che sto provando ad implementarla ma niente di niente!!!
12 Gennaio 2012
AlessandroScusa, ma per aggiungere altre palline? E’ possibile? e se io volessi implementarlo in un’app, come potrei fare per mettere una navigation bar…forse sono io che sono nostalgico di IB…ma cosi mi viene nero schermo intero e il resto dell’app, una volta aperta la view, viene tagliata fuori! 🙂 help me please!
13 Gennaio 2012
Francesco BurelliUna cosa alla volta:
1. per mettere una navigation bar io ti consiglio di usare una UINavigationController. Però non posso spiegarti in un commento come funziona questa classe.
2. Inserire più palline è ovviamente possibile, ma presenta un problema molto grosso: programmare l’interazione fra le palline, che non è affatto uno scherzo. Per quanto riguarda il semplice inserimento di più palline basta creare un array di palline e nei metodi delegati dell’accelerometro applicare la legge fisica ciclicamente a tutte le palline dell’array.
5 Giugno 2012
DavideCome si può calibrare l’iPhone in modo tale da non averlo “in piano” ma leggermente piegato verso l’utente finale?
6 Giugno 2012
Francesco Burelli#40 la cosa è leggermente complicata in teoria, nella pratica, non troppo. Hai mai studiato geometria? Praticamente tu hai l’accelerazione su 3 assi (x y z) per simulare un’inclinazione iniziale dovresti ruotare lo spazio di un certo angolo in una certa direzione. A livello matematico si fa con una trasformaizione lineare ovvero applicando una matrice…
Tutti questi paroloni per dire che, PRIMA di usare i valori delle accelerazioni, devi moltiplicarli per un certo fattore e poi usarli, in questo modo otterai l’effetto desiderato.
Non posso fare calcoli o prove ora, ma ti consiglio di provare a moltiplicare l’asse x o l’asse y per un qualche valore (non grande, minore di 1 se non sbaglio) e vedere l’effetto.
13 Agosto 2013
giovannie se volessi aggiornarla per iphone 5?
anche avendo aggiunto il default….@2x.png e avere modificato nella .xib nell iphone 5 lo schermo è occupato ma la palla va in giu e si ferma come se fosse un iphone 4, nel senso, è come se ci fosse ancora la riga nera sotto
14 Agosto 2013
giovannie per aggiungere un eventuale seconda schermata con un semplice bottone che fa partire la schermata con la pallina ? come faccio?