Lección 5: Mapas de bits

Requerimientos: Haber leído Lección 4.

En la lección anterior vimos cómo mover un cuadrado con los botones direccionales.

En esta lección veremos cómo utilizar una imagen en vez de un cuadrado, para representar a nuestro jugador.

Para reemplazar al cuadrado, hemos elegido esta imagen (archivo .bmp  monocromático)



Para poder visualizar un mapa de bits en la consola, es necesario traducirlo a un conjunto de bytes (cada byte está formado por 8 bits). En esos bytes, van a estar representados los pixels negros como bits en 0 y los pixeles blancos como bits en 1.

Esta conversión puede realizarse fácilmente en el sitio http://www.bloggingadeadhorse.com/TeamARGImgConverter/

Solo se necesita arrastrar la imagen a convertir y aparecerá la conversión correspondiente.

Por ahora no entraremos en detalle en dicha conversión. Solo diremos que como resultado de la conversión obtenemos:

const unsigned char PROGMEM jugador[] =
{
// ancho, alto,
24, 24,
0x00, 0xfe, 0xfe, 0x8e, 0x76, 0xfa, 0xaa, 0x8a, 0x8a, 0xf6, 0x0e, 0xfe, 0xfe, 0x0e, 0xf6, 0xaa, 0x8a, 0x8a, 0xfa, 0x76, 0x8e, 0xfe, 0xfe, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xe6, 0xdb, 0xdf, 0xdf, 0xdb, 0xe6, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x7f, 0x7f, 0x78, 0x7a, 0x70, 0x76, 0x76, 0x60, 0x6e, 0x6e, 0x60, 0x6e, 0x6e, 0x60, 0x76, 0x76, 0x76, 0x70, 0x7a, 0x78, 0x7f, 0x7f, 0x00,
};
 

Del conjunto de bytes, los 2 primeros valores corresponden al ancho y alto de la imagen. El resto de los valores representan los pixeles de la imagen.

El nombre de este conjunto de bytes recibirá el nombre de “jugador”, el cual a partir de ahora representará la imagen del jugador.

Para el ancho y alto de la imagen, definiremos 2 constantes:

const int ANCHO_BITMAP = 24;
const int ALTO_BITMAP = 24; 

que luego referenciaremos en nuestro código.

Una constante, al igual que una variable, almacena información. Sin embargo una constante, una vez inicializada con un valor, no puede modificarse durante la ejecución del programa. 

Para crear una constante, se utiliza la palabra clave const al principio de la declaración.

Para mostrar en pantalla una imagen, se utiliza la función  drawBitmap(), la cual recibe como parámetro la ubicación de la esquina superior izquierda de la imagen, y la imagen codificada:

geo.drawBitmap(jugadorX, jugadorY, jugador);
 

El código final quedaría:

#include <Geobuino.h>
Geobuino geo;
 
const int ANCHO_BITMAP = 24;
const int ALTO_BITMAP = 24;
 
const unsigned char PROGMEM jugador[] =
{
// ancho, alto,
ANCHO_BITMAP, ALTO_BITMAP,
0x00, 0xfe, 0xfe, 0x8e, 0x76, 0xfa, 0xaa, 0x8a, 0x8a, 0xf6, 0x0e, 0xfe, 0xfe, 0x0e, 0xf6, 0xaa, 0x8a, 0x8a, 0xfa, 0x76, 0x8e, 0xfe, 0xfe, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xe6, 0xdb, 0xdf, 0xdf, 0xdb, 0xe6, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x7f, 0x7f, 0x78, 0x7a, 0x70, 0x76, 0x76, 0x60, 0x6e, 0x6e, 0x60, 0x6e, 0x6e, 0x60, 0x76, 0x76, 0x76, 0x70, 0x7a, 0x78, 0x7f, 0x7f, 0x00,
};
 
int jugadorX = 0;
int jugadorY = 0;
 
void setup() {
  geo.begin();
}
 
void loop() {
  geo.waitFrame();
  geo.clearDisplay();
  
  if (geo.pressedButton(BTN_LEFT) && jugadorX>0) {
    jugadorX = jugadorX - 1;
  }
  if (geo.pressedButton(BTN_RIGHT)  && jugadorX< (DISPLAY_WIDTH-ANCHO_BITMAP)) {
    jugadorX = jugadorX + 1;
  }
  if (geo.pressedButton(BTN_UP) && jugadorY>0) {
    jugadorY = jugadorY - 1;
  }
  if (geo.pressedButton(BTN_DOWN) && jugadorY< (DISPLAY_HEIGHT-ALTO_BITMAP)) {
    jugadorY = jugadorY + 1;
  }
  
  geo.drawBitmap(jugadorX, jugadorY, jugador);
}
 

 

Al enviar el sketch a la consola, veremos la imagen del jugador, la cual podremos mover con los botones direccionales.