utilizzo di wiimote e balance board come strumento per la

Transcript

utilizzo di wiimote e balance board come strumento per la
POLITECNICO DI MILANO
FACOLTÀ DI INGEGNERIA
CORSO DI LAUREA IN INGEGNERIA INFORMATICA
UTILIZZO DI WIIMOTE E BALANCE BOARD
COME STRUMENTO PER LA RIABILITAZIONE
IN APPLICAZIONI REALIZZATE CON IL FRAMEWORK XNA
Relatore: Prof. Alessandro CAMPI
Correlatore: Ing. Paola SPOLETINI
Tesi di Laurea di:
Enrico BONTEMPI
Matricola n. 704443
Roberto CARETTONI
Matricola n. 704099
ANNO ACCADEMICO 2009-2010
1
Indice
Indice .................................................................................................................................2
Capitolo 1.
Introduzione.................................................................................................5
Capitolo 2.
L’innovazione di Nintendo Wii ....................................................................6
Capitolo 3.
Il Wiimote [4] ..............................................................................................7
3.1
Pulsanti ................................................................................................................8
3.2
Accelerometro .....................................................................................................9
3.2.1
Accelerazione statica e dinamica ...................................................................9
3.2.2
Interpretazione dei valori rilevati ................................................................10
3.2.3
Calcolo delle inclinazioni degli assi ............................................................10
3.3
Puntamento Infrarosso .......................................................................................12
3.3.1
Sensor Bar ..................................................................................................12
3.3.2
Tecnica di puntamento ................................................................................13
3.3.3
Posizione di puntamento .............................................................................13
3.3.4
Levigatura del cursore.................................................................................14
3.4
Altre funzionalità ...............................................................................................15
3.4.1
LED ............................................................................................................15
3.4.2
Rumble .......................................................................................................15
3.4.3
Speaker .......................................................................................................15
3.5
Estensioni ..........................................................................................................16
3.5.1
Nunchuk .....................................................................................................16
3.5.2
Classic Controller .......................................................................................17
3.5.3
Wii Motion Plus ..........................................................................................17
3.5.4
Wii Balance Board ......................................................................................18
Capitolo 4.
4.1
Interfacciamento e connessione dei dispositivi ...........................................19
HID [5] ..............................................................................................................19
4.1.1
L’innovazione di HID .................................................................................19
4.1.2
Il protocollo HID ........................................................................................20
4.1.3
Bluetooth HID ............................................................................................20
4.2
Bluetooth [6]......................................................................................................21
2
4.2.1
BlueSoleil [7] .............................................................................................21
4.2.2
Connessione del Wiimote ...........................................................................22
4.3
Wiimotelib .........................................................................................................24
4.3.1
Creazione del canale di comunicazione .......................................................24
4.3.2
Trasmissione dei pacchetti ..........................................................................26
Capitolo 5.
Ambiente di Sviluppo .................................................................................28
5.1
Microsoft Visual Studio 2008 [12] .....................................................................28
5.2
C# [13] ..............................................................................................................28
5.3
Il Framework XNA [15].....................................................................................29
5.4
Struttura di un progetto XNA [16]......................................................................29
5.4.1
Metodi predefiniti .......................................................................................30
5.4.2
Componenti ................................................................................................30
5.4.3
Grafica 2D ..................................................................................................31
5.5
Audio .................................................................................................................32
5.5.1
XACT .........................................................................................................32
5.5.2
Classe statica Audio ....................................................................................32
5.6
Requisiti di piattaforma ......................................................................................34
Capitolo 6.
6.1
Ideazione del software ................................................................................35
Specifiche del software ......................................................................................35
6.1.1
Design della batteria ...................................................................................35
6.1.2
Criteri di movimento ...................................................................................36
6.1.3
Composizione e disegno della batteria ........................................................39
6.1.4
Determinazione e controllo della posizione del centro di massa ..................40
6.1.5
Fase di gioco ...............................................................................................41
6.1.6
Modalità Free .............................................................................................42
Capitolo 7.
7.1
Gestione del Wiimote con Wiimotelib ........................................................43
La classe Wiimote..............................................................................................43
7.1.1
Metodi ........................................................................................................44
7.1.2
Eventi .........................................................................................................44
7.1.3
WiimoteCollection ......................................................................................44
7.2
Le strutture dati..................................................................................................45
7.3
Eccezioni ...........................................................................................................47
3
7.4
Implementazione della classe WiiMote ..............................................................47
7.4.1
Capitolo 8.
8.1
Metodi della classe WiiMote.......................................................................48
Implementazione del videogame ................................................................49
La classe DrumAble ...........................................................................................50
8.1.1
Modalità di esecuzione ...............................................................................51
8.1.2
Compiti della classe DrumAble...................................................................51
8.2
I componenti della sezione menu .......................................................................52
8.2.1
La classe Menu ...........................................................................................52
8.2.2
La classe Istruzioni .....................................................................................52
8.2.3
La classe Tracklist ......................................................................................52
8.2.4
La classe Speed...........................................................................................53
8.2.5
La classe RiproduzioneSequenza ................................................................53
8.3
Le tracce predefinite ..........................................................................................53
8.3.1
La classe Traccia ........................................................................................53
8.3.2
I DataSet .....................................................................................................54
8.4
L’input della fase di gioco ..................................................................................54
8.4.1
La classe Percussione ..................................................................................54
8.4.2
Rilevamento dei gesti..................................................................................55
8.4.3
Evento PercussioneChanged .......................................................................55
8.4.4
La classe BalanceBoard ..............................................................................55
8.5
I componenti della fase di gioco .........................................................................56
8.5.1
La classe PlayScreen ...................................................................................56
8.5.2
La classe Logica .........................................................................................57
Capitolo 9.
Sviluppi futuri.............................................................................................58
Elenco figure ...................................................................................................................59
Elenco Tabelle .................................................................................................................59
Bibliografia ......................................................................................................................60
4
Capitolo 1.
Introduzione
Nel 2006 Nintendo lancia la console Wii [1], appartenente alla settima generazione [2], la
cui innovazione è insita nella nuova natura dei controller, che non sono più dei semplici
telecomandi che permettono di comandare i giochi soltanto premendo dei pulsanti, ma
dispositivi in grado di rilevare il movimento del corpo o di alcune sue parti rendendo così
possibile un’associazione tra gesti compiuti dai giocatori e azioni di risposta all’interno dei
videogame.
Questo lavoro si colloca in un più ampio progetto di sviluppo di applicazioni rivolte a
soggetti con disabilità motorie [3], quali individui paraplegici. Tale progetto consiste nella
creazione di videogiochi con finalità terapeutiche, con l’intento cioè di intrattenere gli
utenti stimolandoli a compiere determinati movimenti, introducendo così l’uso di questi
software ad esempio nella riabilitazione post-trauma. Grazie alle loro caratteristiche, i
controller di Wii si prestano particolarmente a questo ambito di progetto, e sono l’ideale
strumento di interazione con l’utente in applicazioni di questo genere.
L’obiettivo di questo lavoro è sfruttare la tecnologia del Wiimote e della Balance Board
mediante la creazione di interessanti applicazioni indipendenti dai pulsanti e governabili il
più possibile attraverso i movimenti di un Wiimote e il rilevamento del baricentro tramite
la Balance Board. Il prodotto di questo lavoro è un software che simula una batteria
musicale, utilizzabile mediante il compimento di diversi gesti con il Wiimote, stando seduti
sulla Balance Board.
Questo progetto permette di estendere l’ambito dei lavori svolti in passato, che si
concentravano principalmente sull’equilibrio e sul movimento del busto mediante l’uso
esclusivo della Balance Board, all’utilizzo degli arti superiori.
5
Capitolo 2. L’innovazione
Nintendo Wii
di
Le innovazioni introdotte con Nintendo Wii [1] aprono varie frontiere nel videogaming in
quanto l’utilizzo di movimenti come input per i giochi permette di modellare in maniera
molto più naturale le interazioni con l’utente. Diventa così possibile simulare i gesti
compiuti in discipline sportive, nell’uso di strumenti musicali o di utensili attraverso i
telecomandi di Wii, e introdurre tutte queste attività in svariati videogame che riscuotono
notevole successo.
Il controller principale della console Wii è il Wiimote; è un telecomando senza fili che
comunica con la console attraverso la tecnologia Bluetooth. Il Wiimote è dotato di
pulsanti, di un accelerometro in grado di rilevare i movimenti impressi al telecomando, e di
altri dispositivi che consentono l’interazione sia per l’input che per l’output.
Al Wiimote possono essere collegati mediante un apposito connettore altri controller tra
cui: Nunchuk, Classic Controller, WiiMotionPlus, chitarra e batteria di Guitar Hero e altri.
Questi dispositivi vengono identificati dalla console come estensioni del controller
principale, e il flusso di informazioni trasmesse relativo ad un’estensione viene inglobato
nelle informazioni del Wiimote. È possibile collegare una sola estensione al Wiimote, a
meno che si tratti del WiiMotionPlus, che dispone di un connettore per estensioni, agendo
così in modo “trasparente” e permettendo l’inserimento di una seconda estensione.
Un altro controller di Wii è la Wii Balance Board; è una pedana che comunica via
Bluetooth con la console attraverso lo stesso protocollo utilizzato dal Wiimote, ma che
differisce da quest’ultimo come tecnologia interna in quanto è composta da quattro bilance
che rilevano lo spostamento del peso dell’utente che si posiziona sopra di essa.
6
Capitolo 3.
Il Wiimote [4]
Il controller di Nintendo Wii utilizza un approccio di interazione differente da quello
tradizionale, nel tentativo di risultare interessante per un pubblico più vasto. Il Wiimote ha
la forma di un comune telecomando da televisione e viene tenuto in una sola mano;
Essendo simmetrico, appare ugualmente utilizzabile da destrorsi e mancini.
Il componente principale del Wiimote è il chip Broadcom; esso è dotato di alcuni registri e
di un microcontrollore, attraverso cui gestisce il flusso interno dei dati (input e output dalle
periferiche interne) e le trasmissioni con la console. Il chip fa da riferimento per gli altri
componenti interni al dispositivo, in quanto la struttura del Wiimote è progettata intorno ad
esso.
Vi sono due funzionalità di input direttamente controllate dal chip: un accelerometro a tre
assi e 11 pulsanti (più il pulsante Power). In aggiunta, il telecomando, contiene un
ricevitore infrarosso con un processore di monitoraggio oggetti, una porta d’espansione che
permette di collegarvi fonti di input addizionali (le estensioni), uno speaker e un “rumble
pack” che consente al telecomando di vibrare.
Figura 1: Wiimote
7
3.1 Pulsanti
Il Wiimote ha 11 pulsanti sul lato frontale e uno sul retro; tra questi, il pulsante Power è
speciale ed è considerato differentemente dagli altri dal dispositivo. Tutti gli altri pulsanti
sono indipendentemente accessibili attraverso un pacchetto di 2 byte che viene trasmesso
per primo nella maggior parte dei report. Il bit corrispondente ad un pulsante assumerà
valore 1 se il pulsante è premuto oppure 0 in caso contrario. Di norma questi pacchetti
vengono inviati quando lo stato di qualche pulsante cambia, ma è anche possibile
configurare il Wiimote affinché invii lo stato dei pulsanti continuamente attraverso
un’alterazione del Data Reporting Mode.
I pulsanti dei Wiimote sono i seguenti: A, B (retro), un Pad direzionale, +, -, Home, 1 e 2.
Quando il Wiimote è spento, la pressione del pulsante Power provoca un tentativo di
riattivazione della comunicazione con la Wii a cui è sincronizzato. I dettagli
implementativi che portano all’accensione non sono stati resi pubblici e sono contenuti nel
modulo Bluetooth di Wii. La connessione del telecomando con un diverso host (pc) non
può invece avvenire automaticamente ma occorre ripetere il procedimento di connessione
dal software Bluetooth dell’host. Se il Wiimote è acceso e connesso a un host, la pressione
e il mantenimento del pulsante Power per qualche secondo fa sì che il telecomando
richieda una disconnessione dall’host e si spenga.
Vi è inoltre un ulteriore pulsante nascosto nel vano batterie: il Sync Button. Alla pressione
di tale tasto il Wiimote si disconnette dall’host con il quale ha una connessione attiva e si
pone in modalità di rilevazione accettando richieste di connessione o accoppiamento per
esattamente 20 secondi.
8
3.2 Accelerometro
Il Wiimote contiene un accelerometro lineare a tre assi posto sulla faccia superiore della
base del circuito interno, leggermente a sinistra del pulsante A. Si tratta di un componente
integrato semplicemente saldato al circuito: l’ADXL330
di Analog Devices. Questo
dispositivo può misurare l’accelerazione di gravità statica per applicazioni che
percepiscono l’inclinazione, così come l’accelerazione dinamica derivante da movimenti,
scosse o vibrazioni.
La misurazione avviene con valore minimo di fondo scala di ±3g e una sensibilità del 10%.
3.2.1
Accelerazione statica e dinamica
Poiché il funzionamento reale dell’accelerometro consiste nella misura della forza
esercitata da un insieme di piccole masse di resistenza poste al suo interno nei confronti del
guscio che le contiene, esso misura un’accelerazione lineare di un punto di riferimento in
caduta libera: questo significa che se il Wiimote fosse in caduta libera, riporterebbe
accelerazione
zero.
Quand’è
immobile
invece,
rileva
un’accelerazione
pari
all’accelerazione di gravità g (ma nella direzione opposta, verso l’alto, +Z quando è fermo
in posizione orizzontale). Questo dato può essere usato per intuire l’inclinazione del
telecomando dagli output di accelerazione quando il Wiimote è ragionevolmente fermo.
Figura 2: Wiimote e assi direzionali
9
3.2.2
Interpretazione dei valori rilevati
La Figura 2 rappresenta il Wiimote e gli assi di riferimento dell’accelerometro:
l’orientamento degli assi permette di interpretare il valore letto per ognuno di essi e
dedurne l’inclinazione rispetto alla posizione piana (orizzontale) oppure la direzione del
movimento dell’accelerazione rilevata. Durante la fase sperimentale di studio del Wiimote
si è notato che non tutti i movimenti vengono rilevati, ma il valore relativo ad un asse varia
soltanto se tale asse si muove ruotando in un piano, necessariamente ortogonale al suolo,
che lo contiene. Ad esempio il movimento rotatorio del polso, mantenendo il telecomando
in posizione orizzontale, può essere modellizzato come la rotazione del piano XZ intorno
all’asse Y che funge da perno; tale movimento può essere rilevato dalle variazioni dei
valori dei tre assi, riconoscendo una variazione positiva o negativa dei valori di X e Z (a
seconda che la rotazione sia avvenuta in senso orario o antiorario) e una conservazione del
valore precedente di Y.
Al contrario, un movimento rotatorio del telecomando appoggiato su un piano (rotazione
del piano XY con perno l’asse Z) non può essere rilevato in quanto l’asse Z funziona da
perno e quindi non subisce scostamenti, e nonostante gli assi X e Y stiano effettivamente
ruotando, non ne viene riscontrata una variazione dei valori in quanto il piano da essi
costituito è parallelo al suolo e non ortogonale, quindi anche ripetendo o velocizzando il
movimento l’accelerometro non rileverebbe variazioni: come se il telecomando fosse
fermo.
3.2.3
Calcolo delle inclinazioni degli assi
Come conclusione allo studio del funzionamento dell’accelerometro nell’ambito
dell’accelerazione statica, si è cercata una formula che permettesse di tradurre i valori letti
dal dispositivo nelle rispettive inclinazioni degli assi corrispondenti, interpretate come
sfasamenti da una posizione base, e cioè un angolo di 0° equivalente a una posizione
orizzontale, parallela al suolo, dell’asse.
A seconda dell’inclinazione dell’asse, il valore letto dal telecomando assume valori
compresi tra +1 e -1. Definito l’orientamento degli assi come mostrato in Figura 2, si è
10
messo in relazione il valore letto con la posizione dell’asse, raggiungendo le conclusioni
seguenti:
• Se l’asse (X, Y, Z) si trova in posizione orizzontale, e cioè ortogonale alla direzione
della forza di gravità, il valore rilevato è 0
• Se l’asse si trova nella stessa direzione della forza di gravità e con verso concorde
(verso il basso), il valore rilevato è -1
• Se l’asse si trova nella stessa direzione della forza di gravità ma con verso discorde
(verso l’alto), il valore rilevato è +1
Ponendo a questo punto gli angoli corrispondenti alle posizioni limite (aventi la direzione
della forza di gravità con verso concorde o discorde) rispettivamente -90° e +90°, si può
scrivere la seguente equazione che mette in relazione angoli e valori (fissati da un’ipotesi
teorica) di due posizioni limite:
(Y90° - Yα) : (Y90° - Y0°) = (90° - α) : (90° - 0°)
È un’interpolazione lineare dove:
• Y90° indica il valore di Y letto quando l’asse Y si trova a +90° (Y90° = -1)
• Yα indica il valore di Y letto quando l’asse Y si trova all’angolo α
• Y0° indica il valore di Y letto quando l’asse Y si trova a 0° (Y90° = 0)
• α è l’angolo corrispondente al valore dell’asse Y letto (Yα)
Da questa interpolazione si può ricavare la formula finale:
α = -90° · Yα
Che permette effettivamente di identificare in modo univoco l’angolo (di sfasamento)
corrispondente al valore dell’asse letto.
In Figura 2 sono indicati anche tre movimenti che in realtà non sono rilevabili dal Wiimote
ma possono essere individuati se si dispone del WiiMotionPlus, che verrà successivamente
trattato nella sezione estensioni.
11
3.3 Puntamento Infrarosso
Il Wiimote contiene un ricevitore monocromo 128x96 con un elaboratore d’immagine
integrato. Il ricevitore si presenta come un filtro infrarosso nella custodia di plastica del
telecomando. L’elaboratore d’immagine è capace di puntare fino a quattro oggetti in
movimento, e questi sono gli unici dati che trasmette all’host; i dati relativi ai pixel grezzi
“visti” dalla telecamera non sono raggiungibili dall’host, pertanto il ricevitore non può
essere usato per catturare immagini. Il processore integrato effettua un’analisi sub pixel 8x
per fornire una risoluzione 1024x768 dei punti tracciati.
3.3.1
Sensor Bar
La Wii dispone di una Sensor Bar contenente due gruppi di LED IR (infrarossi), che
vengono tracciati dal Wiimote per fornire informazioni sul puntamento. La distanza tra i
centri dei gruppi di LED è 20cm. La Sensor Bar non svolge nessun compito se non quello
di supporto e alimentazione (tramite un cavetto particolare che la collega alla console) ai
LED IR: funge in pratica soltanto da emettitore infrarosso.
I LED IR costituiscono i punti di riferimento per il ricevitore infrarosso del Wiimote:
questa correlazione permette di sfruttare un tecnica di puntamento nelle applicazioni; i
valori letti vengono spesso elaborati e convertiti ad esempio per l’uso di un cursore
governato dal movimento del telecomando.
Figura 3: Sensor Bar
12
3.3.2
Tecnica di puntamento
La prospettiva derivante dalla combinazione degli angoli (verticale e orizzontale) tra il
ricevitore e la Sensor Bar, può far apparire quest’ultima in una posizione in cui non si trova
realmente, ma attraverso semplici relazioni trigonometriche è possibile individuare lo
sfasamento degli angoli tra gli emettitori e il ricevitore.
Il primo passo dell’algoritmo di puntamento è la localizzazione della Sensor Bar. Poiché
potrebbero essere presenti fonti IR spurie, si rivela indispensabile individuare con
precisione i due punti che più probabilmente corrispondono alla Sensor Bar. Per far questo
si cercano due punti orizzontalmente allineati distanziati da uno spazio minimo predefinito
(per rimuovere ogni possibile riferimento duplicato se il Wiimote rilevasse più punti
raggruppati
intorno
ad
un
emettitore
IR),
usando
l’inclinazione
calcolata
dall’accelerometro per determinare qual è il piano orizzontale cui riferirsi. Le coppie
contraddistinte da un margine di sfasamento dal piano orizzontale superiore ai 10° vengono
scartate. Tra le rimanenti coppie, vengono scelte le due che più si avvicinano al piano
orizzontale; una coppia di punti con un terzo punto molto vicino alla linea immaginaria tra
di essi viene scartata, in quanto non è possibile che vi sia un emettitore IR tra gli estremi,
pertanto quella coppia non può essere la Sensor Bar.
Se il Wiimote smarrisce il puntamento di una delle estremità, che può scomparire dalla
vista una volta avvicinatosi ai bordi dell’area di puntamento o quando ne esce, il
telecomando tenta di proseguire usando il solo punto rimanente cercando di intuire la
posizione del punto scomparso, ad esempio usando i valori della distanza (fissa) tra i due
punti e i valori dell’accelerometro per calcolare l’angolo.
3.3.3
Posizione di puntamento
Noti i due punti della Sensor Bar, viene ruotato il campo del sensore per farli apparire in
allineamento orizzontale (usando i valori dell’accelerometro per assicurare di essere
nell’esatto quadrante, ad esempio se il Wiimote fosse sottosopra). Si può probabilmente
applicare almeno un filtro di base di movimento medio per ridurre gli scatti. Una volta
mappata la Sensor Bar in un sistema di coordinate orizzontali, si può semplicemente
calcolare la posizione intermedia tra i due punti e usarla per calcolare la posizione del
13
puntatore definendo un quadro per mappare lo schermo su di esso. La posizione di questo
quadro può variare a seconda del luogo di posizionamento della Sensor Bar (sopra o sotto
lo schermo). Il quadro dovrebbe essere proporzionatamente dimensionato in modo da
accomodare più angoli senza aree morte. Una posizione di puntamento approssimata può
essere calcolata mediante l’uso delle seguenti formule:
Rotation = Math.Atan2(Accelerometer.Z, Accelerometer.X) - (float)(Math.PI / 2.0);
Position = (1 - Midpoint.x, Midpoint.y);
Position.Subtract(0.5,0.5);
Position.Rotate(Rotation);
Position.Add(0.5,0.5)
Se il punto intermedio non fosse disponibile si può usare il punto rimanente e comparare la
sua posizione corrente con la sua posizione quando entrambi i punti erano visibili.
3.3.4
Levigatura del cursore
La conversione dei dati rilevati dal ricevitore IR in informazioni per il posizionamento di
un cursore nello schermo consente a diverse applicazioni di sfruttare la tecnica di
puntamento nel loro funzionamento. Questa tecnica risulta particolarmente vantaggiosa nei
menu e nelle GUI; per queste applicazioni sarebbe auspicabile un filtraggio della posizione
del cursore. Una strategia per questo scopo è l’implementazione di uno schema circolare
trascinabile; Il software disegna un cerchio immaginario attorno alla nuova posizione
puntata; se il cursore si sposta al di fuori del cerchio, viene immediatamente trascinato al
suo interno. In ogni caso, se il cursore si trova già all’interno del cerchio, si muoverà in
direzione del centro ad una velocità proporzionale alla distanza dal centro. Questa tecnica
“leviga” il movimento del cursore e fa si che alcune piccole vibrazioni fisiche non
muovano drasticamente il cursore, consentendo comunque piccole correzioni.
Un’altra opzione è un algoritmo che corregge più attentamente la posizione quando il
Wiimote si muove lentamente e dà maggiore tolleranza in corrispondenza di movimenti
veloci. L’aspetto complesso di questo metodo sta nella difficoltà di apporto di piccole
correzioni quando il telecomando viene mosso di pochi pixel.
14
3.4 Altre funzionalità
3.4.1
LED
Sul lato frontale del Wiimote sono presenti quattro LED azzurri. Durante la modalità di
rilevazione e prima dell’inizializzazione, questi LED lampeggiano assieme. Il numero dei
LED che lampeggiano è proporzionale alla tensione sulla batteria, e indica la carica delle
pile (tutti e quattro indicano batterie completamente cariche, e un led soltanto indica che le
batterie stanno per esaurirsi e andrebbero sostituite). Il Wiimote è alimentato da due pile di
tipo AA. Quando il Wiimote è sincronizzato alla console, uno dei LED è acceso e indica il
numero giocatore assegnato dalla console al telecomando (fino a quattro giocatori). I LED
sono comunque indipendentemente controllabili dall’host, e possono essere accesi o spenti
a piacimento dal software. I LED possono anche essere modulati ad una comunque
moderata alta frequenza, abilitando un controllo di luminosità occupando però parecchia
banda Bluetooth. I LED sono montati sulla parte superiore del circuito, alimentati a 2.66 V
DC.
3.4.2
Rumble
Il Wiimote include una funzionalità di vibrazione, la cui implementazione consiste in un
piccolo motore unito a un peso decentrato (Rumble Pack). Il motore può essere attivato o
fermato attraverso un Output Report. Non tutti i Wiimote montano lo stesso motore; uno di
questi è il SEM 8728DA, alimentato a 3.3 V DC e a 35 mA.
3.4.3
Speaker
Il telecomando contiene un piccolo altoparlante di 21 mm piezo-elettrico di bassa qualità,
usato per brevi effetti sonori durante il gioco. I suoni provengono direttamente dall’host e
lo speaker ha qualche parametro regolabile. L’altoparlante è controllato tramite tre Output
Report assieme a una sezione del registro indirizzi del Wiimote.
15
3.5 Estensioni
Il Wiimote dispone di un connettore d’espansione a 6 pin che consente di connettervi
periferiche esterne. La comunicazione è bi-direzionale seriale e sincrona (il protocollo è
sconosciuto); le estensioni forniscono un blocco virtuale di registro mappato in una
porzione dello spazio indirizzi del Wiimote; la comunicazione è crittografata. I dispositivi
qui elencati sono tutte estensioni del Wiimote ad esso connesse tramite il connettore di cui
sopra, fatta eccezione per la Balance Board che comunica direttamente con l’host via
Bluetooth.
3.5.1
Nunchuk
È un telecomando di forma ovoidale leggermente più piccolo del Wiimote, dotato di un
accelerometro a tre assi simile a quello del Wiimote, di un joystick analogico, due pulsanti
dorsali (C e Z) e un microcontroller. La posizione centrale del joystick viene calibrata al
collegamento del Nunchuk al Wiimote, con un meccanismo finora sconosciuto. I due
potenziometri (30KΩ) che controllano gli assi del joystick sono collegati in parallelo. Il
chip di controllo dell’accelerometro è il LIS3L02 di STMicroelectronics.
Figura 4: Nunchuk collegato al Wiimote
16
3.5.2
Classic Controller
È un controller tradizionale, utilizzabile come seconda scelta in giochi che lo supportano; è
provvisto di 15 pulsanti, due dei quali sono trigger analogici e forniscono sia lo stato di
“click” una misura della pressione ad essi impressa, e due joystick analogici.
Sul lato frontale del controller sono posizionati i joystick e 11 dei pulsanti standard: A, B, , Home, +, X, Y, Up, Down, Left, Right. Sul lato superiore si trovano i trigger e gli altri
due pulsanti: Z e L; sono posizionati in modo da essere premibili con gli indici.
I trigger (destro e sinistro) sono sensibili a forze; alla pressione di un trigger, un
meccanismo fa scorrere un potenziometro lineare da 30KΩ. Il meccanismo utilizza solo un
quarto della distanza massima percorribile dal potenziometro. Al termine di uno
spostamento derivante da una pressione viene chiuso uno switch; il trigger è considerato
premuto appieno quando viene chiuso anche lo switch in fondo al percorso del
potenziometro.
Tutti i sei potenziometri nel dispositivo (due relativi a ogni trigger e due per ognuno dei
joystick) sono collegati in parallelo.
3.5.3
Wii Motion Plus
È un accessorio che migliora le prestazioni del Wiimote rendendolo molto più preciso e
realistico. Esso permette di compiere movimenti con il telecomando che saranno mappati
1:1 dalla console; in pratica vengono recepiti tutti i movimenti 3D compiuti nello spazio,
rilevati con altissima precisione. Il dispositivo ha una propria porta d’espansione che
consente di collegarvi ad esempio un Nunchuk, permettendo così l’uso di entrambe le
estensioni.
Il Wii Motion Plus contiene due giro sensori: un giroscopio a due assi (IDG-600 di
InvenSense) per il rilevamento di Pitch e Roll, e un giroscopio monoasse (X3500W di
EPSON TOYOCOM) per il rilevamento di Yaw. L’uso combinato dei due giroscopi abilita
il dispositivo alla lettura della velocità angolare in tutti e tre gli assi, consentendo così un
orientamento completo. In Figura 2 sono rappresentati i movimenti Pitch, Roll e Yaw
rilevabili dal Wii Motion Plus.
17
3.5.4
Wii Balance Board
La Wii Balance Board è una pedana che comunica via Bluetooth direttamente con la
console. È composta da quattro bilance che rilevano lo spostamento del peso dell’utente
che si posiziona sopra di essa, permette quindi di usare gli spostamenti del corpo per
controllare le azioni di gioco. La Balance Board è effettivamente un’estensione nonostante
non la si possa collegare fisicamente al connettore del Wiimote, tuttavia è utilizzabile
anche in assenza di un Wiimote in quanto appare alla console come un Wiimote con un
“Balance Board extension controller” permanentemente connesso, e trasmette i propri dati
alla console in maniera del tutto simile ad un’estensione connessa a un Wiimote.
I dispositivi di misurazione della Balance Board sono quattro estensimetri, incorporati in
ciascuno dei piedini su cui la pedana poggia al suolo. Il principio di funzionamento di
questi sensori è la misura della resistenza elettrica di un sottile filo di metallo posto al loro
interno, che aumenta all’allungamento del filo; l’estensione del filo è proporzionale alla
sollecitazione (forza peso) che il sensore subisce.
Grazie alla disposizione dei sensori ai quattro angoli della pedana, questa periferica è in
grado di misurare l’indice di massa corporea, analizzare la posizione del baricentro e il
peso corporeo. Nella versione europea la Balance Board può sostenere fino a un peso di
150Kg. La trasmissione dei dati misurati è continua, e avviene con un rate di 60 fps.
Figura 5: Wii Balance Board
18
Capitolo 4. Interfacciamento e
connessione dei dispositivi
In questo capitolo vengono esposte le tecnologie e i meccanismi mediante i quali avviene
la connessione tra i controller di Nintendo Wii e l’host (console o pc).
4.1 HID [5]
Gli Human Interface Device (HID) sono dispositivi che interagiscono direttamente con
l’utente. Sono tipicamente dispositivi di input, ma spesso emettono anche output. Il
termine HID viene spesso associato alla specifica USB-HID, termine coniato da Mike Van
Flandern (Microsoft) quando propose al comitato USB la creazione di un gruppo di lavoro
per lo sviluppo delle tecnologie dei dispositivi di input. Il gruppo venne rinominato e
nacque la Human Interface Device class, che denota la comunicazione bi-direzionale
supportata dallo standard.
Le motivazioni principali che portarono alla nascita di HID furono l’abilitazione di
innovazioni per i dispositivi di input e la semplificazione del processo di installazione di
tali dispositivi.
4.1.1
L’innovazione di HID
Prima della nascita di HID, i dispositivi di input erano tipicamente utilizzati mediante
protocolli restrittivi per mouse, tastiere e joystick. L’innovazione dell’hardware ha
richiesto modifiche a protocolli esistenti o la creazione di driver personalizzati con
conseguente pubblicazione di nuovi protocolli per gli sviluppatori di applicazioni.
I dispositivi HID rilasciano dei pacchetti autodescrittivi che potrebbero contenere
un’infinità di tipi di dati e formati. Un singolo driver HID installato in un PC analizza i dati
e abilita l’associazione dinamica di informazioni di I/O con le funzionalità applicative.
19
Molti sistemi operativi possono riconoscere dispositivi USB-HID, come mouse o tastiere,
anche senza l’utilizzo di un driver, e in questo caso un dispositivo viene riconosciuto come
“HID-compliant device”.
4.1.2
Il protocollo HID
Il protocollo HID si compone di due entità: l’host e il device. Il device è l’entità che
interagisce direttamente con l’utente, mentre l’host comunica con il device ricevendo (o
trasmettendo) dati in risposta ad azioni compiute dall’utente. Gli host sono tipicamente pc,
ma possono anche essere telefoni cellulari, PDA e console.
Il protocollo HID traduce l’implementazione dei dispositivi in modelli molto semplici. I
dispositivi definiscono un proprio pacchetto dati e quindi presentano all’host un “HID
descriptor”, che contiene la descrizione del contenuto del pacchetto dati. Le informazioni
contenute nel descrittore sono: il numero di pacchetti supportati dal dispositivo, lo spazio
occupato da ogni pacchetto e il significato di ciascun byte nel pacchetto. Tipicamente
l’HID descriptor è memorizzato in una ROM all’interno del dispositivo.
L’host è un’entità molto più complessa del device. Ad esso spetta il compito di ricevere
l’HID descriptor dal device ed analizzarlo allo scopo finale di comunicare in modo
pienamente funzionale con il device.
4.1.3
Bluetooth HID
Il Bluetooth HID è una versione derivante dal protocollo HID definito per USB, alleggerita
e adattata alla tecnologia della trasmissione Bluetooth. Questo permette il riutilizzo di
alcune delle già esistenti funzionalità per USB-HID per il supporto di Bluetooth HID.
Il profilo HID descrive il modo in cui utilizzare il protocollo USB-HID per rilevare una
classe di driver USB-HID preesistente, dalla quale estrarre un set di funzionalità della
classe HID del dispositivo; il profilo descrive inoltre come un dispositivo Bluetooth
supporta servizi HID che sfruttano il livello L2CAP. Il profilo HID è progettato al fine di
abilitare, inizializzare e controllare dispositivi auto-descriventi e di fornire una connessione
a bassa latenza con bassi requisiti di alimentazione.
20
Il Wiimote e la Balance Board usano entrambi allo stesso modo il protocollo Bluetooth
HID standard per comunicare con l’host, quello che cambia è l’identificativo con cui
vengono individuati e associati all’host: il Wiimote viene riconosciuto come “Nintendo
RVL-CNT-01”, mentre la Balance Board come “Nintendo RVL-WBC-01”.
4.2 Bluetooth [6]
Il Wiimote si interfaccia alla console mediante la tecnologia Bluetooth, grazie a un
dispositivo BCM2042 di Broadcom. Il Wiimote e la Balance Board utilizzano il protocollo
HID Bluetooth standard per comunicare con l’host, direttamente basato sull’USB HID
standard. Grazie a questa caratteristica essi possono essere rilevati come dispositivi di
input standard da un qualunque host Bluetooth, quale ad esempio un pc dotato di scheda di
rete Bluetooth o di un adattatore USB (una chiavetta Bluetooth). Viene quindi introdotta la
possibilità di utilizzare il Wiimote e la Balance Board come dispositivi di input per
applicazioni per pc, svincolandosi così da un loro uso esclusivo con la console Wii.
4.2.1
BlueSoleil [7]
I primi tentativi di connessione dei dispositivi al pc hanno esito positivo, ma mostrano una
carenza di affidabilità della connessione in quanto spesso essa si disattiva senza preavviso
e non garantisce una continuità della comunicazione tra l’host e il device. La soluzione a
questo problema è stata raggiunta con la sostituzione del software standard del sistema
operativo che gestisce la rete e i dispositivi Bluetooth con un software avanzato e provvisto
di migliori funzionalità.
Questo software è BlueSoleil di IVT; è un’applicazione che consente a pc abilitati
Bluetooth di collegarsi ad altre periferiche abilitate Bluetooth, ma anche di creare reti e
scambiare dati tra dispositivi.
21
Figura 6: IVT Bluesoleil
Funzione Bluetooth (Profilo)
Client
Server
Advanced Audio Bluetooth
√
√
√
Auricolare e microfono Bluetooth
Connessione remota Bluetooth
√
FAX Bluetooth
√
Trasferimento file Bluetooth
√
Periferica d'interfaccia umana (HID) Bluetooth
√
OPP (Object Push) Bluetooth
√
√
PAN (Personal Area Network) Bluetooth
√
√
Stampa Bluetooth
√
Porta seriale Bluetooth
√
√
√
Tabella 1: Profili Bluetooth supportati da BlueSoleil
Come illustrato in Tabella 1, BlueSoleil dispone di diverse funzionalità operative sulle reti
Bluetooth. Il software consente la gestione delle reti sia nella erogazione dei servizi
(Server) che nell’accesso a servizi (Client).
4.2.2
Connessione del Wiimote
Il Wiimote viene rilevato dal software come Bluetooth HID (Joystick), e identificato
attraverso un id univoco; Esso non richiede alcuna autenticazione o cifratura,
l’interfacciamento consiste nella pressione contemporanea dei tasti 1 e 2 o del tasto rosso
di sincronizzazione all’interno del coperchio delle batterie, che porta il Wiimote nella
22
modalità di rilevazione nella quale viene accoppiato all’host (console o pc) mediante il
driver Bluetooth-HID. A sincronizzazione avvenuta, il Wiimote dirige automaticamente i
propri pacchetti verso l’host a cui è accoppiato.
L’interfacciamento con la console Wii è automatico una volta che il Wiimote viene portato
in modalità di rilevazione, in quanto la console si accoppia automaticamente al dispositivo
e vi associa un indice da 1 a 4 (alla console si possono interfacciare fino a 4 Wiimote
contemporaneamente) che viene normalmente indicato dall’accensione di uno dei 4 led sul
dispositivo.
Per connettere il Wiimote a un pc è invece necessario anzitutto effettuare nel software
BlueSoleil una ricerca dispositivi Bluetooth: se il Wiimote si trova in modalità di
rilevazione, esso viene trovato, ma non accoppiato. Occorre mantenere il Wiimote nella
modalità di rilevazione e indicare al software di connettere l’host al dispositivo. Se
l’operazione ha esito positivo l’icona relativa al dispositivo diventa verde. In Figura 7 è
mostrata la notifica della fase di sincronizzazione del dispositivo.
Figura 7: Sincronizzazione Wiimote
Tuttavia il Wiimote è inutilizzabile dai driver standard HID in quanto non usa né la
tipologia standard di dati né lo stesso descrittore HID, ma si limita a fornire la lunghezza
del pacchetto, senza descriverne il contenuto; questo aspetto ha reso necessaria la
creazione di alcuni driver Wiimote.
Il Wiimote utilizza un set di operazioni abbastanza complesso, trasmesse tramite il canale
HID di output, e restituisce attraverso il canale di input differenti pacchetti contenenti dati
provenienti dalle sue periferiche interne.
La connessione della Balance Board avviene in modo del tutto analogo.
23
4.3 Wiimotelib
Wiimotelib è una libreria .NET sviluppata da Brian Peek [8], che consente ad una
applicazione .NET di interfacciarsi a un controller Wiimote e alle varie estensioni esistenti.
Diverse versioni di questa libreria sono disponibili su CodePlex [9]. Gli algoritmi mediante
i quali la libreria abilita la comunicazione con il dispositivo sono descritti nei paragrafi
seguenti [10].
4.3.1
Creazione del canale di comunicazione
Quando il Wiimote e la Balance Board vengono sincronizzati con il pc, sono identificati
come HID-compliant devices, ma i loro pacchetti non sono decodificabili. Pertanto, per
connettersi funzionalmente ai dispositivi, occorre utilizzare le API di Win32 per la
gestione dei dispositivi HID; queste API sono definite nel Windows Driver Kit (WDK).
Non essendo disponibile in .NET un supporto integrato per tali API, diventa necessaria
l’introduzione di uno strumento che permetta di chiamare direttamente i metodi delle API
da .NET: questo strumento è P/Invoke. La difficoltà di questo passaggio consiste nella
ricerca della corretta signature per ogni metodo e le definizioni delle strutture che
introducono propriamente i dati attraverso Win32. Wiimotelib è scritta in C#, e i metodi
inerenti P/Invoke sono contenuti nella classe HIDImports.
Il processo attraverso il quale la libreria apre la comunicazione con il Wiimote (o con la
Balance Board, che come detto è considerata a tutti gli effetti un Wiimote) si compone dei
seguenti passi:
1. Trovare il GUID della classe HID definita da Windows
2. Trovare un gestore della lista di tutti i dispositivi che fanno parte di tale classe
3. Enumerare l’insieme di questi dispositivi e ottenere informazioni dettagliate
riguardo ognuno di essi
4. Comparare Vendor ID e Product ID di ognuno dei dispositivi della classe con i già
noti VID e PID del Wiimote
5. Una volta trovata la classe corrispondente, creare un FileStream per ricevere o
inviare dati al dispositivo
6. Svuotare la lista dei dispositivi
24
Viene qui riportato il codice C# che esegue i passaggi precedentemente descritti:
// read/write handle to the device
private SafeFileHandle mHandle;
// a pretty .NET stream to read/write from/to
private FileStream mStream;
bool found = false;
Guid guid;
uint index = 0;
// 1. get the GUID of the HID class
HIDImports.HidD_GetHidGuid(out guid);
// 2. get a handle to all devices that are part of the HID class
IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero,
HIDImports.DIGCF_DEVICEINTERFACE);// | HIDImports.DIGCF_PRESENT);
// create a new interface data struct and initialize its size
HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
diData.cbSize = Marshal.SizeOf(diData);
// 3. get a device interface to a single device (enumerate all devices)
while(HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index, ref diData))
{
// create a detail struct and set its size
HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new
HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
diDetail.cbSize = 5; //should be: (uint)Marshal.SizeOf(diDetail);, but that's the wrong size
UInt32 size = 0;
// get the buffer size for this device detail instance (returned in the size parameter)
HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size,
IntPtr.Zero);
// actually get the detail struct
if(HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out
size, IntPtr.Zero))
{
// open a read/write handle to our device using the DevicePath returned
mHandle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite,
FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped,
IntPtr.Zero);
// 4. create an attributes struct and initialize the size
HIDImports.HIDD_ATTRIBUTES attrib = new HIDImports.HIDD_ATTRIBUTES();
attrib.Size = Marshal.SizeOf(attrib);
// get the attributes of the current device
if(HIDImports.HidD_GetAttributes(mHandle.DangerousGetHandle(), ref attrib))
{
// if the vendor and product IDs match up
if(attrib.VendorID == VID && attrib.ProductID == PID)
{
25
// 5. create a nice .NET FileStream wrapping the handle above
mStream = new FileStream(mHandle, FileAccess.ReadWrite, REPORT_LENGTH, true);
}
else
mHandle.Close();
}
}
// move to the next device
index++;
}
// 6. clean up our list
HIDImports.SetupDiDestroyDeviceInfoList(hDevInfo);
4.3.2
Trasmissione dei pacchetti
Nel mondo di HID, i dati vengono trasmessi sotto forma di report, sono cioè blocchi di dati
di lunghezza predefinita e fissa con un header che descrive il report contenuto nel blocco.
Il Wiimote trasmette e riceve vari report, ognuno dei quali ha una lunghezza di 22 byte.
Una volta creato il FileStream su cui comunicare con il Wiimote, è possibile aprire la
trasmissione dei dati. Poiché i report saranno trasmessi e ricevuti quasi sempre in modo
continuo, è essenziale l’uso di operazioni di I/O asincrone; in .NET questo è
particolarmente semplice. Il processo consiste nell’avviare un’operazione asincrona di
lettura e fornire un metodo di risposta quando il buffer si riempie; terminato il metodo di
risposta, i dati sono stati manipolati e il processo può essere ripetuto.
// report length
private const int REPORT_LENGTH = 22;
// report buffer
private byte[] mBuff = new byte[REPORT_LENGTH];
private void BeginAsyncRead()
{
// if the stream is valid and ready
if(mStream.CanRead)
{
// create a read buffer of the report size
byte[] buff = new byte[REPORT_LENGTH];
// setup the read and the callback
mStream.BeginRead(buff, 0, REPORT_LENGTH, new AsyncCallback(OnReadData), buff);
}
}
private void OnReadData(IAsyncResult ar)
{
26
// grab the byte buffer
byte[] buff = (byte[])ar.AsyncState;
// end the current read
mStream.EndRead(ar);
// start reading again
BeginAsyncRead();
// handle data....
}
Questo è il codice sufficiente ad aprire e avviare la comunicazione con il Wiimote. Il resto
del codice comporta l’analisi dei dati ricevuti dal dispositivo e l’invio di dati
adeguatamente formati al Wiimote. Si può inviare un qualunque comando al Wiimote
attraverso il seguente codice:
mStream.Write(mBuff, 0, REPORT_LENGTH);
27
Capitolo 5. Ambiente di Sviluppo
L’ambiente di sviluppo dell’applicazione è XNA Game Studio 3.1, estensione di Microsoft
Visual Studio. Il linguaggio di programmazione utilizzato è C#.
È stato possibile utilizzare l’edizione 2008 Professional di Visual Studio grazie alla licenza
studenti per il Politecnico di Milano distribuita dall’MSDN Academic Alliance [11].
5.1 Microsoft Visual Studio 2008 [12]
È un IDE (Integrated Development Environment) di Microsoft, con nome in codice Orcas,
ed è uno strumento rivolto a sviluppatori di piattaforme Windows e .NET Framework 3.
Incorpora svariati linguaggi di programmazione tra i quali VB.NET, C#, C++ e altri
ancora. Offre inoltre la possibilità di creare applicazioni e servizi Web ASP.NET. Visual
Studio 2008 richiede il .NET Framework 3.5 che è stato rilasciato assieme all’IDE il 19
Novembre 2007, e per default compila su tale framework le applicazioni ma supporta
anche la compilazioni degli assembly nelle versioni precedenti del framework. Il debugger
di Visual Studio include funzionalità che semplificano il debug di applicazioni multithread.
5.2 C# [13]
C# (C Sharp) è un linguaggio di programmazione Object-Oriented sviluppato da Microsoft
all’interno dell’iniziativa .NET, e successivamente approvato come standard ECMA
(associazione attualmente responsabile per molti standard).
La sintassi del codice C# prende spunto da Delphi [14] (del medesimo autore, Anders
Hejlsberg), da C++, da Java e Visual Basic per gli strumenti di programmazione visuale e
per la semplicità.
C# è il linguaggio che meglio descrive le linee guida del funzionamento di un’applicazione
.NET; i suoi tipi di dati primitivi hanno una corrispondenza univoca con i tipi .NET e
molte delle sue astrazioni come classi, interfacce, delegati ed eccezioni sono
particolarmente adatte a gestire il .NET Framework.
28
5.3 Il Framework XNA [15]
Microsoft XNA (Xna is Not Acronymed) è un insieme di strumenti per la progettazione, lo
sviluppo e la gestione di software per videogiochi contraddistinto dalla semplicità del
processo di creazione, poiché evita al programmatore l’inserimento di parti inutili di codice
e consente l’appoggio a un framework unificato, che contiene tutti i set di istruzioni utili
per un videogame. XNA attualmente comprende l’intera sezione di sviluppo videogiochi di
Microsoft, incluso lo standard Xbox Development Kit.
Il Framework XNA è basato sul .NET Framework 2.0 per Windows e sul .NET Compact
Framework 2.0 per Xbox 360, pertanto è virtualmente supportato da tutti i linguaggi .NET,
anche se è consigliato l’uso di C#. Esso appoggia sulle librerie grafiche di Microsoft
DirectX e incapsula tutti i dettagli di basso livello riguardanti lo sviluppo del videogioco,
risparmiando questo compito allo sviluppatore che può concentrarsi sul contenuto e
sull’esperienza di gioco in quanto sarà il framework a gestire le varie piattaforme di gioco;
sono inoltre presenti numerosi strumenti per la creazione di contenuti, come editor di
suono, visuali e di modelli.
Microsoft ha rilasciato degli IDE specifici per il game design (XNA Game Studio), che si
possono installare come estensione dell’IDE principale (Visual Studio), così come il
Framework XNA viene installato come estensione del .NET Framework.
5.4 Struttura di un progetto XNA [16]
La colonna portante di un progetto XNA è una classe di tipo Game. Questa classe è
implementata alla creazione di ogni progetto XNA e gestisce l’intera applicazione
attraverso dei metodi predefiniti.
In un progetto XNA è possibile separare le varie parti dell’applicazione mediante l’uso di
vari GameComponents, ciascuno dei quali possiede metodi predefiniti ereditabili dalla
classe Game.
29
5.4.1
Metodi predefiniti
Ad ognuno dei metodi predefiniti per le classi XNA è assegnata una particolare mansione.
Ogni metodo contiene il codice opportuno per eseguire tale compito. I metodi sono i
seguenti:
• Costruttore: chiamato al momento dell’istanziazione della classe
• Initialize: chiamato dopo l’istanziazione della classe e usato per inizializzare gli
attributi della classe
• Update: viene invocato a runtime sessanta volte al secondo; contiene il codice che
aggiorna la logica e i dati del componente
• Draw: contiene il codice che gestisce la grafica di gioco e il rendering di oggetti 2D
(Textures), oggetti 3D o effetti sullo schermo; viene chiamato per default alla stessa
frequenza di refresh dello schermo
• LoadContent: contiene il codice che gestisce il caricamento dati (immagini,
modelli, audio) dall’hard disk; XNA gestisce e ottimizza il caricamento attraverso il
Content Pipeline ottenendo così maggiore flessibilità
• UnloadContent: viene chiamato prima della terminazione dell’applicazione e
contiene il codice inerente la disposizione o la rimozione dei dati prima di
effettuare l’uscita dal gioco
5.4.2
Componenti
Il framework XNA fornisce dei componenti specifici che vengono usati per distribuire il
codice relativo a diverse mansioni su più componenti semplificando perciò la struttura di
ogni porzione di codice.
Per utilizzare un componente nell’applicazione occorre crearne un’istanza nella classe
principale Game, inizializzarla e aggiungere il componente alla Component List della
classe Game.
I componenti usati sono di tipo GameComponent e DrawableGameComponent; entrambi
consentono la manipolazione e gestione della logica di gioco per mezzo dei metodi sopra
citati, ma differiscono tra loro in quanto i GameComponent non dispongono di metodi e
proprietà relativi alla gestione della grafica e pertanto non è possibile gestire e visualizzare
30
oggetti grafici in tali componenti. Solo i componenti di tipo Drawable dispongono del
metodo Draw.
Le proprietà più importanti dei componenti sono:
• Enabled: indica se il componente è attivo
• Visible (solo per DrawableGameComponent): indica se il componente è
visualizzato sullo schermo
5.4.3
Grafica 2D
Il framework XNA fornisce alcune funzionalità che consentono la visualizzazione di
immagini per mezzo della classe SpriteBatch. Questa classe è stata ideata ponendo come
priorità la facilità d’uso, ma possiede comunque notevoli potenzialità, tra cui differenti
ottimizzazioni delle immagini. Nella programmazione grafica le immagini visualizzate su
schermo vengono chiamate Sprite, mentre le immagini importate nelle applicazioni e poi
successivamente rese accessibili al codice sono chiamate Texture. In un progetto di XNA
Game Studio è possibile importare delle Texture e renderle accessibili al codice per mezzo
di un asset, che costituisce il riferimento all’immagine memorizzata su disco. Nel codice
esse possono essere inserite in una Sprite e visualizzate su schermo.
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D myTexture;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent()
{
myTexture = Content.Load<Texture2D>("image");
}
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.Draw(myTexture, new Vector2(0, 0), Color.White);
spriteBatch.End();
}
}
31
5.5 Audio
XNA gestisce i suoni nello stesso modo in cui si occupa della grafica, attraverso il Content
Pipeline. Differentemente dai contenuti grafici, ai quali è possibile un accesso diretto, i
contenuti audio necessitano di essere importati in un particolare formato, generato dal un
tool audio: XACT.
5.5.1
XACT
XACT è un Cross-Platform Audio Creation Tool di Microsoft; viene utilizzato per creare
un progetto contenente delle Sound Banks e Wave Banks. La compilazione del progetto
produce tre file, che l’applicazione XNA può ricevere attraverso il Content Manager.
Il processo consiste nella creazione di un progetto XACT, nel quale occorre creare una
Wave Bank all’interno della quale inserire le diverse sorgenti audio (file WAV) che si
vogliono utilizzare dall’applicazione; a questo punto bisogna creare una Sound Bank e
trascinarvi le tracce audio precedentemente inserite nella Wave Bank; i nomi dei file audio
vengono così aggiunti come contenuti della Sound List e Cue List nella Sound Bank. A
questo punto si deve compilare il progetto XACT; il risultato della compilazione sono tre
file (.xgs, .xwb e .xsb) che verranno poi importati nel progetto XNA e letti da una classe
specifica.
5.5.2
Classe statica Audio
Per rendere possibile la riproduzione di audio nell’applicazione XNA, è stata creata
all’interno del progetto una classe statica che fornisce dei metodi specifici per la
riproduzione di determinati suoni. I file audio da riprodurre non devono essere importati
all’interno del progetto poiché grazie alla compilazione del progetto XACT sono ora
contenuti nella Wave Bank; è invece necessario includere nel progetto il file .xap generato
dal salvataggio del progetto XACT.
32
La classe creata fa uso dei seguenti tre oggetti, indispensabili per la gestione del contenuto
audio:
• AudioEngine: costituisce il riferimento ai servizi audio del pc, ed è usato
principalmente come parametro per la creazione delle Wave e Sound Banks. La
creazione dell’AudioEngine richiede il file (.xgs) che descrive le impostazioni
globali del contenuto del progetto XACT, generato dalla compilazione del progetto
stesso
• WaveBank: è una collezione di file wave; la sua creazione richiede la previa
creazione dell’AudioEngine e il file (.xwb) generato alla compilazione del progetto
XACT. La WaveBank non viene esplicitamente utilizzata dal programma, ma è
necessaria in quanto le Cue nella SoundBank dipendono dai file wave contenuti
nella WaveBank
• SoundBank: è una collezione di Cue, definite come riferimenti ai file wave
memorizzati nella WaveBank congiunti a proprietà che dettagliano le modalità e i
metodi che permettono la riproduzione dei file
public static class Audio
{
private static AudioEngine engine;
private static WaveBank waveBank;
private static SoundBank soundBank;
private static Cue noteCue, musicCue;
public static Cue Play(string name)
{
Cue cue = soundBank.GetCue(name);
cue.Play();
noteCue = cue;
return cue;
}
public static void Stop(Cue cue)
{
cue.Stop(AudioStopOptions.Immediate);
}
public static void Initialize()
{
engine = new AudioEngine("Content/Sounds/Sounds.xgs");
waveBank = new WaveBank(engine, "Content/Sounds/Waves.xwb");
soundBank = new SoundBank(engine, "Content/Sounds/Sounds.xsb");
}
public static void Update()
{
engine.Update();
}
public static void ShutDown()
{
soundBank.Dispose();
waveBank.Dispose();
engine.Dispose();
}
}
33
La creazione dei riferimenti all’audio del progetto XACT tramite l’istanziazione degli
oggetti sopra descritti avviene all’interno del metodo Initialize, che deve essere chiamato
prima dell’uso di qualunque altro metodo. Una volta eseguita l’inizializzazione dei
componenti audio, è possibile riprodurre una qualunque traccia audio invocando il metodo
Play passandogli come parametro il nome del suono da riprodurre.
Durante l’esecuzione dell’applicazione è inoltre necessario aggiornare lo stato
dell’AudioEngine, semplicemente richiamando il metodo Update della classe Audio
all’interno della Update delle classi del progetto.
5.6 Requisiti di piattaforma
La distribuzione di un progetto XNA su piattaforme differenti da quella sulla quale è stato
sviluppato richiede l’installazione del framework XNA e del .NET Framework 3.5, in
quanto in assenza di tali framework le applicazioni non sono eseguibili e generano degli
errori. Grazie alla compatibilità di XNA con la tecnologia ClickOnce di Visual Studio, è
possibile far si che l’installer dell’applicazione XNA controlli la presenza di tali pacchetti
sulla piattaforma e, in caso di esito negativo della ricerca, ne richieda l’installazione.
Entrambi i pacchetti sono scaricabili sui siti di Microsoft.
34
Capitolo 6. Ideazione del software
La linea di pensiero che ha caratterizzato il concepimento dell’idea da cui nasce il software
è legata all’elevata accessibilità all’applicazione, essenziale per l’uso da parte di utenti
paraplegici, quanto al mantenimento di un buon livello di intrattenimento e divertimento,
che possa stimolare l’utente a cimentarsi nelle attività previste dai moduli del software.
6.1 Specifiche del software
Si è pensato di realizzare un’applicazione in un dominio musicale, introducendo di
conseguenza una componente audio nel progetto, che nell’ambito dell’intrattenimento aiuta
notevolmente l’utente a confortarsi durante la fase di gioco.
Lo studio delle caratteristiche tecniche e delle modalità d’uso del Wiimote (e del Nunchuk)
e della Balance Board ha portato alla decisione di implementare una batteria virtuale,
emulando il suono di un set di percussioni [17] appartenenti ad una vera batteria musicale
[18] attraverso lo scuotimento del Wiimote e del Nunchuk in sostituzione delle vere
bacchette; inoltre, per mezzo della Balance Board, su cui l’utente è seduto, viene effettuato
un controllo del baricentro dell’utente stesso, in modo che durante l’esperienza di gioco
non pieghi in modo scorretto il busto assumendo una postura errata. Il modello virtuale
della batteria è decisamente semplificato rispetto alla struttura dello strumento reale, in
quanto si è reso necessario ridimensionare la complessità dello strumento adattandolo alle
caratteristiche del contesto applicativo e della principale destinazione d’utenza per la quale
il software è concepito. Allo stesso tempo si è cercato di mantenere un moderato livello di
astrazione per inferire un carattere il più reale possibile, seppur semplice, alla batteria
virtuale.
6.1.1
Design della batteria
La progettazione della struttura della batteria è avvenuta in riferimento alla gamma di
movimenti distinti utilizzabili per emulare il suono di ogni singola percussione, con il
vincolo di escludere l’uso dei pulsanti dei telecomandi, correlando il suono di una
35
particolare percussione unicamente a uno specifico movimento di un telecomando. Questo
dettaglio è fondamentale ai fini di un uso terapeutico del software in quanto questa
soluzione consente ad un utente reduce da traumi di usare i telecomandi senza impugnarli
ma eventualmente mantenendoli congiunti ad un supporto vincolato a ogni braccio. In ogni
caso l’implementazione della sezione di menu e configurazione del videogame la rende
completamente navigabile sia attraverso la pressione dei tasti del Wiimote o del Nunchuk
sia con la tastiera del pc, consentendo così ad un qualsiasi utente la possibilità di
modificare le opzioni di gioco anche a distanza dal pc, mentre nel caso di un utente
paraplegico è possibile che un assistente applichi modifiche alle opzioni dal pc senza
interferire con l’utente che può invece governare solo la fase di gioco muovendo le braccia
e di conseguenza i telecomandi, senza che debba per forza impugnarli per premere
pulsanti.
6.1.2
Criteri di movimento
I vincoli tecnici posti dalla specifica del software hanno comportato una riduzione del
numero di percussioni di cui si compone la batteria virtuale, fino ad ottenerne soltanto sei,
di cui tre suonabili scuotendo il Wiimote e tre scuotendo il Nunchuk. Questa soluzione è
derivata da una ricerca delle tecniche verosimili con cui simulare il suono delle
percussioni, cioè da una discriminazione dei gesti compiuti dall’utente in relazione alla
praticabilità di tali movimenti e al corretto funzionamento del software in risposta al
compimento di tali gesti.
La prima configurazione presa in considerazione prevede l’uso della Sensor Bar come
riferimento per il puntamento del telecomando. Si divide così lo spazio in vari settori a
seconda dell’angolo di puntamento del Wiimote verso la Sensor Bar, associando ad ogni
settore una singola percussione. Tuttavia questa soluzione non garantisce una separazione
netta dei settori virtuali relativi a ogni singola percussione, data la ristrettezza del campo di
puntamento e l’incompatibilità tra il puntamento e il movimento del telecomando, in
quanto spesso l’azione di suono di una percussione attraverso lo scuotimento del Wiimote
porta anche ad un’indesiderata variazione di settore e quindi di percussione. Inoltre questa
tecnica impone un utilizzo differente del Wiimote da quello previsto per il Nunchuk,
poiché quest’ultimo non è provvisto di ricevitore infrarosso e pertanto non è possibile
definire uno spazio di puntamento per tale dispositivo.
36
Vista quindi l’impraticabilità della soluzione precedente, dovuta all’impossibilità di
suddividere lo spazio in settori ad ognuno dei quali associare un preciso strumento, si è
scelta una strada alternativa, questa volta subordinata a una discriminazione del tipo di
movimento effettuato con i telecomandi. Sono stati individuati e descritti quindi tre
movimenti distinti compibili da un singolo dispositivo; l’uso annesso del Nunchuk e del
Wiimote permette di suonare anche due percussioni contemporaneamente, compiendo un
gesto con ciascun dispositivo. Si ottiene così un totale di sei strumenti, che vanno a
comporre la batteria virtuale.
Ad ognuno dei telecomandi sono associate tre percussioni, ognuna delle quali suonabile
mediante l’esecuzione di uno dei tre gesti possibili. Tra i gesti previsti, vi è lo scuotimento
classico dall’alto verso il basso del telecomando, tenendolo in posizione frontale; gli altri
due gesti sono sempre degli scuotimenti dall’alto verso il basso, ma prevedono
l’inclinazione del telecomando verso destra o sinistra durante la fase finale dello
scuotimento, e cioè una rotazione del dispositivo dalla posizione frontale fino a percorrere
un angolo retto (a destra o a sinistra) durante il movimento verso il basso del telecomando.
In Figura 8 è illustrato uno schema dei movimenti predefiniti per il Wiimote per il suono di
una percussione.
Il dispositivo distingue tre diversi tipi di accelerazione ad esso impressa dall’utente:
un’accelerazione sull’asse Z positiva nel movimento frontale, e un’accelerazione sull’asse
X negativa (o positiva) nel movimento verso sinistra (o destra). L’uso esclusivo dei dati
dell’accelerometro permette di controllare in egual modo i movimenti del Wiimote e quelli
del Nunchuk. L’algoritmo di riconoscimento dell’esecuzione di un movimento
corrispondente al suono di uno strumento consiste in:
• uso di un buffer per ognuno dei quattro assi in movimento (assi X e Z di Wiimote e
Nunchuk) al fine di emulare il gesto reale di suono di una percussione: il buffer
emula l’effetto di ritorno della bacchetta una volta colpita la percussione;
in
assenza di tale buffer un singolo movimento verso il basso manderebbe in loop
l’applicazione come se la bacchetta colpisse ripetutamente la percussione
• valutazione dell’accelerazione impressa agli assi e conseguente rilevazione del
movimento eseguito se l’accelerazione supera una soglia predefinita
37
Segue il codice che gestisce questo controllo per il movimento frontale del Wiimote:
if (wiimoteForwardTriggerBuffer > -1) wiimoteForwardTriggerBuffer -= 1;
wiimoteAxisZ = wiimote.GetState().PositionalState.Z;
if (wiimoteForwardTriggerBuffer < 0 && wiimoteAxisZ > 2.5)
{
//Movimento frontale del Wiimote riconosciuto
wiimoteForwardTriggerBuffer = 0;
}
I movimenti sono stati denominati appositamente per semplificarne il riconoscimento:
ognuno dei tre gesti è eseguibile sia con il Wiimote che con il Nunchuk. L’uso corretto dei
telecomandi nel gioco prevede l’impugnatura del Wiimote nella mano destra e del
Nunchuk nella mano sinistra; è possibile suonare due strumenti contemporaneamente, ma
poiché l’associazione tra le percussioni e i movimenti relativi è statica e predefinita, non è
possibile suonare contemporaneamente due strumenti entrambi associati al Wiimote o al
Nunchuk, ma soltanto uno strumento per ogni telecomando. La denominazione dei gesti
compibili dall’utente è: WiimoteLeft, WiimoteForward, WiimoteRight, NunchukLeft,
NunchukForward, NunchkRight.
Figura 8: Visuale dei movimenti del Wiimote corrispondenti al suono delle percussioni
Da sinistra: WiimoteLeft, WiimoteForward, WiimoteRight
38
6.1.3
Composizione e disegno della batteria
Una volta distinti i gesti relativi al suono di ogni singolo strumento, si è passati alla
composizione della struttura della batteria e all’associazione del suono di ogni strumento al
movimento corrispondente.
Si sono scelte, tra le sei percussioni che compongono la batteria, quattro membranofoni
(tamburi) e due piatti (cymbals). In questa batteria non è presente la grancassa poiché non è
previsto l’utilizzo di pedali o comunque degli arti inferiori; per lo stesso motivo, l’HiHat è
modellizzato diversamente dal suo equivalente reale, in quanto è suonabile con la
bacchetta come un normale piatto anziché tramite pedale.
In particolare gli strumenti della batteria virtuale sono i seguenti:
• Tamburi: Low Tom, Mid Tom, Floor Tom (Timpano), Snare Drum (Rullante);
• Piatti: Crash Cymbal, HiHat (Charleston)
I campioni dei suoni relativi ad ognuna delle percussioni sono stati prelevati da Freesound
[19].
La mappatura ed il disegno degli strumenti non è perfetta in quanto l’obiettivo primario era
quello di derivare dalla batteria reale un modello il più semplice possibile, anche se meno
dettagliato. Per rendere graficamente realistica la batteria è stata inserita anche la
grancassa, che ricopre però esclusivamente un ruolo decorativo nella struttura della
batteria.
Figura 9: Batteria Virtuale.
Da sinistra a destra: Crash, LowTom, MidTom, FloorTom, Snare, HiHat
39
Scelti gli strumenti che compongono la batteria virtuale, si è creata l’associazione tra ogni
strumento e il movimento da compiere per suonarlo. La disposizione degli strumenti nella
grafica di gioco è strettamente correlata all’associazione del suono delle percussioni con i
movimenti relativi, e favorisce l’ambientamento sul modello virtuale facilitando
graficamente l’individuazione dello strumento da suonare. Inoltre, al suono di uno
strumento con il Wiimote (o con il Nunchuk), il software lancia una routine che dispone
nell’interfaccia visuale del gioco una figura del Wiimote (o del Nunchuk) in
sovrapposizione all’immagine della percussione suonata, aiutando così l’utente ad
associare i movimenti ai suoni correttamente.
Movimenti
Left
Forward
Right
Nunchuk
Crash
LowTom
MidTom
Wiimote
FloorTom
Snare
HiHat
Tabella 2: Associazione tra movimenti e percussioni
6.1.4
Determinazione e controllo della posizione del
centro di massa
Dopo aver ideato la batteria e le associazioni tra movimento del Wiimote e suono della
relativa percussione, si è passati all’implementazione del controllo di postura tramite la
Balance Board.
Per concepire questa parte del progetto si è utilizzato un lavoro precedente incentrato sullo
studio del centro di massa di una persona in posizione seduta e sul suo calcolo sfruttando la
tecnologia della Balance Board.
Il centro di massa (comunemente detto baricentro) di un corpo generico è il punto intorno
al quale la massa del corpo è equamente distribuita. Se per un corpo con densità uniforme
il centro di massa coincide con il centro geometrico, questo non vale invece per il corpo
umano, in quanto la distribuzione della massa varia continuamente con il variare della
postura. Data la complessità del problema, è stato necessario prendere spunto da questo
studio, limitandosi alla scrittura del codice che gestisse la rilevazione del baricentro
dell’utente seduto sulla Balance Board, in modo da controllarne la postura per evitare
piegamenti innaturali o eccessivi del busto.
40
Segue il codice che gestisce il calcolo della posizione del centro di massa dell’utente
seduto sulla Balance Board, proiettata sull’asse x della schermata di gioco (è stato
considerato solo il movimento del busto verso destra e verso sinistra, non quello in avanti o
indietro):
delta
=
((balanceBoard.GetState().BottomRight
+
balanceBoard.GetState().TopRight)
-
(balanceBoard.GetState().BottomLeft + balanceBoard.GetState().TopLeft));
peso
=
((balanceBoard.GetState().BottomRight
+
balanceBoard.GetState().TopRight)
+
(balanceBoard.GetState().BottomLeft + balanceBoard.GetState().TopLeft));
if (delta > 10)
cursorePosition.X += Math.Abs(delta * 15 / peso);
if (delta < 10)
cursorePosition.X -= Math.Abs(delta * 15 / peso);
6.1.5
Fase di gioco
Il gioco vero e proprio consiste nella riproduzione di una traccia musicale, composta da
una sequenza di percussioni da suonare; le tracce sono predefinite e variano per difficoltà
di esecuzione. La navigazione del menu consente di ascoltare e selezionare la traccia che si
vuole riprodurre, dando così un’idea preliminare del motivo da eseguire. Inoltre sono
disposti tre livelli di difficoltà che influiscono sia sulla velocità delle tracce da riprodurre,
sia sulla tolleranza di accettazione del suono di una percussione, ovvero sul tempo reso
disponibile per suonare correttamente uno strumento. Tale intervallo si riduce all’aumento
della difficoltà richiedendo così una maggiore precisione nei movimenti.
All’avvio della fase di gioco appare una schermata che visualizza uno scheletro della
batteria; in fondo alla schermata compare una barra colorata con un cursore che si muove
al suo interno, indicando la posizione del baricentro dell’utente e quanto essa sia corretta o
sbilanciata; parte poi la traccia, durante l’avanzamento della quale, quando viene raggiunto
l’intervallo utile per suonare una percussione, viene disegnato lo strumento relativo ed
evidenziato nella grafica nella sua corretta posizione. La visualizzazione dello strumento
viene interrotta nel momento in cui viene effettuato il gesto che corrisponde al suono dello
strumento stesso, oppure quando termina il tempo a disposizione per suonare la
percussione.
Il suono corretto di uno strumento fa aumentare il punteggio, mentre il suono di uno
strumento diverso da quello “attivato” ne comporta una diminuzione. Al termine della
41
riproduzione della traccia viene calcolato il punteggio sulla base del numero di suoni
corretti, al quale viene sottratta la penalità relativa ai suoni errati.
6.1.6
Modalità Free
Il software dispone inoltre di una sezione Free-Play nella quale si può suonare qualunque
strumento della batteria senza vincoli di traccia o limiti di tempo; si può quindi prendere
confidenza con i movimenti e gli strumenti, o anche creare ritmi e sequenze personalizzate.
Inoltre il software dispone di una sezione Istruzioni nella quale sono spiegate le
funzionalità del gioco e elencati i dettagli di navigazione dei menu e della fase di gioco,
compresa una spiegazione dettagliata dei movimenti da compiere per suonare ogni singola
percussione ottenendo maggiore precisione.
42
Capitolo 7. Gestione del Wiimote
con Wiimotelib
La libreria Wiimotelib è il mezzo che consente alle applicazioni la comunicazione con il
Wiimote usando .NET.
La fase iniziale del progetto è stata dedicata allo studio della corretta tecnica di
connessione al dispositivo mediante le funzioni disposte dalla libreria; in secondo luogo si
è studiato il metodo di prelievo delle informazioni dal telecomando e lo schema dati in cui
tali informazioni vengono memorizzate e rese accessibili dalla libreria. Una volta compresa
la modalità con cui accedere alle informazioni attraverso codice C#, si è implementata una
classe che fungesse da tramite fra la libreria e le classi XNA del gioco, mettendo a
disposizione di queste dei metodi in formato XNA, facendo riferimento alle classi
predefinite della sezione input del framework XNA (GamePad, Keyboard, Mouse).
7.1 La classe Wiimote
La classe Wiimote definita in Wiimotelib identifica il dispositivo. Si può aprire una
comunicazione con le periferiche Nintendo creando un’istanza di questa classe; essa
fornisce i metodi per connettere o disconnettere i dispositivi, e altri metodi che permettono
di inviare comandi al Wiimote. Questa classe dispone inoltre due eventi, indispensabili per
la lettura delle informazioni dai controller in quanto esse possono essere ricevute soltanto
attraverso l’uso di event-handler che gestiscano tali eventi. Le informazioni relative ai dati
letti dal controller vengono memorizzate nell’attributo WiimoteState.
43
7.1.1
Metodi
• Connect: crea una connessione tra l’istanza della classe Wiimote e il primo
dispositivo trovato (tra quelli sincronizzati all’host)
• Disconnect: si disconnette dal controller e sospende la lettura dei dati da esso
• ReadData: legge i dati direttamente dai registri del Wiimote
• SetLEDs: accende o spegne i quattro LED del telecomando
• SetReportType: imposta il tipo di report ricevuto dal Wiimote
• SetRumble: avvia o ferma la vibrazione
• WriteData: scrive i dati direttamente sui registri del Wiimote
7.1.2
Eventi
• WiimoteChanged: sollevato ogni volta che varia lo stato del Wiimote o
dell’estensione che vi è collegata
• WiimoteExtensionChanged: sollevato all’inserimento o rimozione di un’estensione.
7.1.3
WiimoteCollection
Nelle versioni più recenti di Wiimotelib è possibile gestire la connessione simultanea di
più dispositivi sullo stesso host. Per un uso di questo genere non è possibile l’impiego di
più oggetti Wiimote distinti, ma è necessario utilizzare un approccio diverso, cioè
impiegare la classe WiimoteCollection, definita come collezione di Wiimote, e quindi
dotata di metodi ed enumeratori per la gestione di un gruppo di elementi omogenei, ovvero
di oggetti Wiimote.
Una volta creato un oggetto di tipo WiimoteCollection, si può effettuare una ricerca di tutti
i dispositivi sincronizzati all’host mediante il metodo FindAllWiimotes, che inserisce nella
WiimoteCollection i riferimenti a tutti gli oggetti di tipo Wiimote trovati. La Collection è
così utilizzabile, mediante un indice, come un array di Wiimote e per ognuno di essi si
possono eseguire le operazioni descritte nei paragrafi precedenti.
La classe WiimoteCollection è stata indispensabile per gestire l’utilizzo contemporaneo del
Wiimote e della Balance Board.
44
7.2 Le strutture dati
I dati letti dai dispositivi vengono organizzati da Wiimotelib in una serie di struct che
definiscono ogni tipo di informazione ricevuta; ciascuna di queste strutture è adibita a
contenere i dati prelevati dai dispositivi interni al Wiimote e da ogni tipo di estensione che
vi si può collegare.
La strutture definite in Wiimotelib dipendono strettamente dall’organizzazione dei
pacchetti che il dispositivo invia all’host ogni qualvolta ne cambia lo stato; per questo
motivo esse assumono una configurazione ad albero, in quanto vi è una classe principale
(WiimoteState) che rappresenta interamente lo stato del dispositivo e di tutte le periferiche
ad esso collegate, estensioni comprese. Questa classe contiene istanze di diverse struct che
rappresentano lo stato di ognuno dei dispositivi interni al telecomando o alle estensioni;
queste struct a loro volta contengono istanze rappresentanti ognuna delle informazioni
relative a ogni singolo dispositivo interno, e così via fino ad arrivare alle foglie dell’albero
che sono valori booleani o numerici scalari (o vettoriali, ad esempio per gli assi
dell’accelerometro X, Y e Z).
La classe Wiimote descritta nel paragrafo precedente possiede un attributo di tipo
WiimoteState che, aggiornato al sollevamento dell’evento WiimoteChanged, contiene
l’intero bagaglio di informazioni relative a qualunque dispositivo o estensione collegabile
al Wiimote. Se una certa estensione non è collegata, i valori ad essa corrispondenti non
verranno aggiornati e rimarranno valori di default.
Nella pagina seguente sono elencati tutti i membri di Wiimotelib e le proprietà delle classi
Wiimote e WiimoteState. È possibile intuire la struttura ad albero dai nomi delle struct
della libreria.
45
Figura 10: Membri di Wiimotelib e delle classi Wiimote e WiimoteState
46
7.3 Eccezioni
Wiimotelib dispone di due tipi di eccezioni che consentono la gestione di situazioni
anomale:
• WiimoteNotFoundException: viene sollevata quando non vengono rilevati Wiimote
nella lista dei dispositivi HID
• WiimoteException: viene sollevata quando occorrono errori durante l’esecuzione di
funzioni della libreria
La gestione delle eccezioni risulta notevolmente vantaggiosa per risolvere situazioni
irregolari senza terminare l’applicazione, ad esempio se si tentasse di avviare
un’applicazione senza che un dispositivo sia accoppiato con l’host.
La gestione avviene mediante l’inserimento del codice in un blocco try/catch.
try
{
// Codice da eseguire in condizioni regolari
}
catch (WiimoteException ex)
{
// Codice che gestisce l’eccezione sollevata
}
7.4 Implementazione della classe WiiMote
La classe WiiMote funziona da interfaccia tra le funzionalità intrinseche della libreria
Wiimotelib e le classi di un progetto XNA; essa nasconde la struttura interna della libreria
incapsulando le sue funzionalità in un insieme di metodi in stile XNA che si rifanno alle
classi definite nella sezione del framework dedicata all’input.
La classe WiiMote si occupa internamente del prelievo dei dati dal dispositivo e della loro
memorizzazione in una serie di struct opportunamente articolate sulla struttura ad albero in
cui vengono collezionati i dati provenienti dal Wiimote, attraverso gli handler degli eventi
definiti nel paragrafo precedente.
La classe WiiMote legge i dati dal dispositivo al sollevamento degli eventi di cui sopra; il
lancio di tali eventi avviene periodicamente e ad alta frequenza, pertanto i dati letti dal
telecomando sono continuamente aggiornati. La classe rende invece i dati accessibili per
mezzo di un metodo che restituisce l’intera struttura dati memorizzata all’interno della
47
classe stessa, separando così le fasi di prelievo dei dati dal dispositivo e del loro utilizzo in
due blocchi distinti.
Inoltre la classe WiiMote dispone di metodi che effettuano la connessione o la
disconnessione tra l’applicazione e il dispositivo gestendo l’eventuale sollevamento di
eccezioni, e di altri metodi che consentono l’invio di comandi al dispositivo.
7.4.1
Metodi della classe WiiMote
• Costruttore: inizializza la classe WiiMote, istanziando implicitamente l’oggetto
Wiimote (di Wiimotelib) contenuto nella classe WiiMote, istanzia gli oggetti adibiti
a contenere i dati e sottoscrive gli eventi
• Connetti: esegue il metodo Connect della classe Wiimote di Wiimotelib gestendo
l’eventuale sollevamento di eccezioni
• Disconnetti: esegue il metodo Disconnect della classe Wiimote di Wiimotelib
• GetState: restituisce una struttura contenente tutte le informazioni prelevate dal
Wiimote e memorizzate nelle struct della classe WiiMote
• SetLeds: accende o spegne i quattro LED del telecomando
• SetRumble: avvia o ferma la vibrazione
48
Capitolo 8. Implementazione
videogame
del
La logica del videogame è stata suddivisa in diversi componenti, ognuno dei quali si
occupa di un aspetto particolare del sistema. In aggiunta alle classi che racchiudono i
componenti, ve ne sono altre che si occupano di aspetti diversi, e il cui comportamento non
rispecchia necessariamente quello dei componenti definiti sullo schema XNA, descritto nel
paragrafo 5.4.
Nome Classe
Descrizione
Classe statica i cui metodi consentono all’applicazione di
Audio
riprodurre effetti sonori (inseriti in un progetto XACT). Le
specifiche della classe Audio sono elencate al paragrafo 6.5
Classe che incapsula le funzionalità della Wiimotelib relative
BalanceBoard
alla Balance Board, utilizzate poi dall’applicazione per
comunicare con essa
DrumAble
Istruzioni
È
la
classe
principale
dell’applicazione,
gestisce
l’interoperazione tra tutti i componenti
Componente grafico che gestisce la sezione Istruzioni del
Menu
Componente standard che gestisce la logica di gioco, l’invio
Logica
di comandi per il disegno degli strumenti attivi al componente
grafico e il calcolo del punteggio di gioco
Menu
Componente grafico che gestisce il menu principale, dal quale
si può accedere a tutte le funzionalità dell’applicazione
Classe che riceve dati relativi al movimento dei telecomandi e
Percussione
riconosce i gesti corrispondenti al suono di una particolare
percussione, sollevando un evento in tale circostanza
49
Componente grafico che disegna il cursore per il controllo del
PlayScreen
busto e la batteria virtuale su schermo, evidenziandone solo
gli strumenti da suonare se si è in fase di gioco oppure l’intera
immagine se si è in modalità Free-Play
Componente standard che riproduce un’anteprima delle tracce
RiproduzioneSequenza
audio suonabili nella fase di gioco nella sezione Tracklist del
Menu
Componente grafico che permette la selezione della velocità
Speed
di gioco, accessibile dal menu principale
Classe che legge la composizione di una traccia da un file e ne
Traccia
memorizza i dati in una struttura apposita che verrà poi
utilizzata dalla logica di gioco
Tracklist
Componente grafico che consente la selezione della traccia da
riprodurre nella fase di gioco
Classe che incapsula le funzionalità di Wiimotelib in metodi
WiiMote
in stile XNA, poi utilizzati dall’applicazione per comunicare
con il Wiimote; le specifiche sono definite nel capitolo 8
Tabella 3: Classi implementate nel progetto
8.1 La classe DrumAble
La classe DrumAble dirige l’intera applicazione; gestisce la totalità dei componenti
dell’applicazione attraverso istanze delle classi corrispondenti, amministra direttamente la
comunicazione con il Wiimote e con la Balance Board e fornisce diversi metodi che
vengono chiamati dagli altri componenti per accedere ad alcune informazioni o per
eseguire dei comandi su oggetti controllati direttamente dalla classe principale.
Il software può trovarsi in diversi stati, o modalità, che vengono controllate per mezzo di
una variabile il cui valore funziona da discriminante. Ad una variazione dello stato, la
classe DrumAble si preoccupa di inizializzare i componenti attivi nella nuova modalità e di
attivarli.
50
8.1.1
Modalità di esecuzione
La specifica del software prevede che durante la fase di esecuzione, l’applicazione possa
trovarsi in una particolare modalità; ogni modalità definisce un preciso funzionamento del
programma in merito a logica di esecuzione e componenti utilizzati (attivi). Le modalità
sono le seguenti:
• Menu: schermata principale del menu
• Free Play: modalità nella quale l’utente può suonare liberamente qualsiasi
strumento della batteria
• Tracklist: sezione del menu in cui l’utente può selezionare la traccia da riprodurre
• Speed: menu di scelta della velocità di riproduzione delle tracce
• Play: rappresenta la fase di gioco; è accessibile soltanto se è stata precedentemente
selezionata una traccia
• Instructions: contiene istruzioni per l’uso dell’applicazione
• Exit: modalità di pre-uscita; vi si accede nel momento in cui l’utente decide di
terminare il programma, ed è fondamentale per la deallocazione delle istanze create
durante l’esecuzione e la corretta sequenza di operazioni da compiere prima di
terminare il processo
8.1.2
Compiti della classe DrumAble
Le mansioni della classe DrumAble vengono eseguite all’interno dei seguenti metodi
predefiniti:
• Il costruttore della classe DrumAble inizializza i vari componenti creandone le
istanze e aggiungendoli alla Component List, inizializza la grafica e il Content
Pipeline
• Nel metodo Initialize avvengono le connessioni con il Wiimote e con la Balance
Board e l’inizializzazione dell’audio; viene
impostato
lo
stato iniziale
dell’applicazione, ovvero l’accesso al menu principale
• Il metodo Update valuta continuamente lo stato dell’applicazione, e nel caso rilevi
una variazione dello stato, avvia una procedura specifica per passare nella nuova
modalità; in questo metodo avviene inoltre l’aggiornamento dell’audio
51
Vi sono altri metodi invocati alla creazione o eliminazione dei vari componenti, durante un
cambiamento di modalità o alla terminazione del programma. I dati provenienti dai
dispositivi di input vengono prelevati dalla classe DrumAble: essa fornisce ai vari
componenti soltanto una parte dei dati, strettamente necessaria al loro funzionamento;
pertanto l’accesso alle informazioni da parte dei componenti è filtrato dalla classe
principale.
8.2 I componenti della sezione menu
Vengono qui elencate le classi i cui compiti rientrano nell’ambito del menu
dell’applicazione.
8.2.1
La classe Menu
Il menu è un componente grafico che descrive la schermata principale dell’applicazione,
dalla quale sono accessibili tutte le altre funzionalità.
Questa classe non esegue operazioni particolarmente complesse; si occupa della
visualizzazione su schermo del menu principale e della selezione di una tra le varie voci
del menu, evidenziando graficamente la voce correntemente “puntata” e notificando alla
classe DrumAble il cambiamento dello stato del programma nel caso di selezione di una
delle voci.
8.2.2
La classe Istruzioni
È un componente grafico che contiene alcune schermate di introduzione al videogioco e
nelle quali vengono spiegate le funzionalità e i gesti da compiere per suonare determinate
percussioni.
8.2.3
La classe Tracklist
La classe Tracklist descrive un componente grafico all’interno del quale è possibile
selezionare, tra diverse tracce, quella da riprodurre durante la fase di gioco. Oltre a
visualizzare un elenco di tali tracce e a notificare alla classe principale un’eventuale
52
selezione di una tra queste, dispone di due metodi che abilitano la riproduzione (o la
sospensione) di un’anteprima della traccia evidenziata, operazione poi gestita dalla classe
RiproduzioneSequenza.
8.2.4
La classe Speed
Questo componente grafico rappresenta una sezione del menu in cui compaiono tre diversi
livelli di velocità e difficoltà di riproduzione delle tracce. La selezione di uno di questi
livelli provoca una notifica alla classe principale del livello scelto.
8.2.5
La classe RiproduzioneSequenza
Si tratta di un componente standard la cui logica permette di riprodurre un’anteprima
(audio) di una tra le tracce disponibili nella Tracklist. Una volta prelevati (mediante la
classe Traccia) i dati relativi alla sequenza, viene valutato, all’interno del metodo Update,
l’istante corrente e, se corrisponde all’istante in cui deve avvenire il suono di uno
strumento, viene invocato il metodo Play della classe Audio, riproducendo il suono.
8.3 Le tracce predefinite
8.3.1
La classe Traccia
Le tracce riproducibili nella fase di gioco, sono memorizzati in un file Xml con uno
schema opportuno, che consiste in un insieme di tuple <Percussione, Istante>, ordinate per
istante crescente, che rappresentano ogni suono della traccia. Della lettura di tale file e
memorizzazione in una Struct adeguata si occupa la classe Traccia, tramite un oggetto
DataSet.
All’inizializzazione di un’istanza di questa classe, nel costruttore avviene la lettura del file
Xml, e successivamente il contenuto viene memorizzato in un DataSet. Viene poi definita
una Struct che rappresenta una tupla <Percussione, Istante>, adibita a contenere una riga
della tabella definita nel file. La classe Traccia dispone di alcuni metodi che consentono di
53
prelevare una singola tupla, il numero di tuple presenti nel DataSet, o l’intera traccia
(fornita come array di tuple).
8.3.2
I DataSet
I DataSet consentono la lettura e la manipolazione di informazioni provenienti da una base
di dati, o memorizzate in un file Xml, mediante codice C#; è così possibile prelevare e
alterare grandi quantità di dati con poche e semplici istruzioni, come se si stesse operando
su una base di dati. L’oggetto DataSet rappresenta un DataBase, ed è strutturato come
segue:
• DataSet
o DataTable
 DataColumn
 DataRow
Inoltre fornisce una quantità notevole di metodi per la manipolazione dei dati, nonché
metodi che leggono o scrivono automaticamente file Xml all’interno dei quali viene
memorizzata la totalità dei dati contenuti in una singola tabella o in un intero DataBase.
8.4 L’input della fase di gioco
8.4.1
La classe Percussione
La classe Percussione svolge il compito fondamentale di rilevare i movimenti compiuti
dall’utente mediante un’analisi dei valori dell’accelerometro letti dal Wiimote e dal
Nunchuk. Questa classe non costituisce un componente XNA, ma è una classe standard C#
il cui comportamento è direttamente controllato dalla classe principale e, per riferimento,
dai componenti relativi alla fase di gioco.
L’istanza della classe Percussione viene inizializzata all’accesso da parte dell’utente alla
fase di gioco (o alla modalità Free). Alla creazione dell’istanza, la classe Percussione
riceve un riferimento all’oggetto WiiMote dalla classe principale. Può così accedere
direttamente alle informazioni lette dal dispositivo, e analizzarle per determinare il
compimento di un particolare gesto corrispondente al suono di una percussione.
54
8.4.2
Rilevamento dei gesti
La classe Percussione dispone di un metodo, IndividuaMovimento, che si occupa del
rilevamento dei gesti compiuti dall’utente corrispondenti al suono di una percussione.
L’invocazione di questo metodo è gestita dai componenti della fase di gioco; questa
tecnica consente all’applicazione di porre un controllo restrittivo sui movimenti ed evitare
l’erronea interpretazione di un piccolo spostamento di un telecomando come se
corrispondesse al suono di uno strumento. Senza questo accorgimento l’applicazione non
consentirebbe all’utente di riportare il telecomando nella posizione di partenza una volta
eseguito un gesto, come effettivamente deve avvenire anche nel suono di una percussione
reale. La logica che descrive questo controllo si basa sul fatto che se in un certo istante è
stata suonata una certa percussione, e cioè è stato eseguito il gesto relativo a tale suono, in
tale istante nessun altro gesto può essere stato compiuto.
8.4.3
Evento PercussioneChanged
All’invocazione del metodo IndividuaMovimento, viene eseguito un controllo dei valori
degli accelerometri del Wiimote e del Nunchuk. Se viene riconosciuto un movimento,
viene lanciato l’evento PercussioneChanged, definito all’interno della classe Percussione.
Gli argomenti di tale evento sono due variabili che rappresentano gli strumenti suonati
mediante i movimenti del Wiimote e del Nunchuk. In questo modo è possibile rilevare
gesti compiuti simultaneamente con entrambi i dispositivi. Nel caso in cui venisse scosso
un solo telecomando, la variabile relativa all’altro assumerà valore null.
8.4.4
La classe BalanceBoard
La classe BalanceBoard si occupa di individuare lo spostamento del centro di massa
dell’utente mediante la lettura dei dati rilevati dai sensori di peso della Balance Board.
Questa classe, così come la classe Percussione, non costituisce un componente XNA, ma è
una classe standard C# il cui comportamento è direttamente controllato dalla classe
principale e, per riferimento, dai componenti relativi alla fase di gioco.
55
L’istanza della classe BalanceBoard viene inizializzata dopo l’avvenuta connessione del
dispositivo all’applicazione. Alla creazione dell’istanza, la classe BalanceBoard riceve un
riferimento all’oggetto Wiimote dalla classe principale. Può così accedere direttamente alle
informazioni lette dal dispositivo, e analizzarle per determinare l’eventuale spostamento
del busto da parte dell’utente.
8.5 I componenti della fase di gioco
8.5.1
La classe PlayScreen
Nella classe PlayScreen è descritto un componente grafico che si occupa della
visualizzazione della batteria virtuale e del sistema di controllo della postura. Questo
componente viene attivato sia nella modalità libera che durante la fase di riproduzione di
una traccia.
Nella modalità Free viene visualizzata una Texture che rappresenta l’intera batteria
virtuale, mentre nella fase di gioco viene disegnato soltanto uno scheletro della batteria,
sopra al quale vengono evidenziati man mano gli strumenti che devono essere suonati nei
vari istanti della riproduzione.
La possibilità di utilizzare lo stesso componente nelle due diverse modalità deriva dal fatto
che esso si occupa esclusivamente di caricare nel Content Pipeline le Texture relative ai
vari strumenti della batteria, e della visualizzazione su schermo di alcune di queste Texture
all’invocazione del metodo Draw. La Texture da visualizzare viene impostata
all’inizializzazione del componente e successivamente (solo se ci si trova nella fase di
gioco) attraverso il metodo SetDrumKitTexture, invocato dalla logica di gioco.
Il sistema di controllo della postura, per scelta progettuale, è invece presente in entrambe le
modalità di gioco.
La classe PlayScreen si occupa inoltre della riproduzione del suono corrispondente a un
gesto compiuto dall’utente; essa possiede un riferimento all’istanza della classe
Percussione contenuta nella classe principale e, mediante un event-handler, intercetta
l’evento sollevato dalla classe Percussione e in risposta invoca il metodo Play della classe
Audio riproducendo così il suono corrispondente al gesto compiuto.
56
Durante la gestione della risposta all’evento, il componente si occupa anche di posizionare
una Texture relativa al Wiimote o al Nunchuk (o a entrambi) sullo strumento suonato
dall’utente con il telecomando corrispondente, evidenziando così qual è la percussione che
viene suonata al compimento di un gesto.
8.5.2
La classe Logica
Questo è un componente standard il cui compito è la gestione della logica di gioco durante
la fase di riproduzione di una traccia. All’inizializzazione, il componente preleva le
informazioni della traccia da riprodurre per mezzo di un oggetto di tipo Traccia; usa quindi
questi dati per elaborare la sequenza di percussioni da riprodurre e definire gli istanti di
tempo inerenti il suono di ciascuna percussione.
Durante l’intervallo di tempo utile per il suono di una percussione nella traccia, la logica
invia i comandi al componente PlayScreen per la visualizzazione delle Texture attive.
Queste operazioni avvengono nel metodo Update, utilizzando la variabile GameTime, che
identifica il tempo di gioco, come riferimento per gli intervalli di tempo.
Il componente Logica riceve nella propria inizializzazione il riferimento all’istanza della
classe Percussione dalla classe DrumAble, e sottoscrive un event-handler all’evento
PercussioneChanged; in questo modo, ogni volta che l’utente compie un gesto con un
telecomando, la logica valuta il compimento di tale gesto che, se corrisponde al suono
dello strumento previsto dalla traccia nell’intervallo di tempo corretto, viene validato, con
un conseguente aggiornamento positivo del punteggio. Se invece all’intercettazione
dell’evento la percussione suonata non corrisponde a quella corretta il punteggio viene
ridotto.
57
Capitolo 9. Sviluppi futuri
La tecnologia del Wiimote, per quanto riguarda la rilevazione dei movimenti, è efficace ma
non particolarmente precisa: infatti nel luglio 2009, a quasi 3 anni di distanza dal debutto
sul mercato del Wii, per correggere questo difetto Nintendo ha commercializzato Wii
Motion Plus (vedi paragrafo 3.5.3). Un possibile sviluppo del progetto è l’implementazione
di questo accessorio, in modo da rendere ancora più realistici i movimenti da compiere per
suonare gli strumenti della batteria virtuale.
Un’altra possibile estensione del progetto, è la sostituzione della grafica 2D, introducendo
per la fase di gioco un ambiente 3D in stile Guitar Hero (videogame musicale
particolarmente apprezzato dal grande pubblico), consistente in una pista sulla quale
scorrono i simboli relativi agli strumenti da suonare.
58
Elenco figure
Figura 1: Wiimote ..............................................................................................................7
Figura 2: Wiimote e assi direzionali ...................................................................................9
Figura 3: Sensor Bar ........................................................................................................12
Figura 4: Nunchuk collegato al Wiimote ..........................................................................16
Figura 5: Wii Balance Board ............................................................................................18
Figura 6: IVT Bluesoleil ..................................................................................................22
Figura 7: Sincronizzazione Wiimote ................................................................................23
Figura 8: Visuale dei movimenti del Wiimote corrispondenti al suono delle percussioni ..38
Figura 9: Batteria Virtuale. ...............................................................................................39
Figura 10: Membri di Wiimotelib e delle classi Wiimote e WiimoteState .........................46
Elenco Tabelle
Tabella 1: Profili Bluetooth supportati da BlueSoleil ........................................................22
Tabella 2: Associazione tra movimenti e percussioni........................................................40
Tabella 3: Classi implementate nel progetto .....................................................................50
59
Bibliografia
[1]
http://www.nintendo.it/NOE/it_IT/systems/wii_1069.html
[2]
http://en.wikipedia.org/wiki/History_of_video_game_consoles_(seventh
_generation)
[3]
I. Bromley “Tetraplegia And Paraplegia - A guide for physiotherapists”, Churchill
Livingstone
[4]
http://wiibrew.org/wiki/
[5]
http://en.wikipedia.org/wiki/Human_interface_device
[6]
http://www.bluetooth.com/Bluetooth/Technology
[7]
http://www.bluesoleil.com/
[8]
http://www.brianpeek.com/
[9]
http://www.codeplex.com/
[10]
http://blogs.msdn.com/coding4fun/archive/2007/03/14/1879033.aspx
[11]
http://msdn.microsoft.com/it-it/academic/default.aspx
[12]
http://msdn.microsoft.com/it-it/vstudio/products/bb931331.aspx
[13]
Andrew Troelsen “Pro C# And The .Net 3.5 Platform”, Apress
[14]
http://it.wikipedia.org/wiki/Delphi
60
[15]
http://creators.xna.com/
[16]
Riemer Grootjans “XNA 3.0 Game Programming Recipes - A Problem-Solution
Approach”, Apress
[17]
http://en.wikipedia.org/wiki/Percussion
[18]
http://en.wikipedia.org/wiki/Drumkit
[19]
http://www.freesound.org/
61
Ringraziamenti
Al termine della realizzazione di questo progetto, sentiamo di dover ringraziare tutte le
persone che ci hanno dato la possibilità di arrivare alla conclusione di questo ciclo di
studi. Ringraziamo in primis le nostre famiglie e tutti gli amici per il continuo supporto
ricevuto, soprattutto nei momenti di difficoltà. Desideriamo inoltre esprimere la nostra
gratitudine nei confronti dei relatori, che ci hanno saputo proporre un ambito di progetto
interessante e allo stesso tempo divertente, instradandoci sulle linee guida più
appropriate, e stimolando in noi particolare dedizione.
Enrico
Roberto
62