Objetivo del curso
En este curso, se creará una nueva clase que se encargue de los diálogos del juego. Siguiendo el estilo de juego RPG, cuando se muestre el texto por pantalla se hará de forma pausada para que de tiempo a leerlo y cuando el usuario pulse una tecla, salte al siguiente texto. En esta primera entrega estará centrada en la clase dialogo.
Programación
Se va a programar las siguientes funciones: menor, mayor, numlineas, crea, pinta, y cambia_texto.
La funcion menor, compara dos variables y devuelve el contenido de la variable de menor valor.
La función mayor, compara dos variables y devuelve el contenido de la variable de mayor valor.
La función numlineas, calcula el número de lineas que se necesita para mostrar un texto dentro de un rectángulo determinado.
Esta función sería mucho mas simple en el caso de que la fuente utilizada tenga la cualidad de que todos sus caracteres ocupen el mismo ancho, es decir, que por ejemplo la "W" ocupe lo mismo que la "l". Pero como la mayoría no es así, se complica un poco para averiguar cuantos caracteres caben en un ancho determinado. Por ello, se va cogiendo carácter a carácter hasta completar una linea sin llegar a sobrepasar el limite dado por el rectángulo. Debido a esto es algo complejo averiguar cuantas lineas van a ocupar, aunque si es fácil averiguar cuantas lineas es el máximo que cabe en el espacio definido por el rectángulo. El número total de lineas que ocupará el texto es almacenado en la variable nlineas.
La función crea, se encarga de inicializar las variables de la clase y define texto que se va a mostrar y las dimensiones del rectángulo de texto.
Esta función recibe como parámetro el texto a mostrar, la fuente ( tipo de letra ), y las dimensiones del cuadro de dialogo. Inicializa los valores que utiliza la clase, y se asegura que las coordenadas para definir el tamaño del rectángulo estén de forma correcta. Y calcula el ancho y alto del rectángulo.
La función pinta, se encarga de mostrar por pantalla el rectángulo de dialogo. Coloca en lo mejor posible el texto ajustado al tamaño del rectángulo.
Esta función se encarga de pintar un rectángulo, y sobre el se pinta el texto de manera que este centrado dentro de el todo el texto. En el caso de que el texto no cabe en una linea según el ancho del rectángulo, se realiza un bucle que se encarga de cojer carácter a carácter y va formando las lineas para que no superen el ancho del rectángulo. Una vez que llega al ancho muestra la linea, y vuelve a repetir el proceso con lo que queda por mostrar. Esta forma de hacerlo tiene un inconveniente, y es que cada vez que se muestra se vuelve a calcular todo, por tanto es un proceso algo lento.
Aquí en este video se muestra un ejemplo utilizando la librería, creando varios cuadros de diálogos de distintos tamaño, mostrando un texto que se ajusta según va variando el tamaño de estos rectángulos.
La función cambia_texto, como su nombre indica sirve para cambiar el texto.
Programación
Se va a programar las siguientes funciones: menor, mayor, numlineas, crea, pinta, y cambia_texto.
La funcion menor, compara dos variables y devuelve el contenido de la variable de menor valor.
int menor(int x, int y){ if ( x < y ){ return x; }else{ return y; } }
La función mayor, compara dos variables y devuelve el contenido de la variable de mayor valor.
int mayor(int x, int y){ if ( x < y ){ return y; }else{ return x; } }
La función numlineas, calcula el número de lineas que se necesita para mostrar un texto dentro de un rectángulo determinado.
void MENSAJE::numlineas(){ int cont; int espacio = 0; char* mtexto = (char*)stexto.c_str(); nlineas=1; if ( tancho+espaciado > ancho ){ // no cabe en una linea string resto = stexto; string trozo; char caracter[] = " "; char* caracter2; int nuevoancho = 0; int nc = 0; int restoancho = 0; do{ cont=1; trozo = resto.substr(0,cont); mtexto = (char*)trozo.c_str(); nuevoancho = text_length( fuente, mtexto ); espacio = 0; while ( nuevoancho+espaciado < ancho ){ trozo = resto.substr(cont,1); caracter2 = (char*)trozo.c_str(); if ( strcmp(caracter2,caracter)==0 ){ espacio = cont; } cont++; trozo = resto.substr(0,cont); mtexto = (char*)trozo.c_str(); nuevoancho = text_length( fuente, mtexto ); } nc = resto.length(); trozo = resto.substr(cont,1); caracter2 = (char*)trozo.c_str(); nlineas++; if ( espacio >0 && cont < nc && strcmp(caracter2,caracter)!=0 ) { resto = resto.substr(espacio); }else{ resto = resto.substr(cont); } restoancho = text_length( fuente, resto.c_str() ); }while( restoancho+espaciado > ancho ); } }
Esta función sería mucho mas simple en el caso de que la fuente utilizada tenga la cualidad de que todos sus caracteres ocupen el mismo ancho, es decir, que por ejemplo la "W" ocupe lo mismo que la "l". Pero como la mayoría no es así, se complica un poco para averiguar cuantos caracteres caben en un ancho determinado. Por ello, se va cogiendo carácter a carácter hasta completar una linea sin llegar a sobrepasar el limite dado por el rectángulo. Debido a esto es algo complejo averiguar cuantas lineas van a ocupar, aunque si es fácil averiguar cuantas lineas es el máximo que cabe en el espacio definido por el rectángulo. El número total de lineas que ocupará el texto es almacenado en la variable nlineas.
La función crea, se encarga de inicializar las variables de la clase y define texto que se va a mostrar y las dimensiones del rectángulo de texto.
void MENSAJE::crea(const char* t, FONT* f, int x1, int y1, int x2, int y2){ stexto = t; tancho = text_length( f, t ); talto = text_height(f) + espaciado; fuente = f; mx1 = menor(x1,x2); mx2 = mayor(x1,x2); my1 = menor(y1,y2); my2 = mayor(y1,y2); ancho = abs( mx1 - mx2 ); alto = abs( my1 - my2 ); numlineas(); };
Esta función recibe como parámetro el texto a mostrar, la fuente ( tipo de letra ), y las dimensiones del cuadro de dialogo. Inicializa los valores que utiliza la clase, y se asegura que las coordenadas para definir el tamaño del rectángulo estén de forma correcta. Y calcula el ancho y alto del rectángulo.
La función pinta, se encarga de mostrar por pantalla el rectángulo de dialogo. Coloca en lo mejor posible el texto ajustado al tamaño del rectángulo.
void MENSAJE::pinta(BITMAP* b){ int cont; int espacio = 0; char* mtexto = (char*)stexto.c_str(); int linea=0; int ni; int altura = 0; float exacto; BITMAP *cuadro = create_bitmap(ancho,alto); clear_to_color(cuadro, 0x222222); set_trans_blender(0,0,0,130); draw_trans_sprite(b, cuadro, mx1, my1); set_trans_blender(0,0,0,255); rect(b, mx1-1, my1-1, mx2-1, my2-1, 0xfcf902); rect(b, mx1+1, my1+1, mx2+1, my2+1, 0x363712); rect(b, mx1, my1, mx2, my2, 0x222222); if ( tancho+espaciado > ancho ){ // no cabe en una linea string resto = stexto; string trozo; char caracter[] = " "; char* caracter2; int nuevoancho = 0; int nc = 0; int restoancho = 0; do{ cont=1; trozo = resto.substr(0,cont); mtexto = (char*)trozo.c_str(); nuevoancho = text_length( fuente, mtexto ); espacio = 0; while ( nuevoancho+espaciado < ancho ){ trozo = resto.substr(cont,1); caracter2 = (char*)trozo.c_str(); if ( strcmp(caracter2,caracter)==0 ){ espacio = cont; } cont++; trozo = resto.substr(0,cont); mtexto = (char*)trozo.c_str(); nuevoancho = text_length( fuente, mtexto ); } nc = resto.length(); trozo = resto.substr(cont,1); caracter2 = (char*)trozo.c_str(); if ( espacio >0 && cont < nc && strcmp(caracter2,caracter)!=0 ){ trozo = resto.substr(0,espacio); mtexto = (char*)trozo.c_str(); resto = resto.substr(espacio); }else{ trozo = resto.substr(0,cont); mtexto = (char*)trozo.c_str(); resto = resto.substr(cont); } altura = alto - (talto*nlineas); exacto = ( alto / nlineas ); ni = int( exacto ); textout_centre_ex(b, fuente, mtexto, mx1+1+int(ancho/2), my1+2+(ni*linea)-(talto/2)+(ni/2) , 0x363712, -1); textout_centre_ex(b, fuente, mtexto, mx1+int(ancho/2), my1+1+(ni*linea)-(talto/2)+(ni/2) , 0xffffff, -1); linea++; restoancho = text_length( fuente, resto.c_str() ); }while( restoancho+espaciado > ancho ); mtexto = (char*)resto.c_str(); textout_centre_ex(b, fuente, mtexto, mx1+1+int(ancho/2), my1+2+(ni*linea)-(talto/2)+(ni/2) , 0x363712, -1); textout_centre_ex(b, fuente, mtexto, mx1+int(ancho/2), my1+1+(ni*linea)-(talto/2)+(ni/2) , 0xffffff, -1); }else{ textout_centre_ex(b, fuente, mtexto, mx1+(ancho/2)+1, my1+1+((alto-talto)/2), 0x363712, -1); textout_centre_ex(b, fuente, mtexto, mx1+(ancho/2), my1+((alto-talto)/2), 0xffffff, -1); } destroy_bitmap(cuadro); };
Esta función se encarga de pintar un rectángulo, y sobre el se pinta el texto de manera que este centrado dentro de el todo el texto. En el caso de que el texto no cabe en una linea según el ancho del rectángulo, se realiza un bucle que se encarga de cojer carácter a carácter y va formando las lineas para que no superen el ancho del rectángulo. Una vez que llega al ancho muestra la linea, y vuelve a repetir el proceso con lo que queda por mostrar. Esta forma de hacerlo tiene un inconveniente, y es que cada vez que se muestra se vuelve a calcular todo, por tanto es un proceso algo lento.
Aquí en este video se muestra un ejemplo utilizando la librería, creando varios cuadros de diálogos de distintos tamaño, mostrando un texto que se ajusta según va variando el tamaño de estos rectángulos.
La función cambia_texto, como su nombre indica sirve para cambiar el texto.
void MENSAJE::cambia_texto( const char* t){ stexto = t; tancho = text_length( fuente, t ); numlineas(); };
Esta función se encarga de cambiar el texto a mostrar, actualizando los valores del texto.
La clase se define de la siguiente manera
class MENSAJE{ string stexto; FONT *fuente; // ancho total del texto enviado int tancho; int talto; // para delimitar el rectangulo de vision int mx1,my1; int mx2,my2; // ancho y alto del rectangulo int ancho, alto; // numero de lineas totales q caben en el rectangulo int nlineas; void numlineas(); public: void crea(const char* t, FONT* f, int x1, int y1, int x2, int y2); void pinta(BITMAP* b); void cambia_texto( const char* t ); };
La clase creada se ha llamado MENSAJE.
- stexto : contiene el texto a mostrar
- fuente : contiene el tipo de letra que se utilizará para escribir el texto.
- tancho y talto : son dimensiones del texto según la fuente utilizada.
- mx1,my1 y mx2,my2 : son las coordenadas que delimitan nuestro cuadro de dialogo.
- ancho, alto: son las dimensiones del cuadro de dialogo.
- nlineas: indica el numero de líneas que ocupa el texto para mostrarse en el cuadro de dialogo.
- numlineas() : función privada que se encarga de contar el número de lineas.
También se debe de añadir al principio del código los #include, para incluir las librerías que se utilizan "allegro.h" y la de "string". Y definir una constate llamada "espaciado", con un valor 10. ( este valor se puede modificar según se quiera dejar mas o menos margen entre el border del cuadro y el texto), para ello debes escribir:
#define espaciado 10
Para que no tengan problema con esta nueva librería, les dejo el siguiente link para descargar dialogos.h en archivo RAR.
Donde se declara la variable "espaciado"? Me sale un error porque esta no sé detecta, y cuando busco la palabra en la página, solo sale siendo usada pero nunca declarada
ResponderEliminarHola Satoshi, tienes razón no esta declarado "espaciado", es una constante que le puse el valor de 10 con el siguiente comando:
Eliminar#define espaciado 10
Muchas gracias por avisar del error.