Pillola di BASIC #05 – “PRINT vs POKE”

(articolo di Davide Fichera)

Sorgenti in formato .D64

Print e Poke

Per scrivere caratteri a schermo il BASIC V2 ci offre fondamentalmente due alternative: quella del PRINT, con tutti i suoi caratteri PETSCII e quelli di controllo (cursore su, giù, destra, sinistra, home, clear, reverse on, ecc.) , oppure quella del POKE, che però ci permette di scrivere solo un carattere su schermo alla volta. Il POKE però ha il vantaggio che può scrivere da qualsiasi parte dello schermo senza andare ad utilizzare scomodi caratteri di controllo, tipo quelli che si ottengono tramite i tasti freccia.

Se vogliamo, ad esempio, scrivere il carattere “A” alla colonna 5 e alla riga 8 tramite il comando POKE dovremo scrivere:

10 POKE 1024+8*40+5,1

se invece opteremo per il PRINT scriveremo il seguente codice:

10 PRINT”{home}{down*8}{right*5}A”

Fig. 1 – I due metodi per stampare un carattere a schermo.

La prima versione calcola la posizione che il carattere avrà a schermo utilizzando una formula, dove il 1024 rappresenta la locazione di memoria del carattere più in alto a sinistra sullo schermo, 8*40 calcola la posizione relativa del primo carattere della 8° riga dello schermo e infine aggiungendo il 5 ci spostiamo di ulteriori 5 caratteri sulla destra.

La seconda versione è invece più immediata da comprendere perché semplicemente posiziona il cursore in alto a sinistra con il carattere di controllo home e poi lo sposta di 8 posizioni giù e di 5 posizioni a destra con degli ulteriori caratteri di controllo.

La prima scelta però, per certi versi, risulta più veloce, elegante e di più facile lettura rispetto alla seconda, dove i caratteri di controllo compaiono tutti insieme e sono difficili da interpretare al volo (per un occhio non particolarmente avvezzo a quei caratteri speciali).

Stampa di caratteri in posizioni generiche

Immaginiamo ora di voler posizionare un carattere ovunque sullo schermo tramite delle coordinate X e Y precedentemente assegnate. Come fare ciò nei due casi del PRINT e del POKE? Per quanto riguarda la versione con POKE sarà facile modificare il nostro codice in questo modo:

10 POKE 1024+Y*40+X,1

Per quanto riguarda invece la versione con PRINT dovremo innanzitutto definire una variabile stringa riempita con dei caratteri di controllo freccia giù (24 caratteri) e poi scrivere un PRINT che con un opportuno mix di caratteri di controllo riesca a posizionare correttamente il cursore prima di stampare il carattere voluto. Avremo quindi:

10 D$=”{down*24}” 
20 PRINT”{home}”;LEFT$(D$,Y);TAB(X);”A”;

Analizzando la seconda linea vediamo come innanzitutto il cursore venga posizionato sulla parte in alto a sinistra dello schermo col carattere di controllo {home}, che rappresenta la nostra origine degli assi (x=0, y=0), successivamente l’istruzione LEFT\$ preleva dalla variabile D$ un numero Y di caratteri di controllo “cursore giù”, poi il TAB posiziona il cursore orizzontalmente e infine viene stampato il carattere “A”.

La seconda alternativa sembra proprio più complessa e meno immediata della prima, ma questa rubrica è fondamentalmente orientata alla performance piuttosto che all’eleganza, quindi cerchiamo di capire in quali casi conviene preferire un’alternativa piuttosto che l’altra.

Casi d’uso

Fig. 2 – I 4 casi d’uso analizzati.

A tal fine ho preparato alcuni casi d’uso e ho messo a confronto i due metodi evidenziando per ciascuno di essi quale fosse il più performante.
I casi d’uso sono 4: stampa di un singolo carattere monocolore, stampa di una coppia di caratteri affiancati monocolore, stampa di un gruppo di 4 caratteri (2 x 2) monocolore, stampa di un gruppo di 4 caratteri colorati (diversamente). Qui sotto vediamo le schermate di questi casi d’uso. I programmi stampano rispettivamente 500 caratteri, 500 coppie di caratteri e 500 x 4 caratteri (negli ultimi 2 casi). Analizzando i primi tre casi d’uso e ottimizzandoli al meglio ho ricavato un grafico che evidenzia come il metodo del POKE è preferibile a quello del PRINT solo fino alla stampa di 1 o 2 caratteri, per gruppi più grandi il PRINT risulta vantaggioso.

Fig. 3 – Andamento tempi esecuzione programma al variare del numero di caratteri stampati.

Un discorso a parte va fatto per i gruppi di caratteri colorati perché mentre col PRINT possiamo stampare in una sola istruzione più caratteri del colore che vogliamo (tramite i codici di controllo), col POKE dobbiamo scrivere ben 8 (!) POKE per ottenere lo stesso risultato: 4 per il colore e 4 per i caratteri. E’ facile quindi immaginare che il PRINT è enormemente più conveniente. Se però i colori non sono fissi per ogni gruppetto di 4 caratteri allora il vantaggio del PRINT rispetto al POKE non è così scontato e dipende da come si implementa la stampa. Tornando però all’ultimo caso analizzato i risultati sono stati questi:

Fig. 4 – Tempo impiegato per stampare 500 gruppi da 4 caratteri colorati a schermo.

Conclusioni

In conclusione posso affermare che il PRINT è sempre preferibile al POKE tranne nel caso in cui bisogna stampare un solo carattere e cambiarne eventualmente il colore. Per gruppi di caratteri più grossi (da 4 in su) conviene invece sempre il PRINT.

A titolo d’esempio riporto la schermata di un videogioco che ho sviluppato pochi anni fa, realizzato totalmente in BASIC, e la cui grafica è basata su gruppi di 4 caratteri PETSCII per creare le cosiddette TILES (mattonelle), che formano lo scenario di gioco. Ovviamente in questo caso ho usato il PRINT.

Fig. 5 – Gravity Snake

Per chi fosse interessato, riporto inoltre qui sotto le schermate dei due listati del caso d’uso con i 4 caratteri colorati, nella versione col POKE e col PRINT rispettivamente.
In alternativa potete anche scaricare i sorgenti dal link a inizio articolo.

FIg. 6 – Listati programmi

Have your say