Cerca con Google

Translate

17 luglio 2015

Tutorial 12 (Difficile) Custom TinyWebDB, salvataggio tabellone HighScore su cloud in MIT App Inventor - Parte 1


Continuiamo a vedere una possibile applicazione del Custom TinyWebDB.

In questo tutorial andremo a creare un'istanza
personalizzata del TinyWebDB che ci permetterà in maniera molto semplice di memorizzare sul cloud App Engine una lista dei migliori punteggi realizzati nel nostro gioco creato con MIT App Inventor 2.

La parte difficile del tutorial è quella relativa alla creazione del Custom TinyWebDB, si potevano infatti pensare diversi approcci al problema, se inserire la logica della gestione degli high-score in App Inventor oppure delegare il tutto all'applicazione in Python che gira su Google App Engine.

Visto che sto studiando anche un pò di Python mi son voluto cimentare in questo secondo metodo, il vantaggio è che la parte da inserire in App Inventor è molto più semplice...

In pratica nel nostro gioco creato con App Inventor dobbiamo solamente memorizzare il punteggio del giocatore ed il suo nome.
Questa coppia di valori andrà inserita nella lista costruita e memorizzata nel TinyWebDB.

L'applicazione che gira su Google App Engine prenderà la lista completa di coppie nomi-punteggio, li metterà in ordine (dal più alto al più basso) e restituirà ad App Inventor la nuova lista (con il nuovo nome-punteggio) ordinata pronta per essere visualizzata nel vostro gioco.
In questo tutorial riutilizzeremo il gioco creato qui (SubMarine Shooter) e ci aggiungeremo uno screen in cui inserire e visualizzare gli high-score globali.

Partiamo dalla parte da inserire in App Inventor, ho modificato il gioco per fare in modo che la partita duri 60 secondi (usando un componente Clock), dopo questo tempo il punteggio verrà memorizzato e passeremo allo screen "HighScore".

Questo il nuovo codice in Screen1 (click per ingrandire):


In particolare all'evento Clock1.Timer (che viene generato ogni 0,5s) andiamo a decrementare il contatore globale del tempo rimasto, quando arriva a zero apro lo screen "HighScore" e passo il valore del punteggio realizzato a questo screen:


Vediamo ora la parte relativa al nuovo screen "HighScore", prima il Design editor:


Come vedete il layout è abbastanza semplice, in alto un tasto per riavviare la partita (più due tasti per il debug per i vostri test che leggono il DB completo e salvano un record)
Poi alcune label per visualizzare il punteggio appena realizzato, una textbox "Tb_PlayerName" dove salvare il nome del giocatore.
Un button "Bn_SaveScore" per salvare il punteggio nel tabellone globale degli HighScore.
Ed ovviamente il componente TinyWebDB che si collega nel mio caso al custom serviceURL (https://aihighscoredb-999.appspot.com/) e che svolgerà il grosso del lavoro...
Più un notifier per il dialogo con l'utente.

Passiamo al blocks editor (vi consiglio di aprire questa immagine a schermo intero cliccandoci sopra):


Vediamo cosa accade appena raggiungiamo lo screen "HighScore".

  1. Viene generato l'evento "Screen1.Initialize", prendiamo da "Screen1" il punteggio appena realizzato, lo salviamo in "PlayerHighScore" e lo visualizziamo nella label "Lb_PlayerScore"
  2. Chiamiamo il metodo "GetValue" del TinyWebDB con il tag "HighScoreList" per caricare la lista annidiata contenente i punteggi già realizzati.
Questa lista è memorizzata nel seguente modo [['Nome1', 'Punteggio1'], ['Nome2', 'Punteggio2']...] ovvero ogni elemento della lista è a sua volta una lista composta da due elementi "nome"-"valore".

Quando il TinyWebDB ha caricato il valore relativo al tag "HighScoreList" viene generato l'evento "TinyWebDB1.GotValue", in questo evento abbiamo il codice sia per la memorizzazione del punteggio che per la lettura dei punteggi già presenti.
Controlliamo l'operazione da fare con il flag booleano "shouldUpdateDb" se uguale a "False" vogliamo leggere dal Db, se "True" vogliamo anche scrivere il nuovo punteggio.

Quindi guardiamo la parte evidenziata al punto 3 (siamo ora in modalità "lettura")
Semplicemente carichiamo nella label "Lb_HighScoreList" con una join tutta la lista letta dal TinyWebDB, per ogni elemento andiamo a capo con "\n" (se volete formattare diversamente il tabellone lo potete fare, usando ad esempio una select list item per caricare i nomi in una colonna ed i punteggi in un'altra...)

Come vedremo in seguito, non ci dobbiamo preoccupare di ordinare la lista perchè questa sarà SEMPRE in ordine di punteggio, l'ordinamento viene fatto in Google App Engine (lo vedremo nella parte 2 del tutorial...)

Il risultato nella nostra app sarà che verrà visualizzato il tabellone degli HighScore in questo modo:


Andiamo ora a vedere cosa succede quando il giocatore clicca sul pulsante "Invia il tuo record", anche qui mettete a tutto schermo la seguenete immagine del blocks editor:


Quando il giocatore clicca sul pulsante viene generato l'evento "Bn_SaveScore.Click":

  1. Per prima cosa controlliamo che il punteggio sia maggiore di 0 e che l'utente abbia inserito un nome nella textbox, se così non fosse mostriamo un notifier
  2. Impostiamo la flag "shouldUpdateDB" a True perchè vogliamo scrivere sul DB
  3. Per prima cosa ci dobbiamo assicurare di avere la lista più aggiornata degli HighScore (perchè magari ci sono altri giocatori che stanno giocando ed hanno inviato il loro punteggio mentre noi stavamo ammirando il nostro...). Quindi chiamiamo la "GetValue" per aggiornare i dati.
  4. Quando la lista HighScore è stata letta viene generato l'evento "TinyWebDB1.GotValue", aggiungiamo la nostra coppia  (Nome,Punteggio) alla lista globale degli HighScore appena letta usando il metodo "add items to list", dove ovviamente la lista su cui lavoriamo è "HighScoreList". Il nostro punteggio viene inserito in fondo alla lista (l'ordinamento ricordate verrà fatto in GAE)
  5. A questo punto chiediamo di salvare la nuova lista chiamando il metodo "TinyWebDB1.StoreValue" dove ovviamente il tag deve essere "HighScoreList" ed il valore da memorizzare è la nuova lista annidiata dei punteggi "HighScoreList"
  6. A salvataggio avvenuto (non è inserita la gestione di possibili errori per mancanza di connessione, etc..., questo eventualmente lo lascio a voi...) viene generato l'evento "TinyWebDB1.ValueStored". Mostriamo un notifier per indicare l'avvenuto salvataggio del punteggio. Impostiamo il flag "shouldUpdateDB" a "false" perchè non vogliamo più scrivere sul DB e chiamiamo infine ancora la "GetValue" sul TinyWebDB per caricare la lista HighScore aggiornata (ed ordinata correttamente) con il nostro nuovo punteggio.
In questo modo abbiamo aggiunto il nuovo punteggio nell'elenco degli HighScore salvato sul cloud di Google App Engine!!!

Per la parte relativa ad MIT App Inventor 2 è tutto , nella prossima parte del tutorial vi spiegherò le modifiche che ho fatto all'applicazione Python che gira in GAE.
Non è strettamente necessario che capiate tutto, potreste semplicemente implementare i miei file nel vostro GAE ed implementare il codice in App Inventor e basta.
Vi consiglio comunque di continuare a leggere per capire meglio come funziona il tutto...

Continua alla Parte 2 - Il custom TinyWebDB - applicazione Python


Scarica il file sorgente .aia del gioco da QUA
Scarica il file compilato .apk del gioco da QUA




6 commenti:

  1. Hello friend Sebastiano, has some code finder app to put text with different colors in notes bloo.

    RispondiElimina
  2. Buongiorno Sebastiano!
    Ho un problema col TinyDb di app inventor2, non so se accetti il mio post in questa discussione ma credo sia quella più vicina al mio problema, in caso ti chiedo scusa già da adesso.
    Nella versione classic bisognava creare una nuova variabile che poi, come dicevi tu nel tutorial, sarebbe stata il nostro database. A questa veniva collegata una "make a list", perché nell'esempio si voleva creare una lista vuota da riempire successivamente. Questa nuova variabile veniva "presa" da Definition, un qualcosa che già non vedo in app inventor 2, e questo è il primo problema, perché non so adesso come devo fare. Il My Definition della versione classica che fine ha fatto? Da cosa è stato sostituito? C'è per caso un altro procedimento che non so o che non è stato ancora spiegato rispetto quello della versione classic?
    Grazie mille per l'aiuto e per i tuoi tutorial!!

    RispondiElimina
    Risposte
    1. Molto semplice, in App Inventor 2 trovi le definizioni delle variabili nel blocks editor, alla voce
      "Built-in"-"Variables"
      Per creare una variabile usi il blocco "initialize global name to"
      dove cambi "name" con il nome della tua variabile.
      Poi continui come con AI1, se vuoi mettendo il make a list per creare una variabile globale di tipo lista.
      Spero di essere stato chiaro! ciao!

      Elimina
  3. Grazie mille Sebastiano, con questo tutorial sono finalmente riuscito a realizzare una classifica online dentro il mio gioco. Anche se, ahimé, prima ero convinto di aver un super record personale ma sono stato subito relegato oltre il decimo posto del ranking mondiale (il mio gioco è scaricato principalmente negli States e in Canada). Ho dovuto solo fare una piccola modifica al codice python per eliminare il carattere \ nel campo descrizione in quanto viene utilizzato come sequenza di escape e quindi, come effetto collaterale, si aveva il raddoppio di tutti i \ ogni volta che veniva caricato un nuovo punteggio. Raggiunta la dimensione massima del campo tipo text, non era più possibile salvare un nuovo punteggio.

    Francesco

    RispondiElimina
    Risposte
    1. Ottimo, ero sicuro che qualcuno avrebbe usato questo metodo per creare il suo sistema di high-score nei suoi giochi!
      Sono contento che ti sia servito, ora mi sfugge ma cmq penso proprio che di sicuro c'è un modo per inserire anche lo \ come stringa nel nome dell'utente, penso che lo devi inserire nel codice python forse con '\' oppure "\" dovresti fare qualche esperimento!.
      Cmq buon app inventing!

      Elimina
  4. Ciao Sebastiano. Ho iniziato a seguirti da poco su YouTube e volevo farti i complimenti per i tuoi video tutorial. Ti pongo il mio problema. Ho scaricato la tua app sopraelencata (Submarine Shooter). Il gioco parte, ci posso giocare tranquillamente ed il tempo avanza. Il problema, avviene allo scadere del tempo....quando cambia schermata per passare in quella dove dovrei inserire il nome, appare il seguente messaggio d'errore; Titolo errore= Bad list argument to foreach. Descrizione errore= The second argument to foreach is not a list. The second argument is: *empty-string*. Tasto= End Application. Questo è quanto....da dire che io non ho modificato nulla nel blocks. Spero che tu mi possa aiutare, grazie mille...saluti Gianfranco.

    RispondiElimina