Righe di stato

Uno degli usi più comuni dello Z-assembly nei giochi Inform è quello di creare delle righe di stato personalizzate. Questa cosa non funziona in Glulx Inform, visto che non riconosce lo Z-assembly. Invece dovrete usare gli equivalenti Glk -- che non sono opcode diretti, ma sono delle routine come altre.

La riga di stato è una tale tradizione IF da richiedere l'impegno di qualche sforzo. Un gioco standard Inform divide una porzione dello schermo per mostrare la stanza in cui si trova il personaggio, il punteggio del giocatore ed il numero di mosse fatte. Per cambiare la cosa, il programmatore deve inserire la riga "Replace DrawStatusLine;" all'inizio del programma (metterla dopo la lista delle costanti funziona, come in qualunque altro posto). Quindi il programmatore deve fornire una routine DrawStatusLine() alternativa. Ma qui è dove le cose differiscono un po'.

In Inform standard, il comando per creare la finestra della riga di stato (@split_window) si trova all'interno della routine DrawStatusLine() della libreria. Se volete sostituirla, dovete inserire il comando @split_window da voi. Se volete eliminarla, tutto quello che dovete fare è sostituire DrawStatusLine() con una routine vuota, come:

   [ DrawStatusLine; ];

Non è abbastanza in Glulx Inform. Nella sezione Glulx della libreria bi-piattaforma, la finestra di stato viene divisa in GGInitialise(), non in DrawStatusLine(). Questo significa che se usate una DrawStatusLine() vuota, la riga di status sarà vuota, ma la finestra sarà ancora presente, facendosi beffe di voi. Così dovete intercettare il comando che crea la finestra della riga di stato usando il punto di ingresso InitGlkWindow(), come segue:

[ InitGlkWindow winrock;
   switch (winrock) {
      GG_STATUSWIN_ROCK: rtrue;
   }
   rfalse; ! levare questa riga porta ad uno sporco crash!
];

Se volete mantenere la riga di stato, ma volete fornire le vostre istruzioni, ci sono una serie di linee guida da seguire. Prima di tutto, se volete allocare più di una riga per la finestra di stato, fatelo in InitGlkWindow(), così:

[ InitGlkWindow winrock;
   switch (winrock) {
      GG_STATUSWIN_ROCK:
         gg_statuswin_size = 2; ! o quante righe volete
   }
   rfalse; ! levare questa riga porta ad uno sporco crash!
];

Poi scrivete una routine che sostituisca DrawStatusLine(), che inizi con il codice seguente:

   ! Se non abbiamo una riga di stato, non dobbiamo cercare di ridisegnarla.
   if (gg_statuswin == 0)
      return;

   ! Non dobbiamo farlo neanche se non esiste una locazione per il giocatore
   if (location == nothing || parent(player) == nothing)
      return;

La prima riga dopo quella deve essere "glk_set_window(gg_statuswin);", per impostare la finestra nella quale si vuole visualizzare la riga di stato, e l'ultima riga deve essere "glk_set_window(gg_mainwin);", per essere sicuri che il programma continui a mettere il testo della storia nel posto giusto. In mezzo potete visualizzare quello che volete, sebbene il processo da seguire sia leggermente differente da quello che si usa per una finestra di testo.

Ricorderete che una finestra a griglia di testo è una specie di tavola dello Scarabeo: sebbene i bordi tra le caselle non siano visibili, la finestra è composta da una griglia di caselle, con ognuna che può contenere un carattere -- lettere, numeri, punteggiatura. Ogni casella ha un paio di coordinate associate, una coordinata X ed una coordinata Y. La coordinata X indica a quante caselle di distanza si trova la casella corrente dal bordo sinistro della finestra; la coordinata X delle caselle sul bordo sinistro è 0. La coordinata Y indica a quante caselle di distanza si trova la casella corrente dal bordo superiore della finestra; la coordinata Y delle caselle sul bordo superiore è 0. (Questa cosa differisce dal normale Inform, dove l'angolo in alto a sinistra non è (0,0), ma (1,1)). Per selezionare il posto in cui cominciare a stampare si usa il comando glk_window_move_cursor(), che richiede tre argomenti: il nome della finestra in cui stampare, la coordinata X della casella da cui si comincia a stampare e la coordinata Y della casella da cui si comincia a stampare. Mentre stampate il cursore si sposta automaticamente -- non avete bisogno di spostarlo voi per stampare la lettera successiva di una parola. Così, il codice seguente:

   glk_window_move_cursor(gg_statuswin, 3, 0);
   print "Ora: "

metterà la lettera "O" alla locazione (3,0), "r" a (4,0), "a" a (5,0), i due punti a (6,0) ed uno spazio a (7,0), lasciando il cursore a (8,0). Probabilmente dopo verrà del codice che stamperà l'ora corrente.

Una cosa da tenere presente è che non tutti quelli che giocheranno il vostro gioco avranno la stessa quantità di spazio di schermo allocata da Glulxe: la finestra della riga di stato potrebbe essere lunga 120 caratteri sulla macchina di una persona, e 40 su un'altra. O qualcuno potrebbe ridimensionare la propria finestra di Glulxe da una larghezza di 120 caratteri a 40 nel corso di una partita. Potete, comunque, mettere del codice in DrawStatusLine() per sistemare queste cose (come, in realtà, viene già fatto nella routine standard). Semplicemente mettete delle variabili chiamate "width" e "height" nella dichiarazione della vostra DrawStatusLine(), ed inserite il seguente pezzo di codice nella routine:

   glk_window_get_size(gg_statuswin, gg_arguments, gg_arguments+4);
   width = gg_arguments-->0;
   height = gg_arguments-->1;

Quindi potete fare tutti gli aggiustamenti che ritenete opportuni. Diciamo che state lavorando ad un gioco chiamato Crunch, Crumple and Stomp e volete mettere un indicatore di fame nella riga di stato, iniziando da colonna 40, che visualizzi "PIENO", "SAZIO", "AFFAMATO", "VORACE". Questo ci porta fino a colonna 47. Alcune persone, però, potrebbero giocare con meno di 48 colonne, così volete che l'indicatore compaia solo se c'è abbastanza spazio (visto che non volete che l'indicatore tagli a metà le parole). Si usa semplicemente del codice come questo:

   if (width > 48) { ! imponiamo un po' di chiarezza
      glk_window_move_cursor(gg_statuswin, 40, 0);
      switch (gojira.fame) {
         0: print "PIENO";
         1: print "SAZIO";
         2: print "AFFAMATO";
         3: print "VORACE";
      }
   }

Notate che le possibilità hanno differenti lunghezze. Se cercate di sovrascrivere "AFFAMATO" con "PIENO" ottenete "PIENOATO", a meno che riempiate a spazi ogni possibilità per ottenere per tutti la stessa lunghezza, o inserite la riga "glk_window_clear(gg_statuswin);" subito dopo la vostra chiamata a "glk_set_window(gg_statuswin);". La libreria usa il secondo metodo.

Sono possibili degli aggiustamenti migliori che il non stampare del tutto le voci che non entrano -- potremmo aver scritto un codice elaborato che abbrevia le cose quando la riga di stato diventa più piccola, ad esempio. La cosa simpatica è che, visto che DrawStatusLine() viene chiamato ad ogni turno, non dovete stare dietro a HandleGlkEvent() per avere a che fare con i ridimensionamenti, come dovete fare per la grafica. Altro su questo nelle prossime sezioni.


Prossima sezione: Visualizzare immagini PNG e JPEG
O ritorna al sommario