scribble

Tactics DS

Sobre nosotros Blog de desarrollo GitHub

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

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.

Captura del programa rotation

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 16_bit_color_bmp con imagen custom

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.

image

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.

image

Handmade Text 256x256

image

Text 256x256

image

Text 256x512

image

Text 512x256

image

Text 512x512

image

Extended Rotation 128x128

image

Extended Rotation 256x256

image

Extended Rotation 512x512

image

Extended Rotation 1024x1024

image

Rotation 128x128

image

Rotation 256x256

image

Rotation 512x512

image

Rotation 1024x1024

  • Bitmap:

Estos ejemplos ya utilizan imágenes en formato bmp pero creado dinámicamente con números aleatorios.

image

256 color 128x128

image

256 color 256x256

image

256 color 512x256

image

256 color 512x512

image

256 color 512x1024

image

256 color 1024x512

image

16-bit color 128x128

image

16-bit color 256x256

image

16 bit color 512x256

image

16-bit color 512x512

  • Scrolling:

image

Text Backgrounds

image

Rot Backgrounds

image

Vertical Scrolling

image

Horizontal Scrolling (Text)

image

Horizontal Scrolling (ExRot)

image

4 Way Scrolling (Text)

image

4 Way Scrolling (Rotation)

Aquí tenemos diversos ejemplos de modificación avanzada de imágenes

  • Advanced:

image

Mosaic

image

Rotation

image

Scaling

image

Extended Palette

image

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

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

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

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.

image

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

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

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

scribble

Sobre nosotros Blog de desarrollo GitHub