Si estas sentado en el computador viendo tus perfiles o descargando cuanta cosa pillas en Internet, quizás no sepas que ya estamos en la cuarta entrega de los tutoriales aplicados de GRRLIB, ¿qué esperas para echarles un ojo?.
En el capítulo anterior conseguimos escribir nuestro primer "Hola Mundo". Esto seguro que nos ha animado a seguir, pero de poco serviría si no pudiéramos conseguir una apariencia un poco más cuidada. Al fin y al cabo estamos utilizando una biblioteca que es capaz de explotar todas las capacidades gráficas del hardware de nuestra Wii.
En este capitulo vamos a aprender a utilizar las distintas funciones gráficas en 2D que implementa GRRLIB sin llegar a utilizar las texturas, ya que esto merece, por si sólo, la atención de la siguiente entrega.
Aunque imprimir vuestro primer "Hola Mundo" pueda haber sido un poco más difícil de lo habitual, podréis observar que a partir de ahora os resulta muy sencillo utilizar el resto de las funciones en 2D.
Comenzaremos explicando las principales funciones de dibujo en 2D para luego explicar paso a paso su aplicación en un programa.
void GRRLIB_FillScreen (const u32 color)
Borra la pantalla con el color especificado (en el formato RGBA).
bool GRRLIB_ScrShot ( const char* filename )
Crea una copia de la pantalla en el archivo que especificamos en filename con formato PNG.
void GRRLIB_SetBackgroundColour (u8 r, u8 g, u8 b, u8 a);
Asigna el color con el que se borrará la pantalla. En esta ocasión se le pasan los componentes RGBA por separado.
unsigned int GRRLIB_WidthTTF (GRRLIB_ttfFont* myFont, const char* string, unsigned int fontSize)
Esta función nos devuelve la anchura de la cadena de texto string en pixels. Se le debe pasar la fuente truetype en myFont y el tamaño de letra utilizado en fontSize.
void GRRLIB_Plot (const f32 x, const f32 y, const u32 color)
Dibuja un punto del color indicado en la posición x,y
void GRRLIB_Line (const f32 x1, const f32 y1, const f32 x2, const f32 y2, const u32 color)
Dibuja una línea del color indicado entre las posiciones x1,y1 y x2,y2.
void GRRLIB_Rectangle (const f32 x, const f32 y, const f32 width, const f32 height, const u32 color, const bool filled)
Dibuja un rectangulo de anchura width y altura height en la posición x,y.
Si filled es distinto de 0 el rectangulo se rellenará, en caso contrario sólo se dibujará el contorno.
void GRRLIB_Circle (const f32 x, const f32 y, const f32 radius, const u32 color,const u8 filled)
Dibuja un círculo de radio radius en la posición x,y.
Si filled es distinto de 0 el cículo se rellenará, en caso contrario sólo se dibujará el contorno.
void GRRLIB NGoneFilled ( const guVector v[ ], const u32 color[ ], const long n)
Dibuja un poligono de n lados.
El parámetro v es un array de elementos del tipo guVector que contiene los vértices del poligono.
El tipo guVector representa un punto o vector y contiene los valores de posición x,y,z de dicho punto.
El parámetro color es un array que contiene los colores que se aplicarán a cada uno de los vértices del polígono.
Por último, el parámetro n es el número de vértices.
Como habréis visto, GRRLIB nos ofrece muchas posibilidades a la hora de dibujar en 2D. Vamos ahora hacer un programa de ejemplo en el que aplicaremos lo que hemos visto.
He elegido un programa sencillo, que hace uso se varias de las funciones que hemos visto y que simplemente muestra en pantalla varias figuras geométricas. Concretamente dibujaremos una línea, un círculo, dos rectángulos (uno de ellos semitransparente) y un triángulo multicolor.
Aunque en GRRLIB no hay una función específica para dibujar triángulos, utilizaremos una función multipropósito que nos permitirá dibujar cualquier polígono y que además nos permitirá especificar colores diferentes para cada vértice, consiguiendo así efectos de gradiente. Dicha función es GRRLIB_NGoneFilled.
Vamos a seguir paso por paso el programa hasta obtener el programa completo.
Lo primero, y como en las entregas anteriores, crearemos un nuevo proyecto que basaremos en el programa que hicimos en la entrega anterior, incluyendo también la fuente verdana.ttf en la carpeta data y el fichero makefile que venimos usando hasta el momento.
Comenzamos incluyendo las bibliotecas necesarias:
#include <grrlib.h> #include <stdlib.h> #include <wiiuse/wpad.h> #include "verdana_ttf.h"
Para faciliar el uso de los colores añadiremos un listado de constantes correspondientes a los principales colores RGBA.
// Colores RGBA #define GRRLIB_BLACK 0x000000FF #define GRRLIB_MAROON 0x800000FF #define GRRLIB_GREEN 0x008000FF #define GRRLIB_OLIVE 0x808000FF #define GRRLIB_NAVY 0x000080FF #define GRRLIB_PURPLE 0x800080FF #define GRRLIB_TEAL 0x008080FF #define GRRLIB_GRAY 0x808080FF #define GRRLIB_SILVER 0xC0C0C0FF #define GRRLIB_RED 0xFF0000FF #define GRRLIB_LIME 0x00FF00FF #define GRRLIB_YELLOW 0xFFFF00FF #define GRRLIB_BLUE 0x0000FFFF #define GRRLIB_FUCHSIA 0xFF00FFFF #define GRRLIB_AQUA 0x00FFFFFF #define GRRLIB_WHITE 0xFFFFFFFF
Son todo colores opacos, por lo que si queremos añadir transparencias no nos servirán.
Ya entrando en el main llamamos a las funciones de inicialización que ya hemos explicado y declaramos una serie de variables que necesitaremos y explicaremos después.
Vamos a pasar directamente dentro del bucle while para observar como utilizamos las funciones de dibujo:
Las primeras líneas que nos encontramos son el chequeo de la tecla "home" para salir del programa, y la comprobación de la pulsación del botón "1" para realizar un volcado de la pantalla.
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) break; if (WPAD_ButtonsDown(0) & WPAD_BUTTON_1) GRRLIB_ScrShot("SCREEN.PNG");
Como vimos en el apartado anterior, la función GRRLIB_ScrShot creará el archivo "SCREEN.PNG" con una copia de lo que estamos visualizando en este momento.
Seguídamente continuamos con las funciones de dibujo própiamente dichas.
GRRLIB_FillScreen(GRRLIB_YELLOW); // Coloreamos la pantalla de amarillo GRRLIB_PrintfTTF(centro, 10, myFont, "Hola mundo", 20, GRRLIB_WHITE); GRRLIB_Rectangle(100, 100, 200, 100, GRRLIB_RED, 1); GRRLIB_Line(100, 100, 350, 200, GRRLIB_SILVER); GRRLIB_Rectangle(150, 150, 200, 200, 0x0000FFC8, 1); // Azul con transparencia GRRLIB_NGoneFilled(triangle, trianglecolor, 3);
La primera función a la que llamaremos es la función FillScreen, que nos permite borrar la pantalla rellenandola de un color especificado. En el ejemplo utilizamos la constante previamente definida GRRLIB_YELLOW que coloreará la pantalla de amarillo.
Seguidamente escribimos la palabra "Hola Mundo" tal y como vimos en la entrega anterior. Pero para poder mejorar el aspecto visual de nuestro texto vamos a intentar situar dicho cartel centrado horizontalmente.
Para poder centrar dicho texto horizontalmente necesitamos saber la resolución horizontal de la pantalla en pixels y lo que ocupa nuestro texto también en pixels.
El primer dato lo podemos considerar siempre constante y con un valor de 640. Esto vale para las dos resoluciones habituales que son (640x480 y 640x520).
El segundo dato es variable, y para averiguarlo necesitaremos echar mano de la función GRRLIB_WidthTTF que nos devolverá dicho valor.
Como hemos visto antes, la sintaxis de dicha función es:
unsigned int GRRLIB_WidthTTF (GRRLIB_ttfFont* myFont, const char* string, unsigned int fontSize) Donde: myFont - es la fuente true type utilizada. string - es la cadena de texto a mostrar fontSize - es el tamaño de la letra.
Una vez tenemos ambos datos, el cálculo de la posición x en la que debemos situar nuestro texto para que aparezca centrado es sencilla. En nuestro programa la guardaremos en una variable auxiliar, llamada centro, que declaramos al principio.
int centro = (640-GRRLIB_WidthTTF(myFont, "Hola mundo", 20))/2; // calculamos el centro de la pantalla
Haciendo uso de dicha variable es trivial escribir "Hola mundo" en el centro de la pantalla:
GRRLIB_PrintfTTF(centro, 10, myFont, "Hola mundo", 20, GRRLIB_WHITE);
Seguidamente dibujamos un triángulo de color rojo y una línea de color plata:
GRRLIB_Rectangle(100, 100, 200, 100, GRRLIB_RED, 1); GRRLIB_Line(100, 100, 350, 200, GRRLIB_SILVER);
La sintaxis de ambas funciones es muy sencilla y prácticamente idéntica. Los dos primeros parámetros son la posición x,y del primer vértice y los dos siguientes la posición del segundo vértice y el siguiente parámetro es el color RGBA.
GRRLIB_Rectangle tiene un parámetro adicional que indica si queremos que el rectángulo sea rellenado. Pasando un 1 el rectángulo será rellenado del color especificado.
Lo siguiente que añadiremos será un rectángulo azul para ver el efecto de las transparencias.
GRRLIB_Rectangle(150, 150, 200, 200, 0x0000FFC8, 1); // Azul con transparencia
Como vimos en el capitulo anterior si a un color RGBA le asignamos en sus dos últimos dígitos un valor inferior a FF conseguiremos un color con cierto grado de transparencia. Cuanto más pequeño sea dicho valor, más transparente será el color.
Como última función de dibujo vamos a ver GRRLIB_NGoneFilled.
GRRLIB_NGoneFilled es un poquito más complicada de usar que el resto de las funciones que hemos explicado, pero a cambio nos da mucha más versatilidad.
Con esta función vamos a poder dibujar un polígono tenga el número de lados que tenga.
Como GRRLIB no tiene una función específica para dibujar triángulos utilizaremos GRRLIB_NGoneFilled.
El formato de GRRLIB_NGoneFilled es como sigue:
void GRRLIB NGoneFilled ( const guVector v[ ], const u32 color[ ], const long n)
Necesitaremos pues declarar una variable que contenga un array de posiciones de vértices y otro array con los valores de los coloes de cada vértice.
Un triángulo tiene tres vértices por lo que necesitaremos un array de tres elementos con las coordenadas de cada vértice.
Aunque para representar las coordenadas de cada vértice en dos dimensiones necesitamos parejas de valores x e y, nuestra función GRRLIB_NGoneFilled utiliza el tipo guVector que permite representar coordenadas en tres dimensiones, por lo que nos sobrará la coordenada z que rellenaremos como 0.
guVector es un ejemplo de lo que en C se llama una estructura. Una estructura de C es una forma de agrupar varias variables en una sola.
En el caso de guVector nos encontramos con una estructura que agrupa las variables, x, y, z de tipo f32 o lo que es lo mismo números en coma flotante de 32 bits.
Agrupar estas tres variables en una sola es lo que nos permitirá hacer un array de datos con los valores x,y,z de cada vértice. Además C nos permite inicializar dichas variables, a la vez que las declaramos, con los valores de posición de los vértices del triángulo.
La línea de la declaración quedaría como sigue:
guVector triangle[] = {{400,200,0.0f}, {500,400,0.0f}, {300,400,0.0f}};
Además de las coordenadas necesitamos definir los valores de los colores de cada vértice mediante un array de valores de color.
u32 trianglecolor[] = {GRRLIB_GREEN, GRRLIB_RED, GRRLIB_BLUE};
Con la ayuda de estas dos variables ya podemos hacer la llamada a la función GRRLIB_NGoneFilled que quedaría como sigue:
GRRLIB_NGoneFilled(triangle, trianglecolor, 3);
El programa final quedaría así:
#include <grrlib.h> #include <stdlib.h> #include <wiiuse/wpad.h> #include "verdana_ttf.h" // Colores RGBA #define GRRLIB_BLACK 0x000000FF #define GRRLIB_MAROON 0x800000FF #define GRRLIB_GREEN 0x008000FF #define GRRLIB_OLIVE 0x808000FF #define GRRLIB_NAVY 0x000080FF #define GRRLIB_PURPLE 0x800080FF #define GRRLIB_TEAL 0x008080FF #define GRRLIB_GRAY 0x808080FF #define GRRLIB_SILVER 0xC0C0C0FF #define GRRLIB_RED 0xFF0000FF #define GRRLIB_LIME 0x00FF00FF #define GRRLIB_YELLOW 0xFFFF00FF #define GRRLIB_BLUE 0x0000FFFF #define GRRLIB_FUCHSIA 0xFF00FFFF #define GRRLIB_AQUA 0x00FFFFFF #define GRRLIB_WHITE 0xFFFFFFFF int main(int argc, char **argv) { guVector triangle[] = {{400,200,0.0f}, {500,400,0.0f}, {300,400,0.0f}}; u32 trianglecolor[] = {GRRLIB_GREEN, GRRLIB_RED, GRRLIB_BLUE}; // Inicializar gráficos GRRLIB_Init(); // Inicializar wiimotes WPAD_Init(); GRRLIB_ttfFont *myFont = GRRLIB_LoadTTF(verdana_ttf, verdana_ttf_size); // lo convertimos al formato usado por GRRLIB int centro = (640-GRRLIB_WidthTTF(myFont, "Hola mundo", 20))/2; // calculamos el centro de la pantalla while(1){ WPAD_ScanPads(); // Leer mandos // Si pulsamos home salimos del bucle if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) break; if (WPAD_ButtonsDown(0) & WPAD_BUTTON_1) GRRLIB_ScrShot("SCREEN.PNG"); GRRLIB_FillScreen(GRRLIB_YELLOW); // Coloreamos la pantalla de amarillo GRRLIB_PrintfTTF(centro, 10, myFont, "Hola mundo", 20, GRRLIB_WHITE); GRRLIB_Rectangle(100, 100, 200, 100, GRRLIB_RED, 1); GRRLIB_Line(100, 100, 350, 200, GRRLIB_SILVER); GRRLIB_Rectangle(150, 150, 200, 200, 0x0000FFC8, 1); // Azul con transparencia GRRLIB_NGoneFilled(triangle, trianglecolor, 3); GRRLIB_Render(); // Refrescamos la pantalla } GRRLIB_FreeTTF (myFont); // Liberamos la fuente truetype GRRLIB_Exit(); // Liberamos memoria exit(0); // Usar exit para salir del program (no usar return desde el main) }
Y esto es todo por ahora.
En nuestra próxima entrega veremos como se utilizan las texturas, que combinandolo con lo que hemos visto hasta ahora, serán la base para la creación de un bonito "button tester" gráfico.
Comentarios
=/
Buen tuto, pero hubieras explicado como usas la función de captura de pantalla, seguro muchos usuarios se liaran con eso xD
Saludos!
Me lo apunto para editarlo.
Me lo apunto para editarlo. ;)
Gracias por el aviso.