Lezione 5, Il Cursore
RyujiAndy | apr 19, 2009 | Commenti 0
Cursore
In Questa lezione vedremo come funziona il dispositivo infrarossi del controller wii, parto dal presupposto che avete letto le lezioni precedenti perchè trovo inutile riprendere ciò che ho già spiegato.
Per spiegarvi meglio vi allego un codice “main.c” con un semplice programma che non fa altro che inizializzare il wiipad e lo schermo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
static u32 *xfb;
static GXRModeObj *rmode;
void Initialise() {
VIDEO_Init();
PAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
int main() {
Initialise();
return 0;
}
Ora inseriamo delle funzioni per per il tracciamento di un rettangolo.
void DrawHLine (int x1, int x2, int y, int color) {
int i;
y = 320 * y;
x1 >>= 1;
x2 >>= 1;
for (i = x1; i <= x2; i++) {
u32 *tmpfb = xfb;
tmpfb[y+i] = color;
}
}
void DrawVLine (int x, int y1, int y2, int color) {
int i;
x >>= 1;
for (i = y1; i <= y2; i++) {
u32 *tmpfb = xfb;
tmpfb[x + (640 * i) / 2] = color;
}
}
void DrawBox (int x1, int y1, int x2, int y2, int color) {
DrawHLine (x1, x2, y1, color);
DrawHLine (x1, x2, y2, color);
DrawVLine (x1, y1, y2, color);
DrawVLine (x2, y1, y2, color);
}
Come vedete per disegnare un quadrato abbiamo bisogno di tre funzioni:
la prima per tracciare una riga orizzontale, la seconda per una riga verticale e la terza funzione “DrawBox()” per tracciare il nostro rettangolo, questa è quella che poi al momento noi interessa, da tenere conto le variabili necessarie per il tracciamento, infatti abbiamo necessità di due cordinate x/y, se vediamo la figura qui in basso sono il vertice alto a sinistra e quello in basso a destra, per comodità le ho chiamate x1/y1 e x2/y2, valori strettamente interi e in più il colore che intendiamo usare, anche questo intero.

fig. 1
Come da notare nella figura 1 le coordinate “x=0″ e “y=0″ equivalgono al punto in alto a sinistra dello schermo e il punto massimo che equivale alla risoluzione massima è di “x=640″ e “y=480″.
Spostando il cursore
Ora vogliamo disegnare un quadrato più piccolo che rappresenta il nostro cursore, potremo usare la funzione vista in precedenza e quindi:
DrawBox (300, 250, 301, 251, COLOR_WHITE);
Ora che abbiamo il nostro cursore dobbiamo avere i comandi per poter spostare il nostro cursore, per fare questo ci servono le variabili per il controllo del cursore che determinano le coordinate sullo schermo.
Per comodità chiamerò “cursor_x” la coordinate sull’asse “x” e “cursor_y” la coordinata sull’asse “y” e assegneremo un valore di defaul di “200″ e “200″ in modo che sia vicino al centro. Quindi il codice sarà:
int cursor_x = 300;
int cursor_y = 250;
Ora dobbiamo fare in modo che il cursore si muova quando il joystick verrà cliccato, facendo in modo che il cursore si sposta in alto o a destra e viceversa, per fare questo basta sommare o sottrarre le variabili del curore di “1″. Vi ricordo se non lo avete fatto di leggere la lezione precedente per richiamare le funzioni necessarie al conttollo del GC-pad.
if (PAD_StickY(0) > 18) {
cursor_y–;
}
if (PAD_StickY(0) < -18) {
cursor_y++;
}
if (PAD_StickX(0) > 18) {
cursor_x++;
}
if (PAD_StickX(0) < -18) {
cursor_x–;
}
Analizzando il codice qui sopra vediamo che se il joystick viene spostato l’alto fino il valore di “cursor_y” viene decrementato di 1 tramite il comando “cursor_y–;”, se invece viene spostato verso il basso avremo invece un incremento e questo grazie alla funzione “cursor_y++;”, lo stesso principio vale per destra e sinistra infatti il “cursor_x” viene incrementato o decrementato a seconda dell’imput sul joystick.
Per visualizzare il nostro cursore dobbiamo richiamare la funzione “DrawBox()” come vistp in precedente sostituento ai valori fissi le nostre variabili.
DrawBox (cursor_x, cursor_y, cursor_x + 1, cursor_y + 1, COLOR_WHITE);
Il prossimo passaggio è di cancellare lo schermo dopo ogni movimento del cursore, in questo modo il nostro cursore verrà cancellato ad ogni movimento, se non facciamo questo avremo l’effetto di creare tanti quadrati a seconda dei movimenti che gli facciamo fare quindi per evitare questo il nostro codice sarà:
int cursor_x = 300;
int cursor_y = 250;
while(1) {
PAD_ScanPads();
if (PAD_StickY(0) > 18) {
cursor_y–;
}
if (PAD_StickY(0) < -18) {
cursor_y++;
}
if (PAD_StickX(0) > 18) {
cursor_x++;
}
if (PAD_StickX(0) < -18) {
cursor_x–;
}
VIDEO_ClearFrameBuffer (rmode, xfb, COLOR_BLACK);
DrawBox (cursor_x, cursor_y, cursor_x + 1, cursor_y + 1, COLOR_WHITE);
VIDEO_WaitVSync();
}
Il motivo di aver inserito “VIDEO_ClearFrameBuffer()” prima di “DrawBox()” è per il semplice fatto di non dover cancellare il contenuto dello schermo per non perdere tempo a riscrivere richiamando altre funzioni e poi disegnare il nostro cursore. se il nostro codice richiama molte funzioni ciò richiederà tempo e quindi potremo avre un risultato che il cursore lampeggerà sullo schermo, invece così cancelliamo lo schermo richiamiamo le funzioni e ripetiamo il ciclo w quindi il cursore rimane fisso sullo schermo per tutto il tempo.
Conversione sorgente per utilizzare Wii IR
Ora vediamo di convertire il codice visto per utilizzare il Wii-Pad tramite il puntamento infrarossi, la prima cosa da fare è modificare il nostro “Makefile” sostituendo come già visto nella lezione precedenta:
include $(DEVKITPPC)/gamecube_rules
con
include $(DEVKITPPC)/wii_rules
Aggiungere il wii e le librerie Bluethooth al nostro compilatore come illustrato qui sotto:
LIBS := -lwiiuse -lbte -logc -lm
Ora dobbiamo inserire al nostro codice in modo da poter utilizzare le funzioni Wii:
#include <wiiuse/wpad.h>
Come al solito dobbiamo aggiungere una “W” davanti a tutti i “PAD_” e rimuovere i riferimenti “PAD_Substick”.
Quando si utilizza il Wiimote, in primo luogo si devono comunicare al sistema che vogliamo cogliere tutte le funzionalità del Wiimote, che include il infrarossi (IR) e l’accelerometro. Un’altra cosa da dire al sistema è la risoluzione che vogliamo che “IR” tenga. Entrambi questi due comandi vengono riportati di seguito e vengono collocati dopo la funzione “WPAD_Init”:
WPAD_SetVRes(0, 640, 480);
WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
l’”IR WPAD” ci fornisce vari dati come le coordinate “x” e “y” di dove viene puntato l’infrarossi che l’asse di rotazione ecc., queste informazioni potete andarle a vedere nel file “/(percorso)/devkitPRO/libogc/include/wiiuse/wiiuse.h”.
Ora c’è la necessità di assegnare una variabile che tenga conto dei dati, con la possibilità di poterla richiamare in qualsiasi momento per questo la collochiamo subito dopo i richiami “#includes”, facendo questo non dobbiamo assegnare la variabile ogni in ogni funzione dove viene richiamata:
ir_t ir;
Quindi, ora che abbiamo assegnato ir come la struttura dei dati ir_t, abbiamo bisogno di aggiornare costantemente la variabile ir per avere l’ultima lettura dal Wiimote. Questo viene fatto utilizzando il seguente codice:
WPAD_IR(0, &ir);
È in corso l’aggiornamento del Wii_Pad “0″, se ben ricordate equivale al primo, di tutti i dati e di alimentazione sulle informazioni della variabile “ir”.
Ora il passo finale è sostituire nella funzione “DrawBox()” le variabili “cursor_x” con “ir.x” e “cursor_y” con “ir.y”, come visto “ir” è una variabile che contiene tutti i dati del nostro Wii_pad, e di conseguenza anche le coordinate “x” e “y” per il posizionamento del cursore.
DrawBox (ir.x, ir.y, ir.x + 1, ir.y + 1, COLOR_WHITE);
Quindi ora possiamo completare il nostro codice come segue:
while(1) {
WPAD_ScanPads();
u32 pressed = WPAD_ButtonsDown(0);
// IR Movimenti
WPAD_IR(0, &ir);
if (pressed & WPAD_BUTTON_HOME) {
exit(0);
}
VIDEO_ClearFrameBuffer (rmode, xfb, COLOR_BLACK);
DrawBox (ir.x, ir.y, ir.x + 1, ir.y + 1, COLOR_WHITE);
VIDEO_WaitVSync();
}
Da notare che il puntatore Wii ci semplifica la vita e ci fa risparmiare nella stesura del codice questo perchè la lettura è immediata, cioè abbiamo sempre i valori effettivi delle coordinate e non dobbiamo sommare o sottrarre per avere un cursore.
Per Questa volta e tutto spero di rivedervi alla prossima lezione ciriciao.
RiujiAndy
Tratto e concesso da: http://ryujiandy.ath.cx/
Filed Under: Programmazione