Este sitio web usa cookies de terceros para analizar el tráfico y personalizar los anuncios. Si no está de acuerdo, abandone el sitio y no siga navegando por él. ×


Curso de Pascal. Ampliación 2: Gráficos sin BGI (4)

Ya hemos comentado cómo entrar a un modo gráfico dado, como dibujar un punto, dibujar líneas, círculos o elipses, como hacer rotaciones en el plano, algunas optimizaciones sencillas...

Hoy vamos a tratar cómo borrar la pantalla, como cambiar la paleta de colores, cómo sincronizar con el barrido de la pantalla, cómo escribir en la pantalla gráfica y a dar una idea sobre cómo mover datos en memoria, aplicándolo a un Scroll sencillo.

Borrar la pantalla


Veamos... lo de borrar la pantalla es MUY sencillo.  Si estamos en nuestro modo 320x200, 256 col., la pantalla ocupaba 64000 bytes, que estaban a partir de la dirección $A000:0000 ¿verdad?

Pues entonces podemos situar una matriz en esa posición de la memoria, como hicimos en el primer apartado de este tema:

var pantalla: array[0..319,0..199] of byte absolute $A000:0000;

o bien simplemente

var pantalla: array[1..64000] of byte absolute $A000:0000;



Con cualquiera de estas definiciones, podemos usar la orden "fillchar", que llena con un cierto byte unas posiciones de memoria que le indiquemos:

fillchar(pantalla, 64000, 0);

que quiere decir "lléname la variable pantalla con ceros, ocupando 64000 bytes".

Un uso más adecuado para evitar errores, ya que "fillchar" no hace comprobaciones de tamaño, es usar "sizeof" para que el compilador sea quien calcule cuantos ceros hay que poner:

fillchar(pantalla, sizeof(pantalla), 0);

Lógicamente, si queremos borrar la pantalla empleando el color 2 en vez del 0 (que normalmente es el fondo), basta poner un 2 en vez del cero... ;-)   En el caso más general, sería


procedure BorraPantalla( color: byte );
begin
  fillchar(pantalla, sizeof(pantalla), color);
end; 

 


La paleta de colores


Sigamos... ¿La paleta de colores?  ¿Qué es eso?  Pues supongo que cualquiera que haya llegado hasta aquí recordará que estamos trabajando con 256 colores.  Pero estos colores no tienen por qué ser siempre iguales: el color 0 no tiene por qué ser siempre negro.  Podemos modificar cualquiera de los 256 colores físicos indicando la cantidad de Rojo, Verde y Azul (RGB) que queremos que tenga.  Esto lo hacemos accediendo a través de puertos:

Tenemos las siguientes direcciones importantes:
 $3c7 =>  Dirección de lectura
 $3c8 =>  Dirección de escritura
 $3c9 =>  Dirección de datos (R,G y B consecutivos)
y la intensidad máxima para R, G o B será 63.

¿A que asusta?  No hay motivo, es más fácil de lo que parece: para cambiar las componentes R, G y B de un color dado, hacemos


procedure FijaColor( Color, r, g, b: Byte );
begin
  Port[$3c8] := Color;    { Elegimos el color a modificar }
  Port[$3c9] := r;        { Primer dato: cuanto Rojo queremos }
  Port[$3c9] := g;        { Segundo: verde }
  Port[$3c9] := b;        { Tercero: azul }
end; 

Insisto: R, G y B van de 0 a 63, lo que da un total de 262.144 posibles combinaciones de colores que podemos tomar para rellenar nuestros 256 colores "físicos".

Análogamente, para leer las componentes de un color, sería


procedure LeeColor( Color: Byte );
begin
  Port[$3c7] := Color;    { Elegimos el color a leer }
  r := Port[$3c9];        { Primer dato: cuanto Rojo hay }
  g := Port[$3c9];        { Segundo: verde }
  b := Port[$3c9];        { Tercero: azul }
end; 

donde se ha supuesto que R, G y B son variables globales.  También podría ser una función que devolviera los datos en un array, o haber pasado R, G y B como parámetros por referencia (precedidos por la palabra "var").

 Esto tiene aplicación inmediata para hacer fundidos de pantalla y similares, o para muchos efectos vistosos.  Me voy a limitar a poner uno que funciona incluso en modo texto: vamos a hacer que el fondo pase de negro a blanco y luego vuelva a negro.

 {--------------------------}
 {  Ejemplo en Pascal:      }
 {                          }
 {    Fundido de la panta-  }
 {    lla a blanco y luego  }
 {    a negro               }
 {    GRB4.PAS              }
 {                          }
 {  Este fuente procede de  }
 {  CUPAS, curso de Pascal  }
 {  por Nacho Cabanes       }
 {                          }
 {  Comprobado con:         }
 {    - Turbo Pascal 7.0    }
 {    - Tmt Pascal Lt 1.01  }
 {--------------------------}

 program GrB4;

 uses crt;

 var i: byte;

 procedure FijaColor( Color, r, g, b: Byte );
 begin
   Port[$3c8] := Color;    { Elegimos el color a modificar }
   Port[$3c9] := r;        { Primer dato: cuanto Rojo queremos }
   Port[$3c9] := g;        { Segundo: verde }
   Port[$3c9] := b;        { Tercero: azul }
 end;

 begin
 for i := 0 to 63 do    { Recorremos todas las intensidades }
   begin
   FijaColor(0,i,i,i);  { Igual cantidad de R, G, B => gris }
   delay(10);           { Esperamos antes de seguir }
   end;
 for i := 63 downto 0 do    { Igual, descendiendo }
   begin
   FijaColor(0,i,i,i);
   delay(15);
   end;
 end.

 

Sin parpadeos..



Cuando enviamos mucha información a la pantalla o cuando cambiamos los colores con rapidez, podremos apreciar a veces "parpadeos".  Esto también es más fácil de evitar de lo que parece: basta empezar a dibujar cuando llegue el barrido (en inglés "retrace") de la pantalla...  :-o ¿Y cómo se hace eso?  Seguro que lo ha preguntado más de uno...  ;-) Pues esperando a que comience el barrido actual y luego a que empiece el siguiente, así:


procedure Retrace;
begin
  repeat until (port[$3da] and 8) = 8;
  repeat until (port[$3da] and 8) <> 8;
end; 

¡ Magia !   }:-D   Pues basta con escribir "Retrace;" antes de empezar a dibujar, y mejorará bastante (si nuestro dibujo no es muy lento), además de que conseguimos una velocidad bastante independiente del ordenador.