| Apartado anterior | Apartado siguiente |
Curso de Pascal. Ampliación 2: Gráficos sin BGI (5)
Escribir texto
Hay dos formas de escribir texto:
Una, que no vamos a tratar, consiste en definir nuestra propias letras,
o saber dónde está la definición de las que trae el
ordenador, para mirar esa zona de memoria, analizarla y escribir las letras
pixel a pixel.
Otra más sencilla, aunque menos versátil, es con la orden
"write" igual que hacíamos en modo texto. Para ello, basta usar
la unidad CRT pero indicando DirectVideo := false
con lo que la escritura pasa a través de la BIOS, en vez de hacerse
directamente en la memoria de pantalla. Así conseguimos que se pueda
enviar a la pantalla gráfica. Veremos un ejemplo al final
del tema, en el ejemplo de Scroll.
Finalmente, para copiar zonas de memoria podemos utilizar move,
que tiene el formato move (org, dest, cuanto) Esto
no nos sirve directamente para zonas rectangulares de la pantalla, porque
el origen debe ser una sóla zona contigua, lo que no ocurre en un
rectángulo, pero podemos evitarlo copiando fila a fila con un bucle.
¿Y cómo se usa? Pues vamos a ver un ejemplillo,
aprovechando que en nuestro modo de pantalla cada byte se corresponde con
un pixel, para hacer un Scroll (desplazamiento) de parte de la pantalla,
para que aparezca un texto:
{--------------------------} { Ejemplo en Pascal: } { } { Scroll sencillo en la } { parte inferior de la } { pantalla } { GRB5.PAS } { } { Este fuente procede de } { CUPAS, curso de Pascal } { por Nacho Cabanes } { } { Comprobado con: } { - Turbo Pascal 7.0 } { - Tmt Pascal Lt 1.01 } {--------------------------} Uses Crt, dos; Const Fila = 23; { Fila (-1) en la que se escribe el mensaje (base 0) } Var pixel, LetraActual : Byte; { Para bucles } regs: registers; { Para interrupciones (ModoPantalla) } tecla: char; { Para absorber la tecla que se pulse } procedure ModoPantalla( modo: byte ); { Cambia a un modo dado } begin regs.ah := 0; { Función 0 } regs.al := modo; { El modo indicado } intr($10,regs); { Interrupción de video } end; procedure Retrace; { Espera el barrido de la pantalla } begin repeat until (port[$3da] and 8) = 8; repeat until (port[$3da] and 8) <> 8; end; Procedure Mueve; { Desplaza el texto a la izqda un pixel } Var LineaAct : Word; { La línea que se está moviendo } begin { Desplaza las 8 líneas 1 pixel hacia la izqda } For LineaAct := (Fila * 8) to (Fila * 8) + 7 DO Move(Mem[$A000 : LineaAct * 320 + 1], Mem[$A000 : LineaAct * 320], 319); { Borra los pixels del final } For LineaAct := (Fila * 8) to (Fila * 8) + 7 DO Mem[$A000 : LineaAct * 320 + 319] := 0; end; procedure ScrollInferior(mensaje:string); { Esto es lo importante } begin ModoPantalla($13); { Modo Mcga/Vga 320x200x256 } DirectVideo := False; { Para escribir texto en modo gráfico } GotoXY(1, Fila + 1); { Vamos a la posición } repeat For LetraActual := 1 to Length(Mensaje) do { Para cada letra } begin For pixel := 1 to 8 do { Los 8 pixels de ancho } begin Mueve; { Mueve el letrero } Retrace; { Espera al barrido } if keypressed then exit; { Si se pulsa tecla: fuera } end; GotoXY(40, Fila+1); { En la posición adecuada } Write(Mensaje[LetraActual]); { Se escribe la sgte letra } end; until keypressed; end; begin ScrollInferior('Esto es un - S C R O L L - '); tecla := readkey; { Vacía el buffer del teclado } ModoPantalla(3); { Vuelve a modo texto } end.
Una recomendación final: en vuestros programas (si es que los haceis X-D ) no se os ocurra copiar el procedimiento "linea", "modopantalla" y similares cada vez. Lo más cómodo es crear una unidad, meter nuestros procedimientos y funciones relacionados con los gráficos y acceder a ella cuando nos interese.
Así además, si encontrais otro procedimiento más
rápido para dibujar líneas (los hay, si trabajamos en ensamblador,
por ejemplo) o cualquier otra mejora, todos los programas la tendrán
sólo con recompilar.
| Apartado anterior | Apartado siguiente |