SDL (Simple DirectMedia Layer) è una libreria di sviluppo
multi-piattaforma, scritta in linguaggio C, progettata per
controllare facilmente video, grafica, audio, tastiera, mouse,
joystick, ecc...
Queste
capacità la rendono ideale per lo sviluppo di videogiochi,
applicazioni multimediali ed emulatori.
Un
grande vantaggio è il fatto di essere multi-piattaforma, questo
infatti semplifica il porting sulle diverse piattaforme supportate
(Linux, OS X, Windows, iOS e Android).
SDL 2.0 è rilasciata con licenza Zlib, che è una licenza
per software libero ed è compatibile con la licenza GPL.
Vediamo
subito come preparare il nostro sistema con tutti gli strumenti
necessari per iniziare a programmare.
In
questo tutorial utilizzerò Debian GNU/Linux 8.6 con il desktop
manager di default GNOME.
Probabilmente
già saprete che Debian è una distribuzione GNU/Linux universale ed
è la base di molte altre distribuzioni derivate, tra le quali
Ubuntu. Utilizzare Debian in questo tutorial mi permette di
abbracciare una grossa fetta di utenti Linux.
La
prima cosa di cui abbiamo bisogno sono gli strumenti di sviluppo
fondamentali, quali il compilatore, il linker ed un debugger.
Il
pacchetto build-essential ci fornirà tutta la suite di programmi
utili allo sviluppo.
$
su
vi
verrà chiesta la password di root.
Controlliamo
se ci sono aggiornamenti del sistema disponibili con
#
apt update
Se
trovati procediamo con l'aggiornamento con
#
apt upgrade
Quindi
installiamo build-essential
#
apt install build-essential
Analizzando
la lista dei pacchetti installati, forse avrete notato che gdb (il
debugger GNU) è nella lista dei pacchetti consigliati, ma non è
stato installato. Possiamo installarlo manualmente con
#
apt install gdb
Oppure
verrà installato automaticamente quando andremo ad installare
Valgrind.
Valgrind
è un ottimo software di debug e profiling che, tra le altre cose,
permette di scovare gli errori nella gestione della memoria, come ad
esempio i memory leaks, ossia le allocazioni di memoria che non
vengono liberate al termine del loro utilizzo.
#
apt install valgrind
Ora
che abbiamo gli strumenti fondamentali per lo sviluppo, possiamo
installare la libreria SDL 2.0.
#
apt install libsdl2-dev
Il
pacchetto libsdl2-dev contiene la libreria SDL 2.0 e tutti i
componenti fondamentali per sviluppare applicazioni con SDL, ma se
provate a cercare i pacchetti libsdl2 disponibili troverete altri
componenti che ne espandono le funzionalità.
#
apt search libsdl2
Analizzeremo
ed installeremo gli altri pacchetti nel prossimo tutorial, quando ci serviranno,
per il momento iniziamo a fare un piccolo test di compilazione per
verificare che tutte le operazioni di preparazione siano andate a
buon fine.
Per
questo tutorial utilizzerò gedit, l'editor di testo del desktop
GNOME, semplice e leggero, sicuramente adatto per scrivere/modificare
file di codice sorgente di piccole dimensioni.
Nonostante
la sua estrema semplicità, con qualche piccolo accorgimento possiamo
renderlo un discreto strumento di sviluppo.
Dopo
aver lanciato gedit, clicchiamo sul menù dell'applicazione sulla
barra dello schermo in alto accanto ad Attività, e selezioniamo la
voce Preferenze. Comparirà una finestra con diverse opzioni divise
per categorie, clicchiamo su Editor e modifichiamo l'ampiezza di
tabulazione da 8 a 4. Personalmente trovo che 8 spazi siano
decisamente troppi, ma siete liberi di impostare il numero di spazi
che più vi aggrada.
Preferenze di gedit |
Ora
cliccate su Plugin e scorrete la lista in basso fino a trovare e
spuntare l'opzione Terminale integrato. Questo ci permetterà di
avere un Terminale nella parte bassa della finestra di gedit,
evitando di dover passare da una finestra ad un'altra quando dobbiamo
compilare o effettuare operazioni di debugging.
Adesso
clicchiamo sull'icona menù, posta sulla finestra di gedit accanto al
tasto x di chiusura, selezioniamo Vista e spuntiamo le voci Riquadro
laterale e Riquadro inferiore.
Queste
faranno visualizzare un riquadro laterale con la lista dei file
aperti ed un riquadro inferiore con il Terminale integrato.
Per
finire, nella barra di stato di gedit, cliccate su Testo semplice per
far comparire un menù e selezionate C++ per usufruire della
colorazione automatica del testo per la sintassi del linguaggio di
programmazione che andremo ad utilizzare nel tutorial.
Al
termine di queste personalizzazioni, gedit ha un aspetto decisamente
più orientato alla programmazione e meno minimalista.
Facciamo
un test veloce per verificare che tutto funzioni regolarmente,
scriveremo il classico Hello World e proveremo a compilarlo.
E' indispensabile avere una conoscenza minima del linguaggio C++,
altrimenti vi consiglio di andare a consultare un manuale o un
tutorial specifico.
Salvate
il file in Documenti con il nome helloworld.cc, quindi dal Terminale
integrato di gedit, andate in Documenti e provate a compilare il
vostro programma.
$
g++ helloworld.cc -o helloworld
Se
non avete fatto errori la compilazione andrà a buon fine e potrete
eseguire helloworld
$
./helloworld
Hello
World!
A
questo punto facciamo un altro test, un nuovo Hello World, ma questa
volta utilizzando SDL 2.
Andremo
a creare una classe chiamata HelloEngine che sarà il motore della
nostra applicazione, mentre nel file principale, chiamato
sdl_helloworld.cc ci sarà la funzione main() che si occuperà di
creare un'istanza di HelloEngine ed avviarne l'esecuzione.
E'
una struttura simile a quello che si utilizza per lo sviluppo di un
videogioco, in questo caso è molto semplificata in quanto non ha un
loop e non gestisce alcun evento. Questo programma si limiterà ad
aprire una finestra e visualizzare il messaggio Hello World, dopo 2
secondi d'attesa chiude la finestra e termina.
Questi
sono i tre file del nostro SDL Hello World.
Iniziamo
ad esaminare il file header della classe HelloEngine, all'inizio del
file andiamo ad includere iostream e SDL2/SDL.h.
Il
secondo è ovviamente indispensabile per utilizzare la libreria SDL2,
mentre il primo è necessario quando andiamo a stampare gli eventuali
messaggi d'errore tramite std::ostream.
Le
funzioni membro sono solo 4:
-
init() si occupa di inizializzare HelloEngine;
-
start() avvia l'esecuzione;
-
render() disegna l'immagine caricata nella finestra;
-
on_SDL_error() stampa il messaggio d'errore sullo std::ostream
indicato.
Per
il resto il file header è piuttosto semplice, andiamo a vedere come
queste 4 funzioni sono implementate in helloengine.cc.
Init()
è la funzione che inizializza l'ambiente SDL invocando SDL_Init(),
prima di poter utilizzare qualsiasi funzione della libreria SDL2
dobbiamo inizializzarla con questa funzione. Successivamente viene
creata una finestra con SDL_CreateWindow(), quindi viene creata
un'istanza di SDL_Renderer che ci servirà per tutte le operazioni
grafiche.
Per
finire viene caricata un'immagine BMP ottenendo un oggetto
SDL_Surface con il quale viene creato un oggetto SDL_Texture.
Dopo
aver ottenuto la nostra texture, viene distrutto l'oggetto
SDL_Surface con la funzione SDL_FreeSurface() liberando la memoria
allocata.
render()
è incaricata di disegnare sulla finestra.
SDL_RenderClear()
cancella il contenuto di renderer, SDL_RenderCopy() disegna la
texture ottenuta dal caricamento dell'immagine su renderer, infine
con SDL_RenderPresent() viene visualizzato il contenuto di renderer
sulla finestra.
Start()
avvia l'esecuzione vera e proprio di HelloEngine, inizialmente invoca
init() per effettuare tutte le inizializzazioni, quindi esegue la
funzione render() per disegnare sulla finestra. SDL_Delay() attende
per il numero di millesecondi indicato, nel nostro caso
attende 2 secondi e quindi esce con valore 0 per indicare che non ci
sono stati errori.
on_SDL_error()
stampa un messaggio d'errore sullo std::ostream indicato, di fatto è
sempre std::cout.
Infine
è bene soffermarsi sul distruttore della classe HelloEngine, che si
occupa di de-allocare tutta la memoria utilizzata dal programma.
SDL2
ha una funzione specifica per ogni tipo di oggetto da de-allocare,
non possiamo utilizzare il semplice delete. Abbiamo visto in init()
la funzione SDL_FreeSurface() per distruggere l'SDL_Surface, qui
utilizziamo SDL_DestroyTexture per l'SDL_Texture, SDL_DestroyRenderer
per l'SDL_Renderer e SDL_Quit per chiudere l'intero ambiente SDL.
Il
file sdl_helloworld.cc contiene la funzione main() del programma, il
funzionamento è estremamente semplice, crea un'istanza di
HelloEngine e ne invoca l'esecuzione con start(). Al termine
dell'esecuzione distrugge l'istanza con il delete ed esce con lo
stesso codice d'uscita dell'istanza.
Andiamo a compilare SDL Hello World con
$ g++ -std=c++11 helloengine.h helloengine.cc sdl_helloworld.cc -o sdl_helloworld -lSDL2
Prima di eseguire ricordatevi di mettere l'immagine helloworld.bmp nella stessa directory dell'eseguibile, altrimenti verrà visualizzata una finestra completamente nera.
Immagine BMP utilizzata per questo test |
L'immagine verrà salvata come JPG, potete esportarla in formato BMP utilizzando Gimp oppure ne potete creare una voi. Ricordatevi che per poter essere caricata correttamente da SDL_LoadBMP() l'immagine deve avere un unico livello.
$ ./sdl_helloworld
SDL Hello World in esecuzione |
Nel
prossimo tutorial vedremo come caricare immagini di altri formati,
gestire eventi come la pressione di un tasto o il click del mouse ed
altro ancora.
Nessun commento:
Posta un commento