14
Capı́tulo 2
Trabajando con textos
2.0.1. Textos básicos
En el ejemplo anterior vimos como escribir texto en la pantalla superior,
profundicemos un poco más en este tema. Ya hemos visto que necesitamos utili-
zar PA InitText(pantalla,fondo); para poder usar el texto, en una o dos pantallas
simultáneamente; para el fondo debemos de elegir uno de los cuatro disponi-
bles, el 0 es el más cercano y por tanto visible sobre el resto y el 3 es el más
profundo de los cuatro. La función PA OutputSimpleText(pantalla,tile x,tile y,"
cadena_texto"), dispone de 4 parámetros. El primero es el número de pantalla,
1 para la pantalla superior y 0 para la inferior (touchscreen); tile x y tile y son
las coordenadas donde situar el texto, no están medidas en pı́xeles si no en tiles,
que es un cuadrado formado por pı́xeles (concretamente 8x8 pı́xeles), en este
caso hay 32 (desde el 0 al 31) tiles horizontales y 24 (del 0 al 23) verticales en
cada pantalla, en vez de pı́xeles nos movemos por unos pequeños ”‘bloques”’
llamados tiles.
PA OutputSimpleText puede ser bastante útil, en cambio es una función
bastante primitiva y no es muy cómodo trabajar con ella. Sólo imprime ca-
denas de texto, lo que no nos permitirı́a por ejemplo mostrar la puntuación.
Existe otra función, PA OutputText(pantalla,tile x, tile y ,"cadena_texto",param1
,...paramN), muy similar a la ya comentada pero podemos pasarles parámetros
para que los muestre. Por ejemplo PA OutputText(1,0,0,"Puntos : %d",puntos),
donde int puntos=123; es una variable entera y el ejemplo imprimirı́a : ”Puntos
: 123”. Veamos un par de ejemplos más para terminar de entender el funciona-
miento.
15
16 CAPÍTULO 2. TRABAJANDO CON TEXTOS
Recorte de Cap02/cap02ej01/source/main.c
11 int entero = 123456;
12 int dia = 1 5 ;
13 i n t mes = 8 ;
14 i n t anyo = 2 0 0 7 ;
15 float decimal = 987.654321;
16 char cadena [ 3 0 ] = " Esto es otra cadena de texto " ;
17
18 PA OutputText ( 1 , 0 , 0 , " Una simple cadena de texto " ) ;
19 PA OutputText ( 1 , 0 , 1 , " Esto es un entero : %d" , e n t e r o ) ;
20 PA OutputText ( 1 , 0 , 2 , " Un decimal : %f6 " , d e c i m a l ) ;
21 PA OutputText ( 1 , 0 , 3 , " Texto : %s" , cadena ) ;
22 PA OutputText ( 1 , 0 , 4 , " Fecha : %d/ %d/ %d" , dia , mes , anyo ) ;
23 PA OutputText ( 1 , 0 , 5 , " Operaciones : %d+ %f3 " , e n t e r o ,
decimal ) ;
24 PA OutputText ( 1 , 0 , 6 , "= %f5 " , ( e n t e r o+d e c i m a l ) ) ;
¿Qué aprendemos de este ejemplo? Vemos que podemos mostrar cadenas
con variables de una forma muy sencilla, incluyendo %d para imprimir un en-
tero, %fX para un decimal donde la X es el número de decimales después del
punto que queremos mostrar y %s para imprimir cadenas de texto indepen-
dientemente de su longitud. Al final de la función debemos de pasarle como
parámetros las variables que queramos mostrar en el orden en el que aparecen
en la cadena formateada. PA OutputText(1,0,5,"Operaciones : %d+ %f3",decimal,
entero) esta cadena, aunque no da error si que produce resultados no deseados
(convierte el entero a flotante, pero el flotante no lo puede convertir a entero).
Además hemos de tener cuidado con estas funciones. Si el texto es demasiado
largo y sobre pasa la pantalla, seguirá escribiendo en la lı́nea siguiente por lo
que hemos de tener cuidado y controlar la longitud de las cadenas o de otra
forma obtendremos resultados no deseados al mezclarse dos textos diferentes en
pantalla.
2.1. Borrar cadenas
Hasta ahora sólo hemos escrito una vez en pantalla y no hemos ido más lejos,
por lo general los textos son dinámicos y cambian constantemente, por ejemplo
la puntuación o el número de vidas. Ya hemos visto la posibilidad de escribir
variables en pantalla, lo que lo hace más dinámico, pero cada vez que queramos
actualizar esos datos hemos de invocar a la función PA OutputText(pantalla,tile x
, tile y ,"cadena_texto",param1,...paramN), lo especifico porque hay lenguajes en
los que no es necesario, pero no es el caso. Ahora os cuento un pequeño secreto
que cómo funciona realmente esta función, lo que hace no es más ni menos que
poner en pantalla pequeños gráficos que contienen las letras pero no se preocupa
de borrar lo anterior. Por ejemplo si escribimos
PA OutputText(1,0,5,"Esto es una cadena larga"’);
PA OutputText(1,0,5,"Esto es otra"’);
El resultado final serı́a ”‘Esto es otracadena larga”’ (nótese que se escriben
ambas cadenas en las mismas coordenadas). Para evitarlo tenemos que escribir
una cadena de ”‘espacios vacios”’ entre las dos, PA OutputText(1,0,5,"");. Como
2.2. TEXTO EN CAJAS 17
el segundo ejemplo del capı́tulos :
Recorte de Cap02/cap02ej02/source/main.c
13 int entero = 123456;
14
15 // Ejemplos f a l l i d o s
16 PA OutputText ( 1 , 0 , 0 , " Esto es un ejemplo fallido " ) ;
17 PA OutputText ( 1 , 0 , 0 , " PA_OutputText no borra " ) ;
18 PA OutputText ( 1 , 0 , 1 , " con variables tambien : %d" ,
entero ) ;
19 entero = 99;
20 PA OutputText ( 1 , 0 , 1 , " con variables tambien : %d" ,
entero ) ;
21
22 // Ejemplos f u n c i o n a l e s
23 PA OutputText ( 1 , 0 , 5 , " Esto es un ejemplo fallido " ) ;
24 PA OutputText ( 1 , 0 , 5 , " ") ;
25 PA OutputText ( 1 , 0 , 5 , " Hay que hacerlo manualmente " ) ;
26 PA OutputText ( 1 , 0 , 6 , " con variables tambien : %d" ,
entero ) ;
27 entero = 99;
28 PA OutputText ( 1 , 0 , 6 , " ") ;
29 PA OutputText ( 1 , 0 , 6 , " con variables tambien : %d" ,
entero ) ;
2.2. Texto en Cajas
Desde mi punto de vista, las opciones que hemos comentado son las más uti-
lizadas, pero puede suceder que queramos encerrar el texto dentro de una caja
para por ejemplo mostrar conversaciones entre personajes. Para ello utiliza-
mos PA BoxText(pantalla,inicio x, inicio y , fin x , fin y ,texto,numero de caracteres)
, las unidades inicio x, inicio y, fin x, fin y vienen dadas en los famosos tiles,
texto puede ser una cadena de texto literal o una variable de tipo string1 ).
Recorte de Cap02/cap02ej03/source/main.c
14 PA BoxText ( 1 , 6 , 6 , 2 4 , 1 8 , " Esto es un texto dentro de un
rectangulo limitado . Bastante util para mostrar
dialogos en RPGs " , ( 1 2 ∗ 1 8 ) ) ;
15 char cadena [ 1 0 0 ] = " Esto es un texto dentro de un
rectangulo limitado . Bastante util para mostrar
dialogos en RPGs " ;
16 PA BoxText ( 0 , 6 , 6 , 2 4 , 1 8 , cadena , ( 1 2 ∗ 1 8 ) ) ;
Finalmente número de carácteres denota el número de letras que se impri-
mirán en la caja de texto, independientemente de la longitud de la cadena (si el
número de carácteres es mayor que la longitud de la cadena no se imprimiran
más). Quizás estén pensando para qué sirve limitar el número de carácteres a
imprimir, pues facilita mucho la tarea de crar ese efecto tan C00L que nos gus-
1 Aunque string no es un tipo de variable nativo de C/C++, hablaremos de string para
referirnos a un array/vector del tipo char
18 CAPÍTULO 2. TRABAJANDO CON TEXTOS
ta de los RPG’s, de que el texto vaya apareciendo poco a poco, simplemente
aumentando en 1 el valor de la variable número de carácteres, pueden ver un
ejemplo de esto en (Cap02/cap02ej04/source/main.c).
2.3. Colores
Tenemos dos opciones para colorear el texto, cada una tiene sus venta-
jas e inconvenientes. La primera quizás sea la más sencilla pero también la
que más útil nos pueda resultar, PA SetTextCol(pantalla, color rojo, color verde ,
color azul ) , donde las variables color XXX tomanvalores desde 0 hasta 31. La
tı́pica composición de color a partir de los tres básicos. El problema de esta
función es que como se puede observar no se ha especificado el texto que que-
remos colorear, porque cambia el color de manera global, un color diferente por
pantalla. Todo texto escrito con anterioridad o de forma posterior al uso de esta
función obtendrá el color que le indiquemos. Lo pueden ver en los ejemplos 5 y
5b de este capı́tulo (cap02ej05 y cap02ej05b).
La segunda opción nos permite algo más de libertad a la hora de colorear
diferentes carácteres o palabras, pero en cambio nos limita los colores. Con
PA SetTextTileCol(pantalla, color) disponemos de 10 opciones, la variable color
varia de 0(blanco) a 9(negro), predefinidas para cambiar el color del texto cuan-
do queramos. Lo que hace es cambiar el color actual con el que vamos a escribir,
es como cambiar de bolı́grafo, lo escrito anteriormente no se modifica. Además
podemos cambiar de color en mitad de una misma cadena, con cierto forma.
Más claro se ve con un ejemplo :
Recorte de Cap02/cap02ej06/source/main.c
11 u8 k ;
12 f o r ( k = 0 ; k < 1 0 ; k++)
13 {
14 PA SetTextTileCol ( 1 , k ) ;
15 PA OutputSimpleText ( 1 , 2 , 2+k , " Mas colores
que Benetton !" ) ;
16 }
17
18 int entero = 123;
19 PA OutputText ( 1 , 0 , 1 4 , " %c1Incluso %c2en %c3una %
c4misma %c5f %c6r %c7a %c8s %c9e %c3 %d" , e n t e r o ) ;
Recomiendo al lector que observe el resultado final de esas lı́neas de código
para terminar de asimilar el ejemplo, la aplicación escribirá 10 veces la cadena
Mas colores que Benetton! con los 10 colores disponibles una debajo de la otra;
y luego imprimirála cadena Incluso en una misma frase 123 en diversos colores.
Como se puede observar se usa %cX para cambiar el color en mitad de una
cadena, a partir de ese elemento todo lo que se escriba tendrá el color indicado.
2.4. USANDO FUENTES PERSONALIZADAS 19
2.4. Usando Fuentes Personalizadas
La fuente predefinida no es mala, pero quizás queramos personalizarla, por
ejemplo darle un aspecto más futurista medieval con el propósito de adaptarla
a la estética general del juego. Tenemos una función que cambiará la fuen-
te que vayamos a utilizar PA InitCustomText(pantalla,fondo,nueva fuente), panta-
lla y fondo deben de ser los mismo que hayamos iniciado anteriormente con
PA InitText(pantalla, fondo), nueva fuente es el nombre identificativo de nuestra
fuente personalizada cargado en memoria (Ejemplo Cap02/cap02ej07). ¡CUI-
DADO! Tenesmos que iniciar la fuente personalizada antes de usarla ya que
borra todo el texto anteriormente escrito.
Ahora tenemos que aprender a añadir esas fuentes personalizadasa nues-
tro proyecto, el proceso será el mismo que para añadir fondos y sprites, y
al principio puede resultaralgo complicado. Nos situamos en la carpeta don-
de instalamos DevKitPro, nos dirigimos a PAlib/Tools/ y copiamos la carpe-
ta PAGfx o PAGfx - Linux según corresponda, aunque la versión de Linux
habrá que compilarla e instalar. La pegamos dentro de la carpeta source de
nuestro proyecto y la renombramos a gfx, debe de quedar algo ası́ : DevKit-
Pro/nuestro proyecto/source/gfx/. En esa misma carpeta copiamos el archivo
Cap02/ cap02ej07/source/gfx/[Link], que será nuestra fuente persona-
lizada. Ejecutamos PAGC Frontend, aunque también podemos hacerlo por la
lı́nea de comandos ası́ resulta más sencillo, nos dirigimos a la pestaña de Back-
grounds, Add File, seleccionamos nuestro archivo, finalmente pulsamos sobre
Save and Convert y cuando termine el prompt cerramos. Esta aplicación lo
que hace es convertir las imágenes y fondos en archivos aptos para ser cargados
por nuestra aplicación, pero aún no están cargados. Para hacerlo simplemente
hemos de escribir las siguientes dos lı́neas al principio de nuestro código (o de-
bajo del include de PALib) :
#include "gfx/all_gfx.h"
#include "gfx/all_gfx.c"
Estas lı́neas se encargan de cargar todos los archivos exportados con PAGfx.
Hay algunos aspectos de este programa que no hemos comentado pero que ya
lo haremos en el apartado de sprites y fondos, que será más extenso. Sobre el
formato de la nueva fuente, hemos de decir que es un mapa de tiles, es decir,
cada letra ha de ser una imagen de 8x8 pı́xeles, espacio más que suficiente, y han
de estar en el orden dado por ese archivo. Para editar la imagen lo mejor es usar
la opción ”‘cuadrı́cula”’ o ”‘grid”’ de algunos editores de imágenes y darle una
separación de 8 pı́xeles tanto horizontal como verticalmente para conocer los
lı́mites de cada letra. Con un poco de maña y paciencia podemos tener cuantas
fuentes diferentes queramos personalizadas para nuestros juegos y aplicaciones.
2.5. Texto Avanzado
Finalmente y para cerrar este capı́tulo nos quedan dos tipos de texto, muy
similares entre sı́, 16c y 8bit. La diferencia más notable es la cantidad de colores
entre ellos, mientras que los textos 16c tienen 10 colores (yo tampoco sé de
donde sale el 16 entonces) los de 8bits pueden adquirir su color a través de la
20 CAPÍTULO 2. TRABAJANDO CON TEXTOS
paleta definida, teniendo un abanico de 256 colores posibles. Además el de tipo
8bit puede rotarse en ángulos de 90 grados, centrarse o hacerse transparente.
La ventaja frente al texto que ya hemos visto, es que dispone de 5 tamaños
diferentes, lo que resulta bastante útil.
2.5.1. 16cText
Al igual que en los casos anteriores tenemos que iniciar el fondo para traba-
jar con este tipo de texto, PA Init16cBg(pantalla, fondo). Luego simplemente lo
usamos de la manera PA 16cText(pantalla, inicio x , inicio y , fin x , fin y , texto
, color , tamano, numero de caracteres), donde el color toma valores de 0 a 9 y
tamaño de 0 a 4. De igual forma podemos añadir nuestras fuentes personali-
zadas con la función PA 16cCustomFont(slot, fuente), donde fuente es el nombre
identificativo con la que la hemos cargado (ver la sección de 2.4 para más infor-
mación sobre como cargar la fuente) y el slot es un número entre 0 y 9, contando
con que desde el 0 al 4 están ocupados por las predefinidas, aunque se puede
sobreescribir. Ejemplos Cap02/cap02ej08 y Cap02/cap02ej08b.
2.5.2. 8bitText
Es similar a todo lo visto anteriormente, el siguiente ejemplo reune todas las
opciones de este tipo de fuentes :
2.5. TEXTO AVANZADO 21
Recorte de Cap02/cap02ej09/source/main.c
11 //Como no hay ninguna p a l e t a cargada , agregamos
a l g u n o s c o l o r e s ”a mano”
12 PA SetBgPalCol ( 1 , 1 , PA RGB( 2 3 , 1 , 1 4 ) ) ;
13 PA SetBgPalCol ( 1 , 2 , PA RGB( 3 1 , 0 , 0 ) ) ;
14 PA SetBgPalCol ( 1 , 3 , PA RGB( 0 , 0 , 3 1 ) ) ;
15 PA SetBgPalCol ( 1 , 4 , PA RGB( 0 , 3 1 , 0 ) ) ;
16
17
18 // Debemos i n i c i a r e l f o n d o en 8 b i t
19 PA Init8bitBg (1 , 3) ;
20
21 // V a r i a s p r u e b a s de t e x t o
22 PA SmartText ( 1 , 0 , 1 , 2 5 5 , 2 0 , " Hello Mario !" , 1 , 0 ,
1 , 100) ;
23 PA SmartText ( 1 , 0 , 2 0 , 2 5 5 , 4 0 , " Hello Mario !" , 2 , 1 ,
1 , 100) ;
24 PA SmartText ( 1 , 0 , 4 0 , 2 5 5 , 6 0 , " Hello Mario !" , 3 , 2 ,
1 , 100) ;
25 PA SmartText ( 1 , 0 , 6 0 , 2 5 5 , 8 0 , " Hello Mario !" , 4 , 3 ,
1 , 100) ;
26 PA SmartText ( 1 , 0 , 8 0 , 2 5 5 , 1 0 0 , " Hello Mario !" , 1 , 4 ,
1 , 100) ;
27
28
29 // Texto r o t a d o 90 grados , OJO! e l o r i g e n de
c o o r d e n a d a s tambien r o t a
30 PA SmartText ( 1 , 1 , 1 , 1 9 0 , 2 0 , " Hello Mario !" , 3 , 3 ,
3 , 100) ;
31
32 // Texto c e n t r a d o
33 PA CenterSmartText ( 1 , 0 , 1 0 0 , 2 5 5 , 1 2 0 , " Hello Mario !"
, 2 , 4 , 1 ) ; // Same as Smart t e x t , b u t no l e t t e r
limit
En el ejemplo Cap02/cap02ej09b pueden encontrar como utilizar fuentes
personalizadas.