Si è accennato alla possibilità di leggere e salvare i punteggi migliori. Anche in un semplice gioco è infatti importante dare la sensazione di uno scopo che non sia semplicemente quello di "perdere del tempo". Creiamo innanzitutto una lista denominata high_scores per memorizzare i migliori punteggi ottenuti:
List high_scores = new List();
Per salvare (e leggere) i punteggi possiamo utilizzare l'Isolated Storage del nostro telefonino WP7, vale a dire uno spazio appositamente riservato alle singole applicazioni. In buona sostanza, l'Isolated Storage consente ad un'applicazione di salvare i propri dati in una porzione di spazio completamente isolata rispetto allo spazio riservato ad altre applicazioni (o ad altri utenti), nonché rispetto allo stesso file system del nostro device.
Questa sorta di "spazio protetto", non accessibile da parte di altre applicazioni, viene creato al momento dell'istallazione della nostra applicazione e viene rimosso quando questa viene disintallata da parte dell'utente. Il framework di XNA non consente di accedere a questo spazio.
Per poterlo fare, occorre usare le classi esposte dal namespace System.IO.IsolatedStorage (nei progetti XNA per Windows Phone 7, Visual Studio provvede automaticamente ad aggiungere le assembly necessarie al progetto, per cui è sufficiente ricordare di aggiungere la using per il relativo namespace).
Dal momento che durante l'accesso all'IsolatedStorage del telefonino c'è la possibilità che qualcosa vada storto, è importante utilizzare un blocco try/catch
per assicurarci di gestire le eventuali eccezioni (di tipo IsolatedStorageException
).
A questo punto possiamo ottenere l'Isolated Storage per quell'utente e quella specifica applicazione tramite il metodo GetUserStoreForApplication
, che ritorna una reference al nostro IsolatedStorageFile
, ossia alla porzione di spazio disco accessibile da parte della nostra applicazione:
try
{
var IS = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
La prima cosa da fare è verificare se il file contenente la classifica dei migliori punteggi è già stato creato:
if (IS.FileExists("high_scores.txt"))
{
In caso positivo, lo apriamo (System.IO.FileMode.Open
) e leggiamo i punteggi tramite il metodo ReadToEnd
esposto dalla classe StreamReader
(metodo che restituisce una stringa), dopodiché ne formattiamo il contenuto e aggiungiamo i relativi punteggi alla nostra lista mediante il metodo ToList
:
try
{
using (var hsf = new StreamReader(IS.OpenFile("high_scores.txt", System.IO.FileMode.Open)))
{
var hsf_s = hsf.ReadToEnd();
high_scores = (from l in hsf_s.Split(new[] { 'n' }) select (int.Parse(l))).ToList();
}
}
catch (Exception e)
{
}
Infine, al termine del blocco try/catch ci assicuriamo che, in ogni caso, il punteggio corrente sia nella lista degli high scores, ordiniamo i punteggi dal più alto al più basso e prendiamo i primi tre punteggi.
finally
{
high_scores.Add(score);
high_scores = high_scores.OrderByDescending(x => x).ToList();
high_scores = high_scores.Take(3).ToList();
}
}
A questo punto salviamo i tre punteggi migliori (a dire il vero, nel listato sopra esaminato manca un controllo per verificare che il punteggio corrente sia effettivamente il più alto, ma avrebbe inutilmente appesantito il codice senza aggiungere niente di interessante). Qualora non esista già un file high_scores.txt
, System.IO.FileMode.Create
provvederà a crearlo per noi, mentre in caso contrario si limiterà a sovrascriverlo:
using (var hsf = new StreamWriter(IS.OpenFile("high_scores.txt", System.IO.FileMode.Create)))
{
high_scores.ForEach(x => hsf.WriteLine(x.ToString()));
}
Infine, nel catch più esterno ci assicuriamo che, nella peggiore delle ipotesi, qualora tutto dovesse andare storto, la nostra lista venga quantomeno resettata.
catch (Exception e)
{
high_scores = new List<int>();
}