Quest’ultima parte è tutta in discesa. Le funzioni che elencherò sono basilari, ma anche di facile intuizione. Vi prego di non badare troppo alle ottimizzazioni possibili che non ho effettuato (questo non vuol dire che non potete suggerirle :D), perché il mio intento principale è, in questa guida, mostrare come memorizzare facilmente delle informazioni proprie e trattarle a seconda dei gusti personali di chi programma.
Codice
################################# #Funzione che gestisce gli eventi def Eventi(event, Main): if event.type == QUIT: exit() tasti_premuti = pygame.key.get_pressed() pulsanti_mouse = pygame.mouse.get_pressed() if event.type == KEYDOWN : if tasti_premuti[K_ESCAPE]: Main.action_esc() elif tasti_premuti[K_LALT] and tasti_premuti[K_F4]: exit() elif tasti_premuti[K_DOWN]: Main.action_p("basso",0) elif tasti_premuti[K_UP]: Main.action_p("alto",12) elif tasti_premuti[K_RIGHT]: Main.action_p("destra",8) elif tasti_premuti[K_LEFT]: Main.action_p("sinistra",4) if event.type == MOUSEBUTTONDOWN: if pulsanti_mouse[0]==1: coordinate_mouse = pygame.mouse.get_pos() Main.action(coordinate_mouse) ######################################################################################### # Funzione per il caricamento delle impostazioni. File : impostazioni.pkl; ritorna screen def caricamento_imp(): try: stream = open("data/impostazioni.pkl", "r") pk = cPickle.Unpickler(stream) imp = pk.load() stream.close() pygame.mixer.pre_init(imp.frequenza, imp.dimensione, imp.canali, imp.buffer) pygame.init() if imp.full == False and imp.bool_buff == False and imp.bool_hw == False and imp.bool_opengl == False: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo)) elif imp.full == False and imp.bool_buff == False and imp.bool_hw == False and imp.bool_opengl == True: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),OPENGL,imp.depth) elif imp.full == False and imp.bool_buff == False and imp.bool_hw == True and imp.bool_opengl == False: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),HWSURFACE,imp.depth) elif imp.full == True and imp.bool_buff == False and imp.bool_hw == True and imp.bool_opengl == False: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),FULLSCREEN | HWSURFACE,imp.depth) elif imp.full == False and imp.bool_buff == True and imp.bool_hw == True and imp.bool_opengl == False: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),DOUBLEBUF | HWSURFACE,imp.depth) elif imp.full == True and imp.bool_buff == True and imp.bool_hw == True and imp.bool_opengl == False: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),FULLSCREEN | DOUBLEBUF | HWSURFACE,imp.depth) elif imp.full == True and imp.bool_buff == False and imp.bool_hw == False and imp.bool_opengl == False: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),FULLSCREEN,imp.depth) elif imp.full == True and imp.bool_buff == True and imp.bool_hw == False and imp.bool_opengl == True: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),FULLSCREEN | DOUBLEBUF | OPENGL,imp.depth) elif imp.full == False and imp.bool_buff == True and imp.bool_hw == False and imp.bool_opengl == True: screen = pygame.display.set_mode((imp.larghezza_schermo, imp.altezza_schermo),DOUBLEBUF | OPENGL,imp.depth) return screen except IOError: print ("Impossibile inizializzare Pygame") exit() ######################################################################### # Funzione per il salvataggio delle impostazioni. File : impostazioni.pkl def salvataggio_imp(): try: stream = open("data/impostazioni.pkl", "w") pk = cPickle.Pickler(stream) imp = impostazioni() pk.dump(imp) stream.close() pk.clear_memo() except IOError: print ("Impossibile creare file di configurazione") exit() ################################################## # Funzione che aggiorna le impostazioni di sistema def aggiorna_imp(w,h,full,buff,hw,opengl): try: stream = open("data/impostazioni.pkl", "w") pk = cPickle.Pickler(stream) imp = impostazioni() imp.larghezza_schermo = w imp.altezza_schermo = h imp.full = full imp.bool_hw = hw imp.bool_buff = buff imp.bool_opengl = opengl pk.dump(imp) stream.close() pk.clear_memo() except IOError: print ("Impossibile creare file di configurazione") exit() def run(): try: stream = open("data/impostazioni.pkl", "r") except IOError: salvataggio_imp() Schermo = caricamento_imp() Altezza_s = Schermo.get_height() Larghezza_s = Schermo.get_width() pygame.mouse.set_visible(False) sfondo_erba = pygame.image.load("data/grass3_cyc.jpg").convert() sfondo_erba_scalato = pygame.transform.scale(sfondo_erba, (Larghezza_s,Altezza_s)) personaggio = giocatore("27382_1174921384",48,32, (320,240), None) global fps global orologio global tempo_passato global speed speed = 30.0 orologio = pygame.time.Clock() fps = 60 Ingame = ingame(personaggio, Schermo, sfondo_erba_scalato) Main = main_menu(Schermo, Altezza_s, Larghezza_s, Ingame) pygame.key.set_repeat(100, 30) while (True): for event in pygame.event.get(): Eventi(event,Main) tempo_passato = tps(orologio,fps) mouse_x_y = pygame.mouse.get_pos() Main.render(Schermo,tempo_passato,mouse_x_y) pygame.display.flip() if __name__ == "__main__": run()
Analisi
- Eventi
La funzione che gestisce gli eventi dovrà richiamare funzioni presenti all’interno della classe menù. Quindi, in base al tasto premuto, si effettueranno le opportune chiamate, come per esempio ad action_p per muovere il personaggio.
- Caricamento
La funzione di caricamento delle impostazioni iniziali, inizializza sia il mixer che la libreria pygame, per poi aprire una finestra coerentemente con i flag impostati nel file. Le configurazioni sono molte e questo può essere il modo peggiore per controllarle; comunque sia è il più semplice da capire.
Naturalmente controlliamo se non ci sono errori durante l’apertura del file, perché altrimenti insorgeranno sicuramente dei problemi che non permetteranno l’apertura del gioco.
- Salvataggio
Il salvataggio memorizza semplicemente il nostro oggetto impostazioni scrivendo il file con cPickle. L’apertura dello stream per la scrittura è sempre controllata.
- Aggiornamento
L’aggiornamento delle impostazioni è ancora più semplice da capire. Infatti basta leggere il file con cPickle aprendo uno stream e successivamente cambiare i membri dell’oggetto impostazioni salvato. Una volta fatto questo lo sovrascriviamo, cancellando quindi quello che c’era prima nel file e il gioco è fatto.
- Main
Unica nota nel main è che, inizialmente controlliamo se il file esiste. Infatti non è possibile leggere un file se non esiste e quindi rilascerà un errore; sfruttiamo quindi questa opzione per creare per la prima volta il nostro file impostazioni, che genera una configurazione di base secondo l’inizializzazione della classe che abbiamo già visto negli articoli precedenti.
Per il resto, nella run non ci dovrebbe essere niente di nuovo.
Conclusioni
Con questo ultimo articolo abbiamo visto come salvare le nostre impostazioni, come caricarle e come creare dei salvataggi di gioco. Se il tempo me lo permette, rilascerò oltre ad i sorgenti di questo esempio, anche quelli con le modifiche che apporterò successivamente (aggiornerò i link mano a mano che effettuo i cambiamenti).
Ringrazio tutti per le tante idee che mi avete dato e spero di continuare a scrivere pezzi interessanti e di utilità.
Sorgenti
- Esempio senza modifiche : http://dl.dropbox.com/u/16546001/AD/Loading%20senza%20modifiche.rar
- Esempio con collezionista e bibliotecario (Vedere articoli data manager) : http://dl.dropbox.com/u/16546001/AD/Loading%20cb.rar
Scusa per l’OT: per alcune cose vorrei passare a Phyton, solo che lo trovo un linguaggio interpretato piuttosto lento; esiste un qualche compilatore che possa trasformare i suoi script in codice nativo (compilato 32 e/o 64bit) o che faccia le veci di un compilatore JIT come ne esistono per altri linguaggi?
Grazie mille per eventuali info.
“solo che lo trovo un linguaggio interpretato piuttosto lento;”
porgila a CDMAURO questa domanda….
Bisognerebbe sempre contestualizzare: lento rispetto a cosa? Ad altri linguaggi come C, C++, Java? Sicuramente.
Quando scrivo codice, però, non mi pongo inizialmente la questione della velocità.
Mi metto sempre all’opera per risolvere il problema. Con la soluzione in mano effettuerò dei test per analizzare il comportamento del progetto e verificare se effettivamente ci sono rallentamenti o parti del codice che hanno REALMENTE bisogno di prestazioni migliori.
In questo caso la prima strada che percorro è quella algoritmica: cerco una soluzione che mi permetta di ottenere i risultati desiderati.
Se ciò non dovesse verificarsi, provo a utilizzare un compilatore JIT (c’è psyco http://psyco.sourceforge.net/ anche se è un progetto vecchio; altrimenty pypy ha fatto passi da gigante http://codespeak.net/pypy/dist/pypy/doc/ e se continua così diverrà la nuova implementazione mainstream / ufficiale del linguaggio).
Se anche così non bastasse, le parti critiche potrebbero essere compilate in C con soluzioni come cython http://www.cython.org/ , con le quali si ottengono ottimi risultati.
Se ancora non fosse soddisfacente, potrei anche scrivere direttamente in C (quindi senza “intermediari” com Cython) i pezzi di codice critichi. O anche in assembly.
Arrivato a questo punto se ci fossero ancora problemi avrei qualche dubbio sul progetto di per sé, che magari ha pretese troppo elevate a prescindere dal linguaggio e dalle soluzioni adottate.
Comunque dico subito che in più di 6 anni di lavoro con Python mi sono fermato QUALCHE VOLTA alla prima strada: quella della ricerca di un algoritmo migliore.
E vi assicuro che non ho sviluppato scriptini da due soldi, ma per lo più realizzo server (che, appunto, servono richieste; anche numerose).
Questo perché generalmente il problema prestazionale è, appunto, l’ultimo dei problemi, e spessissimo sovradimensionato e stimato.
Anzi, posso affermare tranquillamente che troppo spesso vedo sviluppare progetti con l’ansia da prestazione (“deve andare veloce!”), senza nemmeno sapere cosa sia un profiler e quando ha senso utilizzarlo…
Per rispondere all’unica domanda di Franci, c’è un progetto ancora in lavorazione, ma che dà già dei buoni risultati. Si chiama Shed Skin: http://code.google.com/p/shedskin/
In alternativa se l’esigenza è solo quella di impacchettare il codice Python in un eseguibile, ci sono un paio di progetti molto utilizzati: Py2Exe http://www.py2exe.org/ e PyInstaller http://www.pyinstaller.org/ .
Questo se le prestazioni non sono un problema (o, al limite, si fa ricorso a una delle soluzioni esposte prima, e poi si impacchetta il tutto con uno di questi due).
Spero di aver chiarito i dubbi, e scusate l’OT.
Aggiungo all’ottima lista di Cesare swig e sip:
http://www.swig.org/
http://www.riverbankcomputing.com/software/sip/intro
Permettono in maniera estremamente semplice di interfacciare con estrema semplicità codice c c++ con linguaggi di scripting di alto livello.
Per quanto riguarda il bundling del codice ho utilizzato su linux cx_freeze (multipiattaforma):
http://cx-freeze.sourceforge.net/
ed ultimamente sto seguendo con un certo interesse questo progetto che però non ho ancora provato:
http://www.stanford.edu/~pgbovine/cdepack.html
semplicissimamente, in maniera estremamente semplice, con estrema semplicità. Se mi viene in mente qualche ripetizione la aggiungo. :D
In effetti una piccola guida su py2exe e/o simili volevo farla, ma ora con tutte queste idee non so come procedere…
OT : momento di riflessione -.-
Puoi sempre pensarci dopo aver completato la serie di articoli sui giochi. O, per lo meno, di quelli in 2D. ;)
Cesare Di Mauro wrote:
> Quando scrivo codice, però, non mi pongo inizialmente
> la questione della velocità.
Io ho sempre avuto la fisima del piccolo e specializzato a tutti i costi, sempre che non vada ad influire troppo sui tempi di sviluppo.
Tieni conto che io sono uno studente e non programmo per lavoro o per progetti grossi, il mio interesse primario è sviluppare dei tool per me e/o pochi altri che possano risolvermi dei piccoli problemi di produttività (quindi non si pongono troppo la problematiche, per esempio quelle dell’andamento asintotico degli alg. di ordinamento che impari in algoritmi e strutturi dati con il C come linguaggio per progetto finale) o di gestione sistema ma, lo devono fare con poche risorse e in generale essere efficienti. Forse è anche per questo che ho sempre odiato Java (l’ho fatto a Programmazione I) e soci con le loro virtual machine (eventualmente se ne riparlerà in ambito lavorativo).
In poche parole, desiderio di programmini efficienti per Win e linux, anche con gui, ma che allo stesso tempo si possano sviluppare in maniera piuttosto veloce.
Su questo versante non avrei problemi, visto che uso da tempo la combinata veloce ed efficiente di euphoria+c, è solo che volevo provare a passare ad un ambiente più diffuso e usato da tanti altri (per tutta una serie di ragioni), proprio come Phyton.
Comunque grazie, mi avete dato dei link molto interessanti.
Emanuele Rampichini wrote:
> ed ultimamente sto seguendo con un certo interesse questo
>progetto che però non ho ancora provato:
> http://www.stanford.edu/~pgbovine/cdepack.html
Interessante, un discorso di portabilità per linux, spero possano saltare fuori soluzioni interessanti così come ce ne sono di veramente ottime su Win (nel caso che il programma non sia già nativamente portabile).
Sono sempre stato un fanatico della portabilità, il portarsi dietro su supporti usb (per fortuna esistono possibilità per crittografare il contenuto di un drive portatile ma che il tutto si possa decriptare al volo su un computer ospite anche senza la necessità di richiedere permessi admin) dei programmi che una volta lanciati su un computer ospite non lascino alcuna traccia nel registro e nelle dir di sistema (%userprofile%, %appdata%, ecc.) è sempre stata una cosa agognata da tantissimi (praticità e backup veloci in primis) sin dall’avvento di Win95.
ciao
@Franci:
Ero così anch’io, fino a un po’ di anni fa. Poi ho smesso di dannarmi pensando sempre alle prestazioni, e ho ricominciato a vivere.
Ma questo lo potrai dire solo se effettivamente l’applicazione non risponderà secondo le tue aspettative. Una volta completata, quindi.
Sì, ma se poni l’efficienza come prerequisito, non ne uscirai più: ti troverai sempre legato a un certo ambiente di programmazione.
L’efficienza, come dicevo, va sempre considerata col prodotto in mano, e dimostrata con dati reali. Rilevato ciò, si provvederà all’ottimizzazione delle sole parti critiche, come avevo scritto nel precedente commento.
Insomma, l’efficienza non può essere il fine dello sviluppo di un’applicazione.
Specialmente se parliamo di GUI i tempi di reazione di un’applicazione sono generalmente trascurabili rispetto a quelli dell’essere umano.
Comunque t’invito a provare Python, ma senza pregiudizi. Vedrai che il tuo livello di produttività aumenterà notevolmente. Inoltre, almeno per me, ho ritrovato il piacere di programmare, grazie alla sua immediatezza, chiarezza ed enorme flessibilità (non hai idea delle cose carine che ti permette di fare). :P
@ Franci
Se ti può rincuorare, anche Don Knuth la pensa così :
“Se ottimizzi tutto, sarai sempre infelice.”
Se non sbaglio, è proprio lui che sostiene: ottimizzare precocemente il codice, è la strada verso il male.
Cerca di non farti attrarre troppo dal lato oscuro… :D
@Cesare Di Mauro/Mirco Tracolli:
non voglio ottimizzare subito il codice e/o arrovellarmi prematuramente in tal senso, voglio solo un ambiente di sviluppo che sia produttivamente veloce ma che allo stesso tempo sia più efficiente (prestazioni/risorse usate), rispetto alle attuali soluzioni di “default” con le virtual machine, nei risultati prodotti (questo è quello che mi garantisce la combinata postata nel msg precedente, oltre ad essere anche immediatamente win/linux risultante). Python, da quel poco che ho ancora visto, mi piace come approccio, spero che le soluzioni appartenenti ai link postati portino presto dei frutti.