giovedì 22 dicembre 2016

Iniziare a programmare con SDL 2 su Linux - parte 2


Nella prima parte di questo tutorial abbiamo visto come installare tutti gli strumenti di sviluppo e abbiamo creato il nostro primo programma sfruttando la libreria SDL 2. In questa seconda parte approfondiremo meglio l'utilizzo di g++ e valgrind, inoltre miglioreremo il nostro SDL Hello World.

Per tutti coloro che sono nuovi utenti del mondo Linux o che comunque non hanno esperienza nell'invocazione del compilatore g++ ho pensato di fare un po' di chiarezza sulla sintassi di questo comando.

La sintassi più semplice è
$ g++ [file sorgente]

L'eseguibile avrà il nome di default a.out.
Per specificare il nome dell'eseguibile basta aggiungere l'opzione -o [nome eseguibile], quindi
$ g++ [file sorgente] -o [nome eseguibile]

Se ci sono più file sorgenti basta elencarli
$ g++ [file sorgente 1] [file sorgente 2] -o [nome eseguibile]

Per finire, se dobbiamo utilizzare una libreria, come SDL 2 nel nostro caso, dobbiamo comunicarlo al linker tramite l'opzione -l (elle minuscola) seguita dal nome della libreria senza spazi.
$ g++ [file sorgenti] -o [nome eseguibile] -l[nome libreria]

Per la libreria SDL 2 scriveremo -lSDL2

Bene, questo è quanto abbiamo visto finora nella prima parte del tutorial, ma avrete notato che, quando la lista dei file sorgente aumenta, invocare g++ diventa decisamente scomodo.
Per semplificare il tutto possiamo utilizzare il comando make.

Il funzionamento di make è molto semplice, dobbiamo creare un file di testo dove forniremo tutte le informazioni necessarie per la compilazione, quali il compilatore da invocare, la lista dei file sorgente, le opzioni da passare al compilatore, ecc...
Una volta preparato il file chiamato Makefile, basterà invocare make e questo invocherà g++ per noi.
Questo è un esempio di Makefile per compilare il nostro SDL Hello World


Il contenuto del Makefile è abbastanza semplice da capire, man mano che aggiungiamo un file sorgente o un file header basterà aggiungerlo alla lista nel Makefile. Possiamo apportare tutte le modifiche che vogliamo nel Makefile e basterà invocare il comando make per compilare ed ottenere il file eseguibile.
Oltre a questo make si occupa di verificare se dall'ultima compilazione è cambiato qualcosa nei file sorgente, se nulla è cambiato ci verrà notificato.
Copiate ed incollate il testo in un file e salvatelo con il nome Makefile nella stessa directory dei file sorgente. Ora provate ad eseguire il comando
$ make

Decisamente più comodo, non è vero?



Passiamo ad un altro argomento: valgrind.
La scorsa volta avevamo installato valgrind in quanto ottimo strumento di debugging, in particolare per gli errori nella gestione delle allocazioni di memoria. La sintassi è semplice
$ valgrind ./[nome eseguibile]

L'eseguibile verrà avviato all'interno dell'ambiente di debugging di valgrind, il quale analizzerà tutte le allocazioni di memoria e le relative de-allocazioni delle stesse. Al termine del programma verrà stampato sul terminale un resoconto completo con un elenco degli eventuali errori rilevati.

Proviamolo con il nostro SDL Hello World
$ valgrind ./sdl_helloworld

L'esecuzione risulterà più lenta e alla fine avremo sul terminale un resoconto dettagliato.
Senza entrare troppo nei particolari, quello che ci interessa più di tutto il resto è l'ultima riga:
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 2)

Nella sezione LEAK SUMMARY potete trovare altri dettagli sulle allocazioni di memoria.
E' ovvio che non è solo il vostro codice che viene analizzato, ma anche quello delle librerie utilizzate, quindi alcuni memory leaks possono essere causati da quest'ultime.

Bene, torniamo all'argomento principale di questo tutorial, SDL 2.
Nello scorso esempio abbiamo utilizzato la funzione SDL_loadBMP(), che carica un'immagine di tipo BMP (Windows bitmap) in un oggetto SDL_Surface.
Per quanto questa funzione sia molto comoda e semplice da utilizzare, il formato BMP è piuttosto limitato e scarsamente utilizzato al giorno d'oggi.
Nella libreria principale di SDL 2 non ci sono altre funzioni per caricare immagini di tipo diverse, quali ad esempio PNG o JPG, ma fortunatamente c'è un'altra libreria dedicata a questo scopo: SDL_image.

Prima cosa da fare è installare sul nostro sistema questa libreria.
$ su
(verrà richiesta la password di root)
# apt install libsdl2-image-dev



Ora che abbiamo installato SDL_image possiamo modificare il programma per aprire un'immagine di tipo PNG.

Aggiungiamo l'include con il file header di questa libreria in helloengine.h
#include <SDL2/SDL_image.h>

Come la libreria SDL 2 anche questa va inizializzata, quindi nella funzione init() della classe HelloEngine (helloengine.cc) aggiungiamo queste righe di codice per inizializzare SDL_image per il caricamento di immagini PNG, subito sotto l'inizializzazione di SDL 2.

// inizializzazione SDL_image per i file di tipo PNG
if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG)
{
    on_SDL_error(std::cout, "IMG_Init");
    return false;
}

Ora andiamo a modificare la parte di codice che carica l'immagine, è sempre nella funzione init() poco più in basso. Utilizzeremo la funzione IMG_LoadTexture() che ci restituisce direttamente un puntatore ad un oggetto di tipo SDL_Texture, quindi non avremo bisogno di crearla passando per un SDL_Surface.

// carica l'immagine in texture
std::string name = "helloworld.png";
if ((texture = IMG_LoadTexture(renderer, name.c_str())) == nullptr)
    on_SDL_error(std::cout, "IMG_LoadTexture");

Potete convertire l'immagine BMP in una di tipo PNG utilizzando Gimp e salvatela con il nome helloworld.png.

Prima di compilare ricordatevi che stiamo utilizzando un'altra libreria, quindi dovremo modificare il nostro Makefile aggiungendo -lSDL2_image alla lista delle librerie da linkare, subito dopo -lSDL2.

Terminate le modifiche questo è quello che dovreste ottenere
Compilate con
$ make

Ed ora avviate il programma
$ -/sdl_helloworld

Se non avete fatto errori il programma funzionerà come prima.
Bene, in questa seconda parte del tutorial dedicato ad SDL 2 abbiamo preso maggior confidenza con gli strumenti di sviluppo e debugging, inoltre abbiamo visto come usare la libreria SDL_image.
Nel prossimo tutorial faremo ulteriori modifiche e vedremo come funziona la gestione degli eventi.

Nessun commento:

Posta un commento