Nei precedenti articoli abbiamo lavorato con il punto e la linea, oggi lavoreremo con il cerchio e l’ellisse.
Istruzione circle
L’istruzione che impareremo ad usare per disegnare cerchi ed ellissi è circle.
Come abbiamo fatto per il punto e per la linea, anche in questo caso scriveremo un semplice programma per esplorare le potenzialità di questa istruzione.
''definizione della costante pi greco
const pi = 3.14159
screen 19, 32
color(rgb(0,0,0),rgb(255,255,255))
cls
''cerchio color giallo con centro identificato
''da coordinate assolute
circle (100,100), 50, rgb(255,255,0)
''cerchio color ciano con centro identificato
''da coordinate relative
circle step (50,50), 50, rgb(0,255,255)
''arco color magenta con estremi a 0 rad e pi/2 rad
circle step (50,50), 50, rgb(255,0,255), 0, (90*pi/180)
''ellisse color rosso
circle step (50,50), 50, rgb(255,0,0),,,0.5
''ellisse color verde piena
circle step (50,50), 50, rgb(0,255,0),,,0.25,F
sleep
Con l’aiuto dei commenti il codice è abbastanza intuitivo.
Gli unici aspetti dell’istruzione che meritano qualche nota in più sono:
i due argomenti che gestiscono gli estremi dell’arco che devono essere espressi in radianti (più sotto un utile schema per la conversione gradi/radianti);
l’argomento che gestisce la proporzione tra l’altezza e la larghezza dell’ellisse (nel caso del cerchio varrà ovviamente 1.0).
In realtà ciò che potremo effettivamente disegnare a video sarà soltanto una parte della linea retta: ovvero un segmento.
L’istruzione che utilizzeremo ci permetterà di costruire anche due figure geometriche: il quadrato e il rettangolo.
Istruzione line
In freeBASIC per tracciare un segmento si usa l’istruzione line.
Vediamo in un semplice programma i diversi modi di utilizzo.
screen 19, 32
''primo piano nero, sfondo bianco
color (rgb(0,0,0),rgb(255,255,255))
cls
locate 1: print "Istruzione line"
''1) segmento rosso orizzontale continuo
locate 3: print "1)"
line (25,40)-(500,40),rgb(255,0,0)
''2) segmento blu orizzontale con tratteggio irregolare
locate 5: print "2)"
line (25,70)-(300,70),rgb(0,0,255),,&b1110010011100100
''3) rettangolo verde vuoto con tratteggio regolare
locate 7: print "3)"
line (25,100)-(125,120),rgb(0,255,0),B,&b1111111100000000
''4) quadrato giallo pieno con le coordinate del
'' secondo vertice relative a quelle del primo vertice
'' e diagonale magenta tratteggiata
locate 9: print "4)"
line (25,130)-step(100,100),rgb(255,255,0),BF
line (25,130)-step(100,100),rgb(255,0,255),,&b1100110011001100
sleep
Il codice più sopra riportato si spiega in gran parte da sé, ma forse è bene chiarire il funzionamento di due argomenti di questa istruzione:
il primo riguarda il parametro B o BF: in pratica se si vuole disegnare soltanto il perimetro della figura si indica la lettera B che sta per box (scatola), mentre se si vuole colorare l’intera figura si indicano le lettere BF che stanno per box filled (scatola riempita);
il secondo è quello che specifica lo stile del segmento. Lo si fa scrivendo un letterale numerico intero in forma binaria con 16 bits. Questo valore rappresenta una maschera di bits (bitmask) dove al valore 1 corrisponde un pixel acceso e al valore 0 un pixel spento. La maschera viene ripetuta per tutta la lunghezza del segmento.
Bene. Per oggi ci fermiamo qui. Nel prossimo articolo vedremo come lavorare con il cerchio e l’ellisse. 🙂
In geometria il punto è una entità adimensionale che esiste soltanto in quanto è identificabile attraverso delle coordinate che ne specificano la posizione su un piano.
Come entità adimensionale possiamo dire che il punto fisicamente non esiste, ma, nonostante questo, il pensiero può lo stesso concepirlo concettualmente.
In FreeBASIC per disegnare un punto si utilizza l’istruzione pset.
Disegnare un pixel con pset
Vediamo un semplice esempio per disegnare tre pixels colorati:
''definisce una risoluzione dello schermo 100x100px
''con risoluzione grafica 32bpp
screenres 400, 200, 32
''definisce il colore bianco per il primo piano e il
''colore nero per lo sfondo
color(rgb(255,255,255),rgb(0,0,0))
''pulisce lo schermo grafico per rendere attivi i colori
''definiti con l'istruzione color
cls
''messaggio
locate 1: print "3 pixels"
''disegna tre pixels
pset(180,100), rgb(255,0,0) ''disegna un pixel rosso
pset(200,100), rgb(0,255,0) ''disegna un pixel verde
pset(220,100), rgb(0,0,255) ''disegna un pixel blu
sleep
Coordinate relative con pset step
Abbiamo visto come disegnare tre pixels specificando per ciascuno le proprie coordinate assolute.
In FreeBASIC abbiamo però anche la possibilità di disegnare un pixel specificando delle coordinate relative all’ultimo pixel disegnato:
screen 14, 32
color(rgb(0,0,0),rgb(255,255,255))
cls
pset(40,40), rgb(255,0,0)
for i as integer = 1 to 39
pset step(1,1), rgb(255,0,0)
next i
for i as integer = 1 to 40
pset step(1,-1), rgb(0,255,0)
next i
for i as integer = 1 to 80
pset step(-1,0), rgb(0,0,255)
next i
sleep
Per oggi ci fermiamo qui. Nel prossimo articolo parleremo della linea. 🙂
In questo nuovo articolo andremo alla scoperta di come si può lavorare con i colori in FreeBASIC.
Funzione color
La prima funzione che incontriamo è la funzione color che ci permette di fare tre cose:
impostare il colore del primo piano (foreground)
impostare il colore dello sfondo (background)
ottenere i colori correnti del primo piano e dello sfondo
Impostare i colori del primo piano e dello sfondo
L’impostazione del colore del primo piano e dello sfondo, oltre ad avere diretto effetto sullo schermo grafico, ha effetto anche sulle figure che vengono su questo disegnate, per esempio con le funzioni line o circle, se non si specifica con queste istruzioni l’attributo relativo al loro colore.
Definire un colore con la funzione rgb
La funzione rgb permette di valorizzare distintamente i tre colori primari percepiti dal nostro occhio per sintesi additiva: rosso (red), verde (green) e blu (blue).
''imposta la risoluzione dello schermo e quella grafica
screen 19, 32
''imposta il colore rosso per il primo piano e
''il colore zafferano per lo sfondo
color(rgb(255,0,0), rgb(244,196,48))
''pulisce lo schermo per rendere visibile il
''colore dello sfondo appena impostato
cls
print "Cosa sono i colori?"
sleep
Su Wikipedia è disponibile una lista dei colori molto utile per il programmatore.
Definire un colore con la tavolozza dei colori predefinita
In FreeBASIC è disponibile una tavolozza dei colori predefinita (default pallettes) che raggruppa una serie di colori visualizzabili in base alla modalità grafica scelta.
Per impostare uno di questi colori basterà specificare il relativo valore associato.
screen 12
color(1, 5) ''primo piano blu e sfondo rosa
cls
print "ciao"
sleep
In FreeBASIC è anche possibile cambiare la tavolozza dei colori attraverso l’istruzione palette, ma questa possibilità non verrà esplorata in questo articolo.
Ottenere il colore del primo piano e dello sfondo
La funzione color restituisce un valore ulong (ovvero un valore di tipo long senza però il segno) che contiene l’informazione dei valori del primo piano e dello sfondo correnti:
dim c as ulong
c = color()
print "Colori della console:"
print "primo piano:"; loword(c)
print "sfondo:"; hiword(c)
Ottenere il colore di un pixel
Oltre al colore del primo piano e dello sfondo, potremmo essere interessati a conoscere il colore di uno specifico punto dello schermo (pixel).
Per fare questo possiamo utilizzare la funzione point:
screen 12
color(1, 5) ''primo piano blu e sfondo rosa
cls
line(10,10)-(40,10), 2 ''disegna una linea verde
locate 4,1: print "colore dello sfondo:"; point(5,5)
locate 5,1: print "colore di un pixel della linea:"; point(20,10)
sleep
Bene! Come introduzione al mondo dei colori in FreeBASIC possiamo fermarci qui.
Il nome della funzione che utilizzeremo è multikey.
In quest’altro articolo viene invece descritto l’uso della funzione getkey.
Funzionamento
Questa funzione necessita come argomento del valore del codice del tasto che si vuole verificare se è stato premuto. Se il tasto viene effettivamente premuto la funzione restituisce il valore -1 (true), altrimenti 0 (false).
La collezione dei nomi di queste costanti rientra nello spazio dei nomi (namespace) identificato dalla sigla FB che va quindi anteposta al nome della costante attraverso la notazione puntata. Per esempio: FB.SC_ESCAPE (per indicare il tasto ‘Esc’).
Questi valori costanti sono definiti all’interno del file di intestazione fbgfx.bi che fa parte della libreria grafica di FreeBASIC.
Ciò comporta che all’inizio del modulo dovremo includere la libreria grafica attraverso l’istruzione #include.
Esempio
#include "fbgfx.bi"
dim as integer x, y
screen 19
x = 300: y = 200
''continua il ciclo sino alla pressione del tasto 'Esc' (esci)
do
''verifica se vengono premuti i tasti freccia
if multikey(FB.SC_LEFT) then x = x - 1
if multikey(FB.SC_RIGHT) then x = x + 1
if multikey(FB.SC_UP) then y = y - 1
if multikey(FB.SC_DOWN) then y = y + 1
''pulisce lo schermo e disegna il cerchio alle nuove coordinate
cls
circle(x, y), 30
sleep 15, 1
loop until multikey(FB.SC_ESCAPE)
Il secondo parametro (1) della funzione sleep comunica al compilatore FreeBASIC che la pausa di 15 ms non può essere interrotta dalla pressione di un qualsiasi tasto.
Bene. Anche oggi abbiamo fatto un piccolo passo in avanti. 🙂
In pratica ciò che occorre fare per seguire questo schema di progettazione è raccogliere logicamente i moduli del nostro codice nelle 3 componenti del modello MVC che differiscono per scopo e logica di funzionamento. Vediamole in sintesi:
Il componente Modello – che rappresenta il cuore del nostro programma – è quella parte del codice che contiene tutte quelle procedure (subroutines e funzioni) per la gestione delle informazioni secondo le regole e la logica decise dal programmatore. In pratica è questo componente che determina il vero e proprio comportamento del programma.
Il componente Vista contiene tutta quella parte del codice concepita per la gestione della grafica e del testo. Questo modulo si occupa sia della visualizzazione dei risultati delle elaborazioni avvenute nel componente Modello (output), sia della visualizzazione di quegli elementi grafici e testuali che permettono all’utilizzatore di interagire con il programma (input).
Il componente Controllore si occupa invece della fasi di interlavoro con le altre due componenti: una parte del suo codice permette a questo componente di mettersi in ascolto degli input dell’utilizzatore provenienti dal componente Vista, per poi attivare le relative procedure del componente Modulo, da cui raccoglierà i risultati elaborati per attivare le relative procedure del componente Vista che si occuperà infine di trasformare i dati elaborati in oggetti grafici o testuali.
Forse uno schema può aiutarci a capire ancora meglio ciò che abbiamo provato a descrivere più sopra.
Schema del Modello Architetturale MVC
Di Wdror-wsu-ap and Regis Frey – Opera propria, Pubblico dominio, Collegamento
Per non lasciare tutto questo soltanto ad un livello teorico, scriveremo un programma per disegnare dei quadrati rossi, selezionarli o deselezionarli, e spostarli a video.
Programma di esempio
Volendo seguire lo schema di progettazione MVC, scriveremo un modulo per ciascun componente di questo Modello Architetturale. In aggiunta prepareremo anche un file di intestazione per organizzare meglio le dichiarazioni delle procedure e del tipo di dato creato ad hoc per l’occasione, così come si usa fare in FreeBASIC.
Una volta preparati e salvati i 4 files, si dovrà compilare il file sorgente modulo_controllore.bas e quindi eseguire il file compilato.
File di intestazione
''nome file: intestazione.bas
''sito web: https://ciucoinformatico.home.blog/
''ultimo aggiornamento: 04/08/2019
/' DESCRIZIONE
File di intestazione per la dichiarazione del tipo di dato
creato ad hoc e delle procedure contenute negli altri moduli.
'/
''definizione del tipo di dato figura
type figura
tipo as string
coord_x as integer
coord_y as integer
dimensione as integer
colore(1 to 3) as integer
selezione as boolean
selezione_x as integer
selezione_y as integer
end type
''dimensiona un array fisso del tipo figura
dim figure(1 to 10) as figura
/'
Componente VISTA
'/
''procedura per stampare a video il menu
declare sub stampa_menu()
''procedura per visualizzare le informazioni del mouse
declare sub info_mouse(x as integer, y as integer, r as integer)
''procedura per visualizzare il numero delle figure create
declare sub stampa_tot_figure(n as integer)
''procedura per disegnare le figure
declare sub disegna_figura(f() as figura)
/'
Componente MODELLO
'/
''procedura per la creazione di una figure geometrica
declare sub crea_figura(x as integer, y as integer, r as integer, n as integer, f() as figura)
''procedura per la selezione di una o più figure
declare sub seleziona(x as integer, y as integer, f() as figura)
''procedura per lo spostamento delle figure
declare function sposta(x as integer, y as integer, f() as figura) as boolean
Modulo Controllore
''nome file: controllore.bas
''architettura MVC (Model-View-Controller): componente CONTROLLORE
''sito web: https://ciucoinformatico.home.blog/
''ultimo aggiornamento: 04/08/2019
/' DESCRIZIONE
Componente CONTROLLO: modulo per l'ascolto degli input
dell'utilizzatore che tramite il mouse interagisce con lo
schermo, e dispaccio degli eventi generati dall'utilizzatore
alle procedure del componente MODELLO e chiamata alle
procedure di visualizzazione del componente VISTA.
'/
#include once "file_intestazione.bi"
#include once "modulo_vista.bas"
#include once "modulo_modello.bas"
''dimensiona una variabile per ricevere il valore
''restituito dalla funzione getmouse
dim as long verifica_mouse
''dimensiona quattro variabili per ricevere le
''informazioni provenienti dal mouse
dim as integer mouse_x, mouse_y, mouse_ruota, mouse_pulsante
''variabile per il conteggio delle figure
dim num_figura as integer
num_figura = 0
''Visualizza il menu
stampa_menu()
''ciclo per l'ascolto degli input (informazioni dal mouse)
do
verifica_mouse = getmouse(mouse_x, mouse_y, mouse_ruota, mouse_pulsante)
if verifica_mouse = 0 then
''visualizza a video le informazioni del mouse
info_mouse(mouse_x, mouse_y, mouse_ruota)
else
''non fare nulla
end if
if mouse_pulsante = 1 then
''tasto sinistro del mouse
seleziona(mouse_x, mouse_y, figure())
disegna_figura(figure())
stampa_menu()
stampa_tot_figure(num_figura)
elseif mouse_pulsante = 4 then
''tasto centrale del mouse
if sposta(mouse_x, mouse_y, figure()) then
disegna_figura(figure())
stampa_menu()
stampa_tot_figure(num_figura)
sleep 200
else
end if
elseif mouse_pulsante = 2 then
''tasto destro del mouse
if num_figura < 10 then
num_figura = num_figura + 1
crea_figura(mouse_x, mouse_y, mouse_ruota, num_figura, figure())
disegna_figura(figure())
stampa_menu()
stampa_tot_figure(num_figura)
sleep 200
else
beep
end if
else
''non fare nulla
end if
loop until verifica_mouse = 1
Modulo Vista
''nome file: vista.bas
''architettura MVC (Model-View-Controller): componente VISTA
''sito web: https://ciucoinformatico.home.blog/
''ultimo aggiornamento: 03/08/2019
/' DESCRIZIONE
Componente VISTA: modulo per la rappresentazione a video
del testo e delle figure.
'/
''Imposta una pagina video con la modalità grafica 19 per
''una risoluzione dello schermo di 800x600 pixels, una
''dimenzione testuale di 100 colonne x 37 righe e
''una profondità di colore a 32bpp.
screen 19, 32, 1
''posiziona il mouse al centro
setmouse 400, 300
''procedura per stampare a video il menu
sub stampa_menu()
locate 1,1: print "Mouse:"
locate 2, 1: print "tasto sinistro = seleziona le figure"
locate 3, 1: print "tasto centrale = sposta le figure selezionate"
locate 4, 1: print "tasto destro = crea una figura"
locate 5, 1: print "Nota:"
locate 6, 1: print "Per ingrandire o rimpicciolire la figura, prima"
locate 7, 1: print "di crearla, usa la ruota."
locate 36, 1: print "Per uscire dal programma porta il puntatore del";
print " mouse fuori dalla finestra grafica."
end sub
''procedura per visualizzare il numero delle figure create
sub stampa_tot_figure(n as integer)
locate 8, 1: print "Totale figure create:"; n; _
" (al massimo ne puoi creare 10)"
end sub
''procedura per visualizzare le informazioni del mouse
sub info_mouse(x as integer, y as integer, r as integer)
locate 9, 1
print "x:"; x; " y:"; y; " ruota:"; r
end sub
''procedura per disegnare le figure
sub disegna_figura(f() as figura)
cls 1
''itera gli elementi del contenitore delle figure
for i as integer = lbound(f) to ubound(f)
if f(i).tipo = "quadrato" then
line(f(i).coord_x, f(i).coord_y)-(f(i).coord_x + f(i).dimensione, f(i).coord_y), rgb(f(i).colore(1),f(i).colore(2),f(1).colore(3))
line(f(i).coord_x + f(i).dimensione, f(i).coord_y)-(f(i).coord_x + f(i).dimensione, f(i).coord_y + f(i).dimensione), rgb(f(i).colore(1),f(i).colore(2),f(i).colore(3))
line(f(i).coord_x + f(i).dimensione, f(i).coord_y + f(i).dimensione)-(f(i).coord_x, f(i).coord_y + f(i).dimensione), rgb(f(i).colore(1),f(i).colore(2),f(i).colore(3))
line(f(i).coord_x, f(i).coord_y + f(i).dimensione)-(f(i).coord_x, f(i).coord_y), rgb(f(i).colore(1),f(i).colore(2),f(1).colore(3))
end if
next i
end sub
Modulo Modello
''nome file: modello.bas
''architettura MVC (Model-View-Controller): componente MODELLO
''sito web: https://ciucoinformatico.home.blog/
''ultimo aggiornamento: 03/08/2019
/' DESCRIZIONE
Modulo contenente le procedure per la gestione dei dati
e la logica di funzionamento del programma.
'/
''procedura per la creazione di una figure geometrica
sub crea_figura(x as integer, y as integer, r as integer, n as integer, f() as figura)
f(n).tipo = "quadrato"
f(n).coord_x = x
f(n).coord_y = y
f(n).dimensione = 80 + r
f(n).colore(1) = 255
f(n).colore(2) = 0
f(n).colore(3) = 0
f(n).selezione = false
end sub
''procedura per la selezione di una o più figure
sub seleziona(x as integer, y as integer, f() as figura)
''itera gli elementi del contenitore delle figure
for i as integer = lbound(f) to ubound(f)
if x >= f(i).coord_x and x <= (f(i).coord_x + f(i).dimensione) and y >= f(i).coord_y and y <= (f(i).coord_y + f(i).dimensione) then
f(i).colore(2) = 255
f(i).selezione = true
f(i).selezione_x = x - f(i).coord_x
f(i).selezione_y = y - f(i).coord_y
else
f(i).colore(2) = 0
f(i).selezione = false
f(i).selezione_x = 0
f(i).selezione_y = 0
end if
next i
end sub
''procedura per lo spostamento delle figure
function sposta(x as integer, y as integer, f() as figura) as boolean
dim controllo as boolean
controllo = false
''itera gli elementi del contenitore delle figure
for i as integer = lbound(f) to ubound(f)
if f(i).selezione = true then
f(i).coord_x = x - f(i).selezione_x
f(i).coord_y = y - f(i).selezione_y
''deselezione
f(i).colore(2) = 0
f(i).selezione = false
f(i).selezione_x = 0
f(i).selezione_y = 0
controllo = true
else
''non fare nulla
end if
next i
return controllo
end function
Proviamo ora a fare un piccolo passo in avanti per cercare di interagire prima con la finestra grafica e poi con le figure geometriche che disegneremo su questa.
Il primo obiettivo sarà raggiunto con questo articolo, il secondo con il prossimo.
Per interagire con la finestra grafica dovremo trovare il modo di fornire degli input che ci serviranno per far accadere delle cose. Benvenuti nella programmazione a eventi!
La libreria grafica del compilatore FreeBASIC ci mette a disposizione una serie di funzioni per gestire gli input dell’utente. Tra queste ci sono quelle per lavorare con due strumenti esterni (external devices):
Il compilatore FreeBASIC ci permette sia di recuperare le informazioni dal mouse, sia di impostare, per esempio, la sua posizione.
Come recuperare le informazioni dal mouse
Per intercettare lo spostamento del mouse e la pressione di uno dei tre pulsanti che vi si trovano normalmente, dobbiamo utilizzare la funzione getmouse.
La funzione getmouse ritorna un valore di tipo long che può assumere due soli valori:
0 (zero) se dal mouse arrivano correttamente le informazioni
1 se invece non arriva nulla (per esempio perché il puntatore è uscito fuori dai bordi della finestra grafica)
Questa funzione però non si limita soltanto a questo, ma permette di recuperare la posizione del puntatore del mouse in coordinate espresse in pixels e lo stato dei suoi pulsanti. Per farlo occorre passarle delle variabili i cui valori saranno restituiti per riferimento.
Se per qualche motivo alcune o tutte queste informazioni non vengono recuperate, le variabili coinvolte assumeranno valore -1.
Come impostare la posizione del mouse
Può essere molto utile fare in modo che all’avvio del nostro programma il puntatore del mouse si trovi in un punto specifico all’interno della finestra grafica.
Vediamo un piccolo esempio per provare queste due funzioni:
'dimensiona una variabile per ricevere il valore
'restituito dalla funzione getmouse
dim as long verifica_mouse
'dimensiona quattro variabili per ricevere le
'informazioni provenienti dal mouse
dim as integer x, y, ruota, pulsante
'imposta la finestra grafica con risoluzione dello
'schermo 800x600 pixels e dimensioni testuali 100x37
screen 19
'posiziona il puntatore del mouse al centro della
'finestra grafica
setmouse 400, 300
'ciclo per gestire le informazioni dal mouse
do
verifica_mouse = getmouse(x, y, ruota, pulsante)
if verifica_mouse = 0 then
locate 1, 1
print "Riesco a ricevere le informazioni dal mouse."
locate 3, 1
print "x:"; x; " y:"; y
locate 4, 1
print "ruota:"; ruota; " pulsante:"; pulsante
locate 6, 1
print "Per uscire dal ciclo porta il puntatore"
print "del mouse fuori dai bordi della finestra grafica."
else
cls
locate 1, 1
print "Il puntatore del mouse e' fuori dai"
print "bordi della finestra grafica."
locate 36, 1
print "Premi il tasto INVIO per uscire dal programma."
sleep
end if
loop until verifica_mouse = 1
Istruzione locate
Come avrete notato per posizionare il testo nei punti voluti è stata utilizzata l’istruzione locate che definisce la posizione del cursore attraverso il numero di riga e di colonna del primo carattere della stringa che si vuole stampare con l’istruzione print.
Concludiamo l’esplorazione dell’istruzione screen analizzando il suo quarto attributo che nella documentazione ufficiale in inglese viene definito flags.
Questo attributo serve per impostare diverse proprietà dello schermo, ma per lo scopo didattico della nostra guida ci interesseremo soltanto di quelle relative ad alcune delle proprietà della finestra grafica, ovvero:
la modalità a schermo intero (fullscreen mode);
la presenza o meno dei bordi;
se deve apparire sempre in primo piano o no.
I valori ammissibili per questo attributo sono predefiniti come valori costanti all’interno del file di intestazionefbgfx.bi che deve quindi necessariamente essere incluso nel file sorgente del nostro programma.
Se l’attributo flag viene omesso, verrà aperta una normale finestra (che corrisponde, come vedremo poco più sotto, alla costante GFX_WINDOWED).
Vediamo ora i nomi e il significato di queste costanti:
GFX_WINDOWED: apre una normale finestra grafica secondo le caratteristiche specificate dai primi tre attributi dell’istruzione screen (ovvero la modalità grafica, la profondità di colore e il numero di pagine video);
GFX_FULLSCREEN: se la modalità è supportata dal sistema operativo del proprio computer forza l’apertura di una finestra grafica a schermo intero, altrimenti verrà impostato di default il valore della costante GFX_WINDOWED;
GFX_NO_FRAME: crea una finestra grafica senza bordi;
GFX_ALWAYS_ON_TOP: crea una finestra grafica che rimane sempre in primo piano.
Ora non ci resta che provare con un semplice programma dove per testare le diverse proprietà della finestra grafica non dovremo far altro che trasformare in commento l’istruzione attiva, anteponendo il simbolo apice (‘), e poi trasformare in istruzione quella commentata che volete provare cancellando il simbolo apice:
'include il file contenente le costanti per gestire
'le proprietà dello schermo
#include "fbgfx.bi"
'specifica che le costanti rientrano nello spazio
'dei nomi di FreeBASIC (argomento che affronteremo
'più avanti)
#if __fb_lang__ = "fb"
using fb
#endif
'Imposta una pagina video con la modalità grafica 19 per
'una risoluzione dello schermo di 800x600 pixels e
'la profondità di colore a 32bpp e poi imposta la
'relativa proprietà dello schermo
screen 19, 32, 1, GFX_WINDOWED
'screen 19, 32, 1, GFX_FULLSCREEN
'screen 19, 32, 1, GFX_NO_FRAME
'screen 19, 32, 1, GFX_ALWAYS_ON_TOP
print "Ciao mondo!"
sleep 'rimane in pausa
Bene. Con l’istruzione screen possiamo fermarci qui.
Dopo aver parlato della risoluzione dello schermo (modalità grafica) e della risoluzione grafica (profondità di colore), in questo articolo continueremo l’esplorazione della istruzione screen giocando con il suo terzo attributo: quello che specifica il numero di pagine video con cui si vuole lavorare.
Pagine video
In FreeBASIC è possibile lavorare con più pagine video.
Quindi, oltre alla normale procedura che prevede di disegnare su una pagina mentre questa è già visibile a schermo, avendo a disposizione più pagine video, si può per esempio disegnare su una pagina mentre se ne sta rendendo visibile un’altra su cui si era disegnato in precedenza.
Qual è il vantaggio?
Lo “spettatore” si gode lo spettacolo sul palcoscenico (pagina visibile), mentre nel retropalco (pagina di lavoro) si prepara la scenografia successiva. 😉
Come definire il numero di pagine video
Per definire il numero delle pagine video che necessitano al nostro programma basta scriverlo come terzo attributo dell’istruzione screen:
'Imposta 3 pagine video con la modalità grafica 19 per
'una risoluzione dello schermo di 800x600 pixels e
'la profondità di colore a 32bpp.
screen 19, 32, 3
Se questo attributo viene omesso, il nostro programma avrà comunque una pagina video di default.
Come specificare la pagina di lavoro e quella visibile
Se il nostro programma ha una sola pagina video, le istruzioni per il disegno agiranno e saranno visibili su questa pagina, ma se possiamo disporre di più pagine video, allora dovremo gestire sia la pagina di lavoro che la pagina visibile.
Per farlo si usa la subroutinescreenset che ha due attributi: il primo per definire la pagina di lavoro, il secondo quella visibile. Vediamo alcuni esempi:
screen 19, 32, 2 'per definire due pagine video
screenset 0, 0 'disegna e visualizza la I p.v.
screenset 0, 1 'disegna sulla I p.v. mentre visualizza la II
screenset 1, 0 'disegna sulla II p.v. mentre visualizza la I
screenset 1, 1 'disegna e visualizza la II p.v.
Come è facile notare da questa porzione di codice, l’identificativo delle schede video parte dal valore 0 (zero).
Nel programma dei 3 cerchi colorati riportato più sotto ne vedremo un possibile utilizzo.
La funzione circle permette di disegnare cerchi ed ellissi.
Sintassi
Un uso semplificato è questo:
circle (coordinata x, coordinata y), raggio, [colore]
I valori relativi alle coordinate x e y del centro del cerchio e quello del raggio sono obbligatori, mentre l’attributo del colore è opzionale: se omesso sarà quello del primo piano corrente impostabile con la funzione color().
Nell’esempio che vedremo più sotto ci baseremo sul modello di colori RGB utilizzando la funzione rgb() passandole tre attributi che rappresentano rispettivamente la componente rossa, quella verde e quella blu. Il range dei valori ammessi per questi attributi va da 0 a 255.
Programma dei 3 cerchi colorati
'Imposta 3 pagine video con la modalità grafica 19 per
'una risoluzione dello schermo di 800x600 pixels e
'la profondità di colore a 32bpp.
screen 19, 32, 3
'Imposta come pagina di lavoro la prima (valore 0).
screenset 0
'Disegna 255 cerchi al centro dello schermo, di
'raggio e tono di colore rosso crescenti.
for i as integer = 1 to 255
circle (400,300), i, RGB(i,0,0)
next i
'Imposta come pagina di lavoro la seconda (valore 1).
screenset 1
'Disegna 255 cerchi al centro dello schermo, di
'raggio e tono di colore verde crescenti.
for i as integer = 1 to 255
circle (400,300), i, RGB(0,i,0)
next i
'Imposta come pagina di lavoro la terza (valore 2).
screenset 2
'Disegna 255 cerchi al centro dello schermo, di
'raggio e tono di colore blu crescenti.
for i as integer = 1 to 255
circle (400,300), i, rgb(0,0,i)
next i
'Doppio ciclo per rendere alternativamente visibili,
'una volta al secondo, le tre pagine. Il ciclo si
'ripete per 3 volte.
for i as integer = 1 to 3
for j as integer = 0 to 2
screenset ,j
sleep 1000 'pausa di un secondo
next j
next i
Nel precedente articolo abbiamo parlato della risoluzione dello schermo: ovvero di come impostare le dimensioni digitali delle nostre finestre in termini di quanti pixels si possono disegnare in orizzontale (larghezza) e di quanti in verticale (altezza).
Il rapporto tra la larghezza e l’altezza di una finestra grafica rappresenta il cosiddetto rapporto d’aspetto.
In questo nuovo articolo parleremo invece della risoluzione grafica: ovvero della qualità delle immagini che si possono disegnare a video.
Profondità di colore
In FreeBASIC per definire la qualità delle immagini occorre impostare nella istruzione screen il parametro della profondità di colore (color depth): ovvero il numero di bits utilizzati per descrivere il colore di un singolo pixel. L’unità di misura di questo parametro è quindi espressa in bpp (bits per pixel).
Questo parametro ha effetto soltanto per le modalità grafiche dalla 14 alla 21 e può assumere i valori: 8, 16 o 32 bpp.
Più bits vengono utilizzati per un singolo pixel, più la qualità dell’immagine sarà migliore.
Scheda video
Arrivati a questo punto occorre fare una precisazione:
Le caratteristiche tecniche della scheda video del nostro computer limitano le possibilità di scelta della modalità grafica in relazione alla profondità di colore da noi scelta.
Come facciamo quindi a sapere quale modalità grafica (parametro mode) possiamo scegliere con uno specifico valore di profondità di colore (parametro depth)?
L’istruzione screenlist
La risposta alla domanda che ci siamo posti più sopra ce la fornisce l’istruzione screenlist.
Vediamo nel dettaglio i passi da seguire per utilizzare al meglio questa istruzione:
Nella prima chiamata alla funzione screenlist è necessario specificare il valore della profondità di colore desiderata. La funzione restituirà la più bassa risoluzione dello schermo possibile in relazione alla profondità di colore specificata.
Le successive chiamate alla funzione non necessiteranno più di alcun argomento: ciascuna chiamata restituirà le possibili risoluzioni dello schermo in maniera crescente.
La restituzione del valore 0 (zero) starà a significare che non ci sono risoluzioni dello schermo più grandi dell’ultima restituita.
Scriviamo ora un semplice programma per scoprire quali risoluzioni dello schermo sono possibili con la scheda video del nostro computer in base alle tre diverse profondità di colore gestite dal FreeBASIC.
Per realizzare il nostro programma utilizzeremo due strutture di controllo:
un ciclo for-next per selezionare di volta in volta le diverse profondità di colore;
un ciclo do-loop per eseguire le diverse chiamate alla funzione screenlist.
'dimensiona e poi crea un array con i tre valori della
'profondità di colore disponibili in FreeBASIC
dim prof_col (1 to 3) as long
prof_col(1) = 8
prof_col(2) = 16
prof_col(3) = 32
'dimensiona una variabile per ricevere il
'risultato della chiamata alla funzione screenlist
dim risultato as long
'dimensiona una variabile stringa per la
'risoluzione dello schermo
dim risoluzione as string
'doppio ciclo per ottenere tutte le risoluzioni dello schermo
'gestite dalla scheda video del computer in base alle
'diverse profondità di colore
for i as integer = lbound(prof_col) to ubound(prof_col)
print "Lista risoluzioni dello schermo disponibili"
print "con la profondita' di colore "; prof_col(i)
risultato = screenlist(prof_col(i)) 'prima chiamata
do while risultato <> 0
print risultato
risultato = screenlist()
loop
print "---"
next i
Ecco il risultato a video:
Che dire? Ciò che abbiamo ottenuto è veramente poco soddisfacente: una serie di numeri che sembrano non dirci nulla. Perché?
La risposta ci permetterà di conoscere una tecnica che potrà tornarci utile in molte occasioni.
Lavorare con le codifiche binarie
Il risultato della funzione screenlist è codificato in un valore a 32 bit: dove i 16 bits più alti (ovvero quelli a sinistra) rappresentano la larghezza della finestra, mentre i 16 bits più bassi (ovvero quelli a destra) rappresentano l’altezza della finestra.
Il compilatore FreeBASIC ci mette a disposizione due utili funzioni per estrarre queste informazioni: l’istruzione hiword e l’istruzione loword.
Modifichiamo quindi il ciclo do-loop del nostro programma in questo modo:
do while risultato <> 0
risoluzione = hiword(risultato) & "x" & loword(risultato)
print risoluzione
risultato = screenlist()
loop
Vediamo ora il nuovo risultato a video:
Molto meglio. No? 🙂
Ora non ci resta che fare un confronto con le modalità grafiche disponibili in FreeBASIC per verificare quali sono disponibili.
Modifichiamo quindi il ciclo do-loop inserendo una istruzione select case:
Abbiamo finalmente la lista delle risoluzioni dello schermo gestibili dalla scheda video del nostro computer con evidenziate quelle che hanno una corrispondenza con le modalità grafiche gestite dal compilatore FreeBASIC.
Nel prossimo articolo continueremo ad approfondire l’istruzione screen testando un altro dei suoi attributi: quello che gestisce le pagine video.