Per rendere a tutti gli effetti il nostro operato un videogioco, per quanto piccolo possa essere, bisogna donargli un’ interfaccia grafica che abbia il compito di gestire le impostazioni video, come risoluzione, accelerazione hardware ecc… e sopratutto che consenta di salvare le impostazioni correnti, compresa la partita attualmente in atto.
Per fare questo ho deciso di chiedere supporto al modulo python cPickle, che si occupa della serializzazione (salvataggio) di oggetti creati dall’utente in stringhe di dati. L’utilità sta nel fatto che, queste stringhe, possono essere scritte su un qualsiasi file e successivamente lette.
Il vantaggio che ci offre questo modulo non è del tutto indifferente. Pensate infatti di memorizzare le vostre impostazioni video o di gioco in uno o più file creati da voi a piacimento che, ogni volta, devono essere letti in un certo modo per far si che quei dati memorizzati possano essere utili.
Con cPickle invece possiamo benissimo ricreare gli oggetti che stavamo utilizzando senza preoccuparci di come dovranno essere letti o scritti i file. Anche questo ha però alcune limitazioni, per esempio nella memorizzazione di sottoclassi ecc… (consultare la guida ufficiale di python per altri dettagli) però è un ottima soluzione se non si volgio utilizzare file xml e/o file creati dall’utente stesso, dove è necessario occuparsi del parsing (cioè di come deve essere letto il file).
Il codice
Non voglio tenervi sulle spine e quindi passo direttamente alla presentazione delle funzion e delle classi che andremo ad analizzare:
def tps(orologio, fps): def carica_imm_sprite(nome,h,w,num): class giocatore(pygame.sprite.Sprite): class ingame(): class impostazioni(): class main_menu(): def Eventi(event, Main): def caricamento_imp(): def salvataggio_imp(): def aggiorna_imp(w,h,full,buff,hw,opengl): def run(): if __name__ == "__main__": run()
Come avrete sicuramente notato, ci sono alcune funzioni che abbiamo già visto nei precedenti esempi, quindi non saranno analizzata se non nei cambiamenti (riporterò comunque il codice completo per una migliore consultazione).
- Le funzioni tps e carica_imm_sprite non sono cambiate e hanno sempre lo stesso scopo (caricamento delle immagini e gestione del tempo di gioco).
- La classe giocatore è la stessa classe sprite che abbiamo utilizzato nella guida precedente. L’unica differenza è che non gestiamo le collisioni per semplificare un pò il codice di questo esempio, visto che lo scopo principale è quello di salvare lo stato di gioco attuale e di poterlo caricare correttamente.
- La classe ingame contiene tutti gli elementi di gioco ed è questa che si occupa di renderizzare il gioco avviato.
- La classe impostazioni serve per tener conto dello stato di gioco, in particolare della risoluzione video e dei flag utilizzati (ACCHW, DOUBLEBUFF, OPENGL, FULLSCREEN).
- La classe main_menu, come potete immaginare, si occupa del menù di gioco e di tutte le funzionalità che ci interessano in questo esempio: caricamento e salvataggio di gioco, caricamento e salvataggio delle impostazioni di gioco.
- La funzione Eventi coordina gli eventi di sistema per gestire il gioco, vedremo poi in dettaglio come.
- La funzione caricamento_imp si occupa di caricare dal file impostazioni.pkl da noi creato, le impostazioni memorizzate.
- La funzione salvataggio_imp ha il compito di creare un file di configurazione nell’eventualità che questo non esista.
- La funzione aggiorna_imp cambierà il file di configurazione da noi creato con le impostazioni aggiornate.
Per rendere chiaro il funzionamento globale devo spiegarvi come ho deciso di organizzare le cose:
- Main_menu contiene ingame, che a sua volta contiene il giocatore.
- Eventi richiama solo funzioni di main_menu.
In questo modo gestire gli eventi consiste solo nel passare ad una funzione di main_menu a seconda dell’evento analizzato. Main_menu, che al suo interno contiene anche l’istanza di gioco, si occuperà di passare dal gioco al menù testuale e della gestione degli input dell’utente (a seconda se siamo ingame o nel menù). Main_menu avrà quindi al suo interno anche una propria gestione del caricamento delle impostazioni ed una parte per il caricamento dei salvataggi di gioco. Il videogame vero è proprio però è ingame. In quest’ultimo viene gestita tutta la dinamica relativa alle animazioni del giocatore, delle regole di gioco, del mondo di gioco (non presenti completamente in questo esempio) ecc…
Conclusioni
In questa serie di articoli analizzeremo quindi questi oggetti che daranno vita al menù del nostro gioco, aggiungendo quelle feature di base che caratterizzano qualsiasi videogame. Con ciò sarete in grado di realizzare un piccolo videogioco completo, l’unica vostra limitazione sarà la fantasia. Infatti le nozioni che cercherò di introdurre non sono di difficile comprensione e una volta appreso il meccanismo, è facile modificarlo secondo le vostre esigenze.
Voglio solo ricordare che questa impostazione non è sbagliata ma nessuno vieta di cambiare le cose: se per esempio preferite gestire gli eventi con una classe a parte che coordina i vari stati di gioco (ingame e menu), oppure inserire gli eventi all’interno delle classi esistenti, potete benissimo farlo. Ricordate che durante la progettazione del vostro videogioco dovete sempre tenere conto delle cose essenziali e di quelle superflue. Avere una base solida (concettualmente parlando) vi porterà a fare determinate scelte che vi faciliteranno la vita, quindi non perdete mai l’obbiettivo che volete raggiungere creando il vostro oggetto videoludico.
Sperando di aver stuzzicato ancora il vostro interesse, vi do appuntamento al prossimo articolo.