13 Apr 2015
Práctica 5 - Imagen
Introducción
En esta práctica vamos a trabajar con los diferentes modos para cada pantalla que son: Texto, gráficos en 2D, fondos, sprites y gráficos en 3D.
Imprimiendo o dibujando texto
consoleDemoInit()
Con el tipo de datos de PrintConsole
tenemos acceso a una estructura de datos que almacena el estado del contexto de una consola.
Hasta ahora hemos aprovechado de la función consoleDemoInit
para poder tener una consola de forma más cómoda sin tener que preocuparnos de ninguna configuración. Si vemos la implementación de esta función:
PrintConsole* consoleDemoInit(void) {
videoSetModeSub(MODE_0_2D);
vramSetBankC(VRAM_C_SUB_BG);
return consoleInit(NULL,
defaultConsole.bgLayer,
BgType_Text4bpp,
BgSize_T_256x256,
defaultConsole.mapBase,
defaultConsole.gfxBase,
false,
true);
}
Podemos observar que primero activa la pantalla sub en modo MODE02D y después activa el banco de VRAM_C para el uso de fondo. Luego devuelve el resultado de una llamada a consoleInit()
que devuelve un puntero a la consola creada. Pasa como parámetros a consoleInit()
: NULL
como puntero de consola ya que está creando una nueva instancia de PrintConsole, Luego los valores de la estructura defaultConsole
para layer, mapBase y tileBase. Para los valores de type y size referentes al fondo de la consola pasa como tipo de fondo el de 4 bits y tamaño 256x256. Por último pasa false
para el parámetro de mainDisplay y true
para loadGraphics.
printbothscreens
En este ejemplo para configurar el video pone ambas pantallas en modo MODE02D mediante las instrucciones:
videoSetMode(MODE_0_2D);
videoSetModeSub(MODE_0_2D);
Luego reserva el banco VRAMA para el fondo de la pantalla principal y el banco VRAMC para el fondo de la pantalla secundaria.
vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankC(VRAM_C_SUB_BG);
Para terminar, inicializa las consolas pasando referencias a objetos PrintConsole para cada pantalla, como parámetro de layer el 3, de mapBase el 31 y de tileBase el 0. el resto de parámetros son igual que con consoleDemoInit()
, variando el valor de mainDisplay dependiendo de qué referencia de consola ha sido pasada, de la pantalla superior o de la pantalla secundaria.
consoleInit(&topScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true);
consoleInit(&bottomScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true);
custom_font
En este ejemplo se asigna a la consola una fuente creada por el usuario, esto lo consigue importando la cabecera de la fuente font.h
que fue generada pasando al programa grit la imagen font.bmp. A continuación dejemos una muestra de ese fichero .bmp con 95 caracteres 8x8 en RGB.
Las letras A, B y C de font.bmp
rotscale_text
En este ejemplo muestra el mismo texto que el de custom_font pero además nos permite mediante las teclas realizar movimientos, rotación y escalado de lo que hay en pantalla. Las diferencias más importantes son que en este nuevo ejemplo utilizan el MODE_5_2D
para el modo de video y a la hora de inicializar la consola como parámetro de background layer utilizan el 3 para luego poder hacer las transformaciones de lo visualizado en pantalla ya que con el modo 5 de la pantalla sub solo los BG2 y BG3 permiten Rotoscale
.
Gráficos en 2D
Fondos
rotation
Pasamos al tema de los fondos de pantalla con un primer ejemplo que permite la rotación, escalado de una imagen integrada en el programa.
Captira del programa
rotation
Esto lo consigue variando los parámetros de las siguientes funciones:
static void bgSetCenter(int id, int x, int y)
Permite mover el centro de rotación del fondo referenciado por id en el punto x,y.static void bgSetRotateScale(int id, int angle, int sx, int sy)
Permite escalar el fondo id con sx,sy y además rotar la imagen angle cantidad, un angle positivo gira en sentidos del reloj, un angle negativo al contrario.static void bgSetScroll(int id, int x, int y)
Permite desplazar el fondo id en pantalla en x,y cantidad. Un x positivo es desplazar a la izquierda, un x negativo a la derecha. Un y positivo implica un desplazamiento hacia abajo, un y negativo, hacia arriba.
El programa tiene variables para cada uno de los parámetros de las funciones anteriores y mediante los botones podemos ir variando los valores, la asignación de los botones es la siguiente:
- Left: Incrementar scroll en el eje x.
- Right: Decrementar scroll en el eje x.
- Up: Incrementar scroll en el eje y.
- Down: Decrementar scroll en el eje y.
- A: Incrementar escalado en el eje x.
- B: Decrementar escalado en el eje x.
- X: Incrementar escalado en el eje y.
- Y: Decrementar escalado en el eje y.
- L: Incrementar angle en 20.
- R: Decrementar angle en 20.
- Start: Incrementar centro de rotación en el eje x.
- Select: Incrementar centro de rotación en el eje y.
Cabe indicar que hay un problema con el ejemplo tal como está implementado ya que han asignado el boton start a dos operaciones, aparte de modificar el centro de rotación, en la linea #78 realiza un break
si está pulsado este botón y entonces termina el programa.
16bitcolorbmp
Este ejemplo nos muestra como cargar una imagen en formato png como fondo de pantalla, hemos modificado el programa para que cargue una imagen creada por nosotros.
Captura del programa 16bitcolor_bmp con imagen personalizada
256colorbmp
En este ejemplo también podemos cambiar la imagen de fondo por una nuestra pero si basamos en la imagen por defecto, al cargar el programa el fondo es demasiado grande para la pantallas de la NDS.
En este ejemplo para cargar el fondo lo realiza mediante dos llamadas a dmaCopy()
una para copiar el bitmap a la sección de memoria del BG3 y otra para cargar el pallete de la imagen. En el ejemplo anterior utilizan la función decompress()
.
allinone
Este ejemplo proporciona muestras de muchas de las funciones con fondos que tiene libnds.
- Basic: Estos ejemplos muestran las imágenes que están almacenadas en ensamblador.
Handmade Text 256x256
Text 256x256
Text 256x512
Text 512x256
Text 512x512
Extended Rotation 128x128
Extended Rotation 256x256
Extended Rotation 512x512
Extended Rotation 1024x1024
Rotation 128x128
Rotation 256x256
Rotation 512x512
Rotation 1024x1024
- Bitmap:
Estos ejemplos ya utilizan imágenes en formato bmp pero creado dinámicamente con números aleatorios.
256 color 128x128
256 color 256x256
256 color 512x256
256 color 512x512
256 color 512x1024
256 color 1024x512
16-bit color 128x128
16-bit color 256x256
16 bit color 512x256
16-bit color 512x512
- Scrolling:
Text Backgrounds
Rot Backgrounds
Vertical Scrolling
Horizontal Scrolling (Text)
Horizontal Scrolling (ExRot)
4 Way Scrolling (Text)
4 Way Scrolling (Rotation)
Aquí tenemos diversos ejemplos de modificación avanzada de imágenes
- Advanced:
Mosaic
Rotation
Scaling
Extended Palette
Multiple Text Layers
Sprites
songeventsexample
Este ejemplo utiliza un .png pasado por grit como sprite mediante la función dmaCopy()
tras la inicialización del sprite engine con oamInit()
y oamAllocateGfx()
.
songeventsexample2
Aquí en vez de utilizar una imagen ya creada, utiliza un struct para crear dinámicamente los sprites, aún así, hace uso de las mismas funciones que el ejemplo anterior.
allocation_test
Captura del programa
allocation_test
Para poder elegir tamaños de sprite de forma aleatoria, hacen uso de un struct que contiene todas los posibles tamaños de sprite.
Captura del struct
sizes
Luego para cada sprite tienen un struct mySprite
con contenido adicional de lo que tiene el OAM, para referenciar a todos los sprites tienen un array de mySprite
llamado sprites
con un contador allocationCount
para llevar el número de sprites instanciados.
El ejemplo también hace uso de varias funciones de la OAM:
oamAllocateGfx(OamState * oam, SpriteSize size, SpriteColorFormat colorFormat)
oamFreeGfx(OamState * oam, const void * gfxOffset)
oamSet(OamState * oam, int id, int x, int y, int priority, int palette_alpha, SpriteSize size, SpriteColorFormat format, const void * gfxOffset, int affineIndex, bool sizeDouble, bool hide, bool hflip, bool vflip, bool mosaic)
oamInit(OamState * oam, SpriteMapping mapping, bool extPalette)
oamUpdate(OamState * oam)
simple
En este ejemplo hay un sprite de forma cuadrada en cada una de las dos pantallas de la NDS y si pinchamos en la pantalla táctil ambos sprites se mueven a esa posición en su correspondiente pantalla.
Captura del programa
simple
Para mover los sprites hacen uso de la función oamSet()
y luego el oamUpdate()
para cada una de las pantallas de la consola. Para cada pantalla cambian los parámetros del oamState
y del gfxOffset
(dirección de memoria del sprite)
fireandsprites
Este ejemplo genera sprites de dos maneras distintas, cargando de un fichero y generando dinámicamente.
En la pantalla de abajo genera 128 sprites con forma de pelota cargada del fichero ball.pcx colocando cada sprite en una posición aleatoria. En la pantalla de arriba genera dinámicamente un efecto de fuego y plasma.
Gráficos en 3D
Textured_Quad
En este primer ejemplo de gráficos 3D muestran en pantalla una imagen 128x128 de 16bits que mediante las teclas de flechas permite mover la imagen sobre un eje centrado en la imagen. Hemos cambiado la imagen cargada por una nuestra.
Captura del programa
textured_quad
Para cargar la imagen hacen uso da la siguiente función:
int glTexImage2D(int target, int empty1, GL_TEXTURE_TYPE_ENUM type, int sizeX, int sizeY, int empty2, int param, const void * texture)
donde texture
es una cabecera auto-generado a partir de la imagen.
Para trabajar con las texturas en 3D hacen uso de las siguientes funciones:
glInit()
Para inicializar la maquina de estados de gl.glEnable(int bits)
Para habilitar estados de gl como por ejemplo el alpha, la mezcla, etc..glClearColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
Colocar el color del plano trasero(necesario para activar antialiasing).glClearPolyID(uint8 ID)
Poner la id del polígono del plano trasero(necesario para activar antialiasing).glClearDepth(fixed12d3 depth)
Resetea el buffer de profundidad al valor depth.glViewport(uint8 x1, uint8 y1, uint8 x2, uint8 y2)
glGenTextures(int n, int *names)
Reserva sitio para n texturas.glBindTexture(int target, int name)
Pasa la textura name a ser la textura activa.glTexImage2D(int target, int empty1, GL_TEXTURE_TYPE_ENUM type, int sizeX, int sizeY, int empty2, int param, const void *texture)
Carga una textura 2D en la memoria de textura y aplica a la textura activa el resto de los atributos.glMatrixMode(GL_MATRIX_MODE_ENUM mode)
Cambiar el modo de la matriz activa.glLoadIdentity(void)
Carga una matriz de identidad en la matriz activa.gluPerspective(float fovy, float aspect, float zNear, float zFar)
Crea la matriz de proyección.gluLookAt(float eyex, float eyey, float eyez, float lookAtx, float lookAty, float lookAtz, float upx, float upy, float upz)
Coloca la camera en la ubicación y orientación especificada.glPushMatrix(void)
Inserta la matriz activa en la pila.glTranslatef32(int x, int y, int z)
Multiplica la matriz activa por una matriz de traducción.glRotateX(float angle)
Gira la matriz activa en angle grados sobre el eje x.glRotateY(float angle)
Gira la matriz activa en angle grados sobre el eje y.glMaterialf(GL_MATERIALS_ENUM mode, rgb color)
especifica las propiedades de la material a usar en el renderizado de los polígonos iluminados.glMaterialShinyness(void)
glPolyFmt(u32 params)
Colocar los parámetros para los polígonos en el marco actual.glBegin(GL_GLBEGIN_ENUM mode)
Arranca un grupo de polígonos.glNormal(u32 normal)
glVertex3v16(v16x, v16y, v16z)
Especificar un vertice.glEnd()
Termina un grupo de polígonos.glPopMatrix()
Desapila num matrices de la pila.glFlush(u32 mode)
Espera a un Vblank y intercambia los buffers.
Ortho
Este ejemplo muestra un cubo en 3D donde cada lado del cubo es nuestra imagen. El cubo mueve en las 3 dimensiones de forma automática sin interacción del usuario.
Captura del programa
Ortho
Para cargar la imagen hace uso de
loadPCX(const unsigned char * pcx, sImage * image)
y luego glTexImage2D()
como en el ejemplo anterior.
Además de las funciones de gl utilizadas en el ejemplo anterior Ortho hace uso de la función:
glLight(int id, rgb color, v10 x, v10 y, v10 z)
Para crear iluminicación en la escena.
Hasta la próxima,
Mark, Víctor y Lluís
at 13:40