«[Figlio dell'uomo] Porgi l'orecchio e ascolta le parole di KGB
e applica la tua mente alla SUA istruzione
» Pv. 22,17

Qui si straparla di vari argomenti:
1. Il genere dei pezzi è segnalato da varie immagini, vedi Legenda
2. Per contattarmi e istruzioni per i nuovi lettori (occasionali e non) qui
3. L'ultimo corto è questo
4. Molti articoli di questo blog fanno riferimento a definizioni e concetti che ho enunciato nella mia Epitome gratuitamente scaricabile QUI. Tali riferimenti sono identificati da una “E” fra parentesi quadre e uno o più capitoli. Per esempio: ([E] 5.1 e 5.4)

martedì 11 settembre 2012

MapPanel

Come scrissi in Udacity e CS258 ho intenzione di mettere in pratica quanto appreso sul debugging.
Però, siccome non mi andava di modificare un progetto esistente per aggiungervi “assert” e JUnit varie, ho deciso di partire da zero con un nuovo programma.

La realizzazione di questo programmino mi pare abbastanza interessante e quindi provo a farci un post raccontandone la storia...

L'idea era di scrivere un semplice programma che visualizzasse una mappa su più livelli: l'idea è che se nella mappa c'è una torre voglio poter scorrere tutti i piani. Detto così sembra complicato ma invece è semplice: mi limito a fare tante mappe bidimensionali con due tasti per salire e scendere di livello.
L'altra complicazione che mi sono imposto è che ci possono essere oggetti più grandi di un quadrato: in particolare nel mio esempio c'è una tenda che ne occupa due.

Inizialmente avevo usato un array bidimensionale per memorizzare il tipo di terreno con l'aggiunta di una lista con tutti gli oggetti extra (palizzata, tenda e rospo) e relative coordinate.
Poi ci ho ripensato e ho usato direttamente un array bidimensionale di liste che mette insieme terreni e oggetti “extra”: in pratica ogni quadrato della mappa ha la sua lista di immagini che devono essere disegnate sopra di esso. Per ogni immagine tengo anche traccia del suo livello in maniera da disegnarla in base al “piano” correntemente visualizzato.
Un'interessante complicazione è data dagli oggetti che occupano più di un quadrato (la “tenda” nel mio caso). Inizialmente infatti il modo in cui disegnavo la mappa era il seguente:
Con due “for” nidificati, da zero alla dimensione della mappa, scorrevo tutte le liste corrispondenti al “quadrato” corrente e disegnavo i vari oggetti. Il problema che avevo con la tenda era che, estendendosi questa verso il basso, quando passavo a disegnare il quadrato inferiore finivo per cancellare metà tenda!
Sul momento avevo pensato di bufferizzare gli oggetti multi-quadrato ma avevo la netta sensazione che si potesse fare meglio. E infatti! Basta invertire la direzione in cui si disegna la mappa e il problema è risolto (*1)!

Versione con bug

Versione corretta

Per complicarmi la vita ho deciso che certe immagini (i terreni in pratica) venissero ruotati casualmente dal programma in maniera da nascondere eventuali pattern. Allo stesso scopo, dello stesso oggetto, ad esempio l'erba (*2), possono essere presenti più versioni e il programma ne selezionerà una particolare quadrato per quadrato...

Per gestire tutte queste cose ho usato le seguenti 8 classi (ma almeno di due avrei potuto fare a meno):
  1. Core: contiene il main, fa le inizializzazioni e crea la GUI
  2. Constants: contiene costanti usate dalle varie classi. Avrei potuto metterle in Core ma ho preferito così...
  3. Dado: è una classe che mi trascino di progetto in progetto dove tengo diversi metodi per generare numeri pseudocasuali. Volendo avrei potuto semplicemente copiare il metodo che mi serviva nella classe che lo utilizza...
  4. MapPanel: un componente che estende un JPanel e che uso come superficie per disegnare...
  5. MapElements: gestisce la collezione di MapElement (vedi poi) con alcune funzioni di utilità. Avrei potuto incorporare queste funzionalità in Core ma mi pareva più pulito fare così...
  6. MapElement: carica in memoria le varie immagini (comprese quelle con più versioni) e su richiesta restituisce, eventualmente casualmente (quando ce ne sono più versioni o è abilitata la rotazione), un'immagine specifica. Contiene anche dati extra sull'immagine.
  7. MapTile: contiene semplicemente un immagine e il livello a cui si riferisce
  8. KGBMap: contiene il famigerato vettore bidimensionale di liste di MapTile. In pratica contiene la struttura della mappa
Nei prossimi giorni voglio fare ancora qualche miglioria (estendere la mappa e aggiungere oggetti e livelli) e poi inizierò a fare il debugging con JUnit e coverage testing...
Credo che sarà molto interessante perché non ho ben chiaro come fare e sono sicuro che mi troverò ad affrontare numerosi problemi inaspettati: vedremo cosa verrà fuori!

Ah! se qualcuno è interessato al codice (Java) mi faccia sapere: al momento è abbastanza squallido e quindi non l'ho pubblicato...

Nota (*1): con la condizione che gli oggetti multi-quadrato vengano memorizzati sempre nella lista corrispondente al quadrato più in alto a sinistra che li contiene: cosa intuitiva e che già facevo...
Nota (*2): l'ho implementato e nella versione fatta ieri, con i quadrati 32x32 pixels, mi funzionava già. Oggi però sono passato a immagini di 64x64 pixels e non ho avuto voglia di disegnare due versioni dell'erba (quindi le immagini allegate mostrano un solo tipo di erba).

Nessun commento:

Posta un commento