venerdì 30 settembre 2011

HowTo: Integrare SQLite nel proprio gioco Java

Come tutti i programmi, anche i giochi necessitano di dati. Abbiamo già parlato in precedenza di alcuni metodi per gestire (scrivere e rileggere) tali dati, utilizzando file xml piuttosto che file binari o ASCII. Ci sono naturalmente anche altri modi, e uno di questi è senza dubbio SQLite, un piccolo e leggero database relazionale su file.

Un database? Non sarà un po' troppo?

Dipende. Sicuramente se volessimo scomodare un vero server di database come MySQL o SQLServer occorrerebbe una giustificazione più che valida. Ma SQLite è, come lascia intendere il nome, piccolino. Piccolino ma, attenzione, adatto a gestire grandi mole di dati, soprattutto in lettura. Pensate alla comodità di avere le varie entità del vostro gioco serializzate in modo ordinato in tabelle di una base dati. La tabella Livelli, con i dati relativi ad ogni livello di gioco, la tabella Nemici, con tutte le statistiche delle varie tipologie di nemici, la tabella Oggetti, con tutti gli item presenti nel vostro modo, e perché no, la tabella Partite, con i salvataggi del giocatore. E così via. Tutti dati che dovreste comunque gestire in una qualche forma di file.

I vantaggi del relazionale.

Una volta modellata la base dati potrete poi sfruttare il principale vantaggio del suo utilizzo: le relazioni. La tabella NemiciPerLivello potrebbe contenere in modo semplice le coppie Livello-Nemico con la posizione all'interno del livello del tale nemico, ad esempio. In poche parole avete tra le mani, in forma gratuita, la potenza di chiavi primarie, chiavi esterne, vincoli di check e quant'altro.

I vantaggi del linguaggio di query.

Recuperare (ma anche salvare, aggiornare o eliminare) i dati diventa semplice. Volete popolare il livello con una lista di oggetti casuali ma che siano di valore compreso tra min e max? Complicato con xml, un delirio con ASCII o binario, ma semplice ed immediato con una query SQL come:

SELECT * FROM ITEMS WHERE ITEMVALUE >= @min AND ITEMVALUE <= @max

Già, ma come lo integro nel mio game?

Ed eccoci al punto. Per questo articolo prenderò come linguaggio di esempio Java. Essendo un linguaggio orientato per motivi storici ad applicazioni enterprise (da ufficio, per intenderci) ha già una buona integrazione con oggetti esterni come le basi dati. Per prima cosa occorre scaricare il pacchetto (.jar) contenente SQLite: al momento in cui scrivo ne trovate una copia qui.

(Per gli amici C++: SQLite è scritto in C, quindi la sua integrazione con C/C++ è assolutamente fattibile. Ne esiste anche la versione managed per .NET).

Questo pacchetto va poi inserito nel vostro progetto ed incluso tra le librerie in uso (in Eclipse si fa il tutto da Progetto->Proprietà->Java Build Paths->Librerie->Aggiungi JAR).

A questo punto siete pronti per scrivere codice! Vi servono solo 2 righe, che sono queste:


Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:db/miodatabase.sqlite");


dove db/miodatabase.sqlite è il percorso + nome del vostro database, relativo alla root del progetto.

E come lo creo il database?

E qui viene il bello. Con file di testo semplici ci basta Blocco Note. Con file binari ci occorre un editor di qualche tipo, che spesso dobbiamo scrivere noi. Con file xml può andare un qualunque editor di testi, ma per documenti importanti può diventare necessario un editor apposito, ancora una volta custom e a nostre spese.

Per SQLite invece è pieno il mondo di programmi di amministrazione. Pensateli come fossero i vostri editor per i dati, perché è proprio quel che sono. C'è ad esempio un plugin per Firefox, SQLite Manager, comodissimo e ben realizzato, che vi fa creare ed editare il vostro database da browser. Check it out!

Un esempio di lettura.

Concludiamo con un piccolo esempio che mostra quanto diventi semplice ottenere i dati (per la loro creazione avrete probabilmente usato un tool come quelli citati qui sopra).

List<quest> ret = new ArrayList<quest>();
Connection conn = DriverManager.getConnection("jdbc:sqlite:db/miodatabase.sqlite");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from quests where npc = " + npcId + " and done = 0");
while(rs.next()){
ret.add(new Quest(rs.getInt("id"),
rs.getString("text"),
rs.getString("type"),
rs.getString("onsuccess"),
rs.getString("onwait"),
rs.getInt("reward_gold")));
}
rs.close();
conn.close();

Una volta creato il vostro oggetto Connection potrete interrogare la base dati attraverso un oggetto Statement. La query in questo esempio preleva tutte le Quest di un ipotetico gioco di ruolo fornite da un personaggio non giocante con un certo id. Si riempie quindi un oggetto di gioco Quest con i dati prelevati e lo si aggiunge alla lista da restituire. Quando il set di dati finisce (rs.next() ritorna false quando non trova più nulla da leggere) si chiude la connessione. Abbiamo ora una lista di oggetti Quest pronti per essere gestiti dal motore di gioco!

Con questo spero di avere aggiunto un'ulteriore freccia alla faretra dello sviluppatore in erba. Considerate che esistono anche i database e che non è vietato utilizzarli. Specie se se ne restano confinati in un unico, piccolo file binario.

Buon coding!

1 commento:

  1. PokerStars casino: The most innovative poker room
    Our PokerStars Casino: The most apple watch stainless steel vs titanium innovative poker หาเงินออนไลน์ room on earth. ford focus titanium hatchback Our PokerStars Casino: titanium exhaust tips The most innovative columbia titanium boots poker room. The fastest growing slots casino

    RispondiElimina