lunes, 29 de diciembre de 2014

TEMA #10: LA INTERFAZ DE BAJO NIVEL (GAMECANVAS) I: DIBUJANDO



Hasta ahora, todo lo que hemos visto son elementos que se adaptan a la pantalla del celular donde se ejecutan, de manera automática. Cualquier aplicación/juego que construyamos con lo que hemos visto hasta ahora se adaptará a la pantalla de cualquier celular, incluso si son táctiles ya que estos elementos tienen soporte táctil incluido. Ahora, en este tema, veremos algo nuevo ya que lo que creamos no se adapta a cualquier pantalla, y por eso debemos manejarlo con cuidado.

Este tema está titulado Interfaz de Bajo Nivel; esto no quiere decir que sea de menor importancia que la de Alto Nivel, sino que se llama así porque nos permite trabajar a un nivel más “básico”, a un nivel más “bajo”, a nivel de píxeles.
Antes de adentrarnos a la Interfaz de Bajo Nivel debemos conocer qué es un píxel y algunos datos para entender mejor cómo funciona la interfaz usando los píxeles como referencia.

Píxeles
Un píxel se puede definir como la parte más pequeña de una imagen.  En internet hay varias definiciones y mencionan que un pixel puede ser cuadrado o rectangular, lo cierto es que un píxel sólo puede tomar un color a la vez. Veamos la siguiente imagen:


Lo que podemos ver son muchos cuadros y cada uno tiene un color específico. Cada uno de esos cuadros es un píxel y dependiendo del color de cada píxel se dibuja una imagen, claro, estamos hablando a nivel informático. Si acercamos lo suficiente una imagen (zoom) que tengamos en nuestra computadora podremos ver sus píxeles.

Hoy en día vemos como existen muchos dispositivos con cámara (celulares, tablets, cámaras digitales propiamente dichas,...), y cada uno de ellos tiene una capacidad determinada en píxeles, pero ¿qué quiere decir esto? La capacidad en píxeles que tiene un dispositivo corresponde a que las fotos que toma tienen esa cantidad de cuadros, por ejemplo, un celular con una cámara de 2 Megapíxeles toma fotos que tienen 2 millones de cuadros, y uno con 5 Megapíxeles toma fotos que tienen 5 millones de píxeles.

Ahora, esos píxeles pueden distribuirse de una manera diferente, según la cámara del dispositivo, y aún así conservar la misma cantidad de píxeles; y esto se especifica a través de la resolución de la imagen. La resolución de la imagen se puede definir como la cantidad de píxeles de ancho por la cantidad de píxeles de alto que tiene una imagen. Veamos las siguientes imágenes:






Supongamos que tenemos dos celulares, A y B, ambos con una cámara de 16 píxeles (0.000016 Megapíxeles), el celular A tomó la fotografía A y el segundo tomó la fotografía B. Como podemos observar, ambas imágenes tienen la misma cantidad de píxeles pero distribuidos de manera diferente (4x4 en A y 2x8 en B). Así, puede haber imágenes con la misma cantidad de píxeles pero distribuidos de manera diferente, por eso, cuando vayamos a hablar de una imagen en este curso hablaremos de resolución y no de los píxeles que tenga una imagen.

Esto también se aplica a las pantallas de nuestras computadoras, la mía, por ejemplo, tiene una resolución de 1280x800 píxeles; también se aplica, por supuesto, a las pantallas de nuestros celulares, y es lo que debemos tomar en cuenta a la hora de utilizar la Interfaz de Bajo Nivel.

Si no sabes cuál es la resolución de la pantalla de tu celular, conócela antes de continuar este tema. La siguiente aplicación te dirá cuál es la resolución de la pantalla de tu celular y por tanto, la que podremos utilizar en la Interfaz de Bajo Nivel. Descargar App.     


GameCanvas
Un GameCanvas es un tipo de variable que representa un lienzo de dibujo, en el que podemos dibujar distintos elementos gráficos, siempre tomando como referencia los píxeles. Se define de manera sencilla:

GameCanvas lienzo = new GameCanvas(boolean bloquearTeclado){
...
};

Como vemos, tenemos la variable de tipo GameCanvas y el nombre es “lienzo”. La definimos como ya hemos visto para las variables de la Interfaz de Alto Nivel. El parámetro bloquearTeclado permite decidir si queremos que el teclado alfanumérico de nuestro celular pueda ser usado cuando se muestra este lienzo (true) o no (false). Por ejemplo, en los juegos de celular es muy usada la Interfaz de Bajo Nivel, y si el parámetro bloquearTeclado estuviera true, en esos juegos no podríamos manejar el personaje o realizar cualquier acción a través del teclado alfanumérico de nuestro celular.

Ya definido el lienzo debemos hacer un paso extra antes de empezar a dibujar en él, y es implementar un método llamado paint, y lo hacemos así:

GameCanvas lienzo = new GameCanvas(boolean bloquearTeclado){
          public void paint(Graphics g){
              g.setColor(255, 255, 255);
              g.fillRect(0, 0, getWidth(), getHeight);
              …
          }
};

Como vemos, este método utiliza como parámetro una variable de tipo Graphics, que en este caso la hemos llamado “g” (generalmente es el nombre más usado, y siempre lo usaremos en este curso). Las dos líneas de código que están en cursiva lo que van a hacer es teñir el lienzo de blanco para que esté listo y podamos pintar dentro de él, aunque se puede pintar del color que se quiera. Veamos más adelante.

Ahora que sabemos cómo definir el lienzo, los elementos que podemos dibujar en el incluyen: formas geométricas, texto e imágenes; pero primero veremos cómo seleccionar un color.


Color
El color en Java está representado por tres valores de tipo int y que representan a los colores rojo, verde y azul, es por eso que la selección de color es RGB (siglas en inglés de Red, Green y Blue). Cada uno de estos valores definirá cuánto de cada color se utilizará y puede ser desde 0 hasta 255. El color se puede elegir a través del método g.setColor(int red, int green, int blue);, siendo “g” el nombre de la variable de tipo Graphics.

GameCanvas lienzo = new GameCanvas(boolean bloquearTeclado){
          public void paint(Graphics g){
              g.setColor(int red, int green, int blue);
          }
};

Los colores se obtienen de la mezcla de estos tres colores. Veamos algunos ejemplos de colores:

Colores
Valores RGB
Representación
Blanco
.setColor(255, 255, 255);

Negro
.setColor(0, 0, 0);

Gris
.setColor(128, 128, 128);

Rojo
.setColor(255, 0, 0);

Verde
.setColor(0, 255, 0);

Azul
.setColor(0, 0, 255);

Amarillo
.setColor(255, 255, 0);

Morado
.setColor(255, 0, 255);

Descarga esta aplicación en la que podrás elegir el color de cada componente RGB y ver qué color resulta. Descargar App.      


Formas Geométricas
Las formas geométricas que podemos dibujar en Java y sus correspondientes definiciones las veremos en la siguiente tabla:

Figura
Definición
Línea
g.drawLine(int x1, int y1, int x2, int y2);
Rectángulo (contorno)
g.drawRect(int x, int y, int ancho, int alto);
Rectángulo con bordes redondeados (contorno)
g.drawRoundRect(int x, int y, int ancho, int alto, int xBorde, int yBorde);
Círculo (contorno)
g.drawArc(int x, int y, int ancho, int alto, int inicio, int grados);
Triángulo (sólo con relleno)
g.fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3);

Vemos que en todas las definiciones tenemos que proporcionar una serie de parámetros numéricos. Estos parámetros numéricos corresponden a píxeles y van a determinar desde qué píxel hasta cuál píxel de la pantalla se dibujará una forma, imagen o texto, de allí la importancia de conocer la resolución de la pantalla de nuestro celular.

El significado de los parámetros de cada definición son los siguientes:

                 Línea

  1.  x1: es el punto de inicio de la línea en el eje horizontal.
  2.  y1: es el punto de inicio de la línea en el eje vertical.
  3.  x2: es el punto de culminación de la línea en el eje horizontal.
  4.  y2: es el punto de culminación de la línea en el eje vertical.

                 Rectángulo

  1. x: es el punto de inicio del rectángulo en el eje horizontal.
  2. y: es el punto de inicio del rectángulo en el eje vertical.
  3. ancho: es el ancho del rectángulo, en píxeles.
  4. alto: es el alto del rectángulo, en píxeles.

                 Rectángulo con bordes redondeados

  1. x: es el punto de inicio del rectángulo en el eje horizontal.
  2. y: es el punto de inicio del rectángulo en el eje vertical.
  3. ancho: es el ancho del rectángulo, en píxeles.
  4. alto: es el alto del rectángulo, en píxeles.
  5. xBorde: es la magnitud del borde redondeado en el eje x.
  6. yBorde: es la magnitud del borde redondeado en el eje y.

                 Círculo

  1. x: es el punto de inicio del círculo en el eje horizontal.
  2. y: es el punto de inicio del círculo en el eje vertical.
  3. ancho: es el diámetro del círculo, en píxeles.
  4. alto: es el alto del círculo, en píxeles.
  5. inicio: es el grado (º) desde donde se iniciará a dibujar el círculo.
  6. grados: determina cuántos grados de círculo se dibujarán. Si se coloca 360 en este valor se dibujará un círculo completo.

                 Triángulo

  1. x1: es el componente horizontal del vértice 1 del triángulo.
  2. y1: es el componente vertical del vértice 1 del triángulo.
  3. x2: es el componente horizontal del vértice 2 del triángulo.
  4. y2: es el componente vertical del vértice 2 del triángulo.
  5. x3: es el componente horizontal del vértice 3 del triángulo.
  6. y3: es el componente vertical del vértice 4 del triángulo.

Para dibujar figuras rellenas se utiliza la misma definición que para su correspondiente figura con sólo contorno, pero en lugar de la palabra “draw” utilizamos la palabra “fill”: g.fillRect(int x, int y, int ancho, int alto);,... En el caso del triángulo, sólo existe g.fillTriangle(...); y no existe g.drawTriangle(...);. Veamos un ejemplo gráfico:



Supongamos que queremos dibujar un cuadrado (lo hacemos con el mismo del rectángulo), desde el punto amarillo hasta el punto azul, lo hacemos así: g.drawRect(2, 2, 3, 3);. Ahora, supongamos que queremos dibujar un rectángulo desde el punto verde hasta el punto rojo, lo hacemos así: g.drawRect(10, 9, 6, 4);. Si queremos dibujar una línea desde el punto amarillo hasta el punto rojo, lo hacemos así; g.drawLine(2, 2, 15, 12);. Con la práctica vamos a ir aprendiendo todo esto. Si queremos dibujar un triángulo cuyo vértice 1 sea el punto azul, el vértice 2 sea el punto negro y el vértice 3 sea el punto verde, lo hacemos así: g.fillTriangle(4,  4,  4,  9,  10,  9);.


Texto
Para dibujar texto en un GameCanvas lo hacemos a través del método .drawString(...);, veamos cómo se define:

Método
Notas
g.drawString(String texto, int x, int y, int referencia);
El primer parámetro es el texto que queremos dibujar. Los parámetros x e y son un punto como hablamos anteriormente en el ejemplo gráfico de formas geométricas. El parámetro referencia determina cómo se va a ubicar el texto con respecto al punto de referencia que hemos fijado con x e y.

Existen varios valores para el parámetro referencia y vamos a verlos a través de un ejemplo gráfico.



Supongamos que el punto naranja es el punto de referencia que hemos fijado y vemos cómo se colocará el texto dependiendo del valor del parámetro referencia. Es algo confuso porque pareciera estar al revés, sin embargo, debemos recordar que estos parámetros van a determinar dónde se ubicará el punto de referencia con respecto al texto. Hay dos que no mencionamos que son: Graphics.HCENTER y Graphics.BASELINE, que van a situar el punto de referencia en el medio del texto en sentido horizontal y en la línea de base en sentido vertical, respectivamente.
Algo importante es que debemos obligatoriamente seleccionar dos valores para el parámetro referencia, uno horizontal (LEFT, RIGHT, HCENTER) y uno vertical (TOP, BOTTOM, BASELINE), y los unimos con el operador “|”. Ejemplo, g.drawString(“Hola”, 2, 2, Graphics.LEFT|Graphics.TOP);. En este ejemplo, el punto de referencia estará ubicado en la coordenada (2,2), y éste se ubicará arriba y a la izquierda del texto (Graphics.LEFT|Graphics.TOP):




Se puede también elegir el tipo de letra con la que se va a trabajar a través de .setFont(Font font);, pero no vamos a detenernos en este método.


Imágenes
El método que se utiliza para dibujar una imagen es .drawImage(...);, veamos cómo se define:
Método
Notas
g.drawImage(Image imagen, int x, int y, int referencia);
El primer parámetro es la imagen que queremos dibujar, para lo cual debemos definir primero la imagen como lo mencionamos en la Interfaz de Alto Nivel, y siempre tomando en cuenta atrapar el error que se produce.
Los parámetros x e y son un punto de referencia, como hablamos anteriormente. El parámetro referencia determina cómo se va a ubicar la imagen con respecto al punto de referencia que hemos fijado con x e y.

Los valores para el parámetro referencia son los mismos que mencionamos para el dibujado de texto, sin embargo hay una excepción, para dibujar imágenes no existe la referencia Graphics.BASELINE;, en lugar de ésta referencia tenemos Graphics.VCENTER; que va a colocar el punto de referencia en el punto medio de la imagen, en sentido vertical (es parecido a HCENTER pero en sentido vertical).

De igual manera que mencionamos para el dibujado del texto, se deben usar dos referencias, una horizontal y una vertical. Ejemplo: Graphics.HCENTER|Graphics.VCENTER.

Ahora veamos un código de una aplicación donde utilizamos todo lo que hemos aprendido en este tema, dibujando formas geométricas, texto e imágenes. Descargar código y recursos.     

Descargar la aplicación de ejemplo. Descargar App.      

No hay comentarios.:

Publicar un comentario