La interfaz gráfica de bajo nivel
Cuando
se diseñó J2ME, los ingenieros de Sun ya sabían que una de las claves
para que su tecnología tuviera éxito era que tenía que ser capaz de
hacer funcionar juegos, y hacerlo de forma medianamente decente. Para
ello debían dotar a los MIDlets de la capacidad de controlar la
pantalla al más bajo nivel posible, es decir, a nivel gráfico.
En
el capítulo anterior, hemos profundizado en las clases que nos
permitían trabajar con interfaces de usuario. Todas ellas derivaban de
la clase Screen, que a su vez derivaba de Displayable. Si nos fijamos en el diagrama de clases vemos como de Displayable también deriva la clase Canvas. Esta clase es capaz de mostrar información gráfica a nivel de píxel. Es por ellos que la llamamos interfaz de bajo nivel.
Básicamente podemos realizar tres operaciones sobre un Canvas:
- Dibujar primitivas gráficas
- Escribir texto
- Dibujar imágenes
Es
este capítulo vamos a cubrir estas operaciones, y así sentar las bases
necesarias para abordar las materias concretas relativas a la
programación de videojuegos.
Tal
y como hicimos en el anterior capítulo utilizaremos un código de
ejemplo para ir explicando sobre él los conceptos básicos.
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class Canvas1 extends MIDlet implements CommandListener { private Command exitCommand; private Display display; private SSCanvas screen; public Canvas1() { display=Display.getDisplay(this); exitCommand = new Command("Salir",Command.SCREEN,2); screen=new SSCanvas(); screen.addCommand(exitCommand); screen.setCommandListener(this); } public void startApp() throws MIDletStateChangeException { display.setCurrent(screen); } public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable s) { if (c == exitCommand) { destroyApp(false); notifyDestroyed(); } } } class SSCanvas extends Canvas { public void paint(Graphics g) { g.setColor(255,255,255); g.fillRect (0, 0, getWidth(), getHeight()); q.setColor(10,200,100); g.drawLine (0, 0, 100, 100); g.fillRect (50, 50, 30, 30); } }
La Primera parte del código, es decir, la clase Canvas1
debe ya sernos familiar. La única diferencia con el código del
capítulo anterior, es que, en lugar de utilizar un objeto de la clase Form como pantalla principal de la aplicación, utilizamos uno derivado de la clase SSCanvas que implementamos justo debajo.
private SSCanvas screen;
Como puedes observar, la clase SSCanvas hereda de la clase Canvas. Es por ello que podemos utilizarla como pantalla principal (recuerda que Canvas es una clase derivada de Displayable).
class SSCanvas extends Canvas {
La clase SSCanvas implementa el método paint(), que hereda de la clase Canvas.
Éste es el método que se invoca cada vez que la pantalla necesita ser
redibujada. Por lo tanto, todo el código encargado de pintar en la
pantalla ha de situarse aquí.
public void paint(Graphics g) {
El parámetro g, es el llamado contexto gráfico, que es de tipo Graphics.
Esta clase posee los métodos necesarios para dibujar en pantalla,
mostrar gráficos y mostrar textos. Las siguientes líneas se ocupan de
borrar la pantalla y dibujar una línea y un rectángulo utilizando los
métodos de la clase Graphics.
Vamos a entrar a continuación en detalles sobre los métodos de esta clase.
Primitivas Gráficas
Colores
En
la naturaleza hay millones de posibles tonalidades de color.
necesitamos pues un método que nos permita expresar un color concreto
de una gama muy amplia. Newton, experimentando con un prisma de vidrio,
constató como la luz podía descomponerse en una serie de colores
básicos. Lo cierto es que este experimento sólo trataba de reproducir
lo que en la naturaleza conocemos como arco iris, que se produce por la
difracción de la luz al atravesar las gotas de agua. Un color, por lo
tanto, se forma a partir de las distintas aportaciones de los colores
básicos. Según predomine más o menos cada color básico, el color
resultante será distinto. Utilizando esta misma técnica, en informática
utilizamos tres colores básicos para especificar colores complejos.
Estos colores son el Rojo, el Verde y el Azul, y abreviamos con RGB (de
Red, Green y Blue).
Código RGB | Color |
---|---|
255, 0, 0 | Rojo |
0, 255, 0 | Verde |
0, 0, 255 | Azul |
128, 0, 0 | Rojo oscuro |
255, 255, 0 | Amarillo |
0, 0, 0 | Negro |
255, 255, 255 | Blanco |
128, 128, 128 | Gris |
Para especificar el color que queremos utilizar al dibujar en la pantalla utilizamos el método setColor() de la clase Graphics.
void setColor(int rojo, int verde, int azul)
Los parámetros de color tienen un rango de 0 a 255.
Pero,
no todos los dispositivos poseen pantalla a color. El siguiente método
establece un tono de gris dentro de la grama de grises de una pantalla
monocromo.
void setGrayScale(int tono)
El parámetro tono puede tomar un valor entre 0 y 255.
Primitivas
Aunque
no vamos a necesitarlas muy a menudo para desarrollar nuestros juegos,
es interesante que conozcamos las primitivas básicas con las que
contamos para dibujar.
void drawLine (int x1, int y1, int x2, int y2)
Este método dibuja una línea que une los puntos de la coordenada (x1, y1) de la pantalla y la coordenada (x2, y2).
void drawRect (int x, int y, int ancho, int alto)
Con drawRect()
podemos dibujar rectángulos. Los parámetros x e y indican cual será la
esquina superior izquierda del rectángulo, mientras que los otros dos
parámetros nos indican el ancho y el alto que tendrá el rectángulo en
píxeles.
En
nuestro programa de ejemplo, además de utilizarlo para dibujar un
cuadrado, le hemos asignado la misión de borrar la pantalla. Esto se
hace dibujando un rectángulo del tamaño de la pantalla del dispositivo y
de color blanco.
void drawRoundRect (int x, int y, int ancho, int alto, int ancho_arco, int alto_arco)
Este método es similar a drawRect(), excepto porque sus esquinas son redondeadas. Los otros dos parámetros son al ancho y el alto del arco de las esquinas.
void drawArc(int x, int y, int ancho, int alto, int ángulo_inicial, int ángulo)
Con drawArc()
seremos capaces de dibujar secciones de arco. Los cuatro primeros
parámetros no deberían necesitar ya explicación. El perámetro ángulo_inicial
indica cual será el ángulo a partir del que se comenzará a dibujar el
segmento de arco. El parámetro ángulo indica la longitud de arco (en
grados) que será dibujado.
void fillRect (int x, int y, int ancho, int alto) void fillRoundRect (int x, int y, int ancho, int alto, int ancho_arco, int alto_arco) void fillArc(int x, int y, int ancho, int alto, int ángulo_inicial, int ángulo)
Estos
tres métodos son iguales que los anteriores con la diferencia de que la
primitiva que dibujan estará rellena. Es decir, dibuja las primitivas
como sólidas en lugar de huecas.
Texto
Aunque
estemos trabajando a nivel gráfico, es muy probable que necesitemos
mostrar información textual en pantalla. Un ejemplo claro es el marcador
de puntuación de un juego.
El método que nos permite escribir texto en un Canvas es:
void drawString (String texto, int x, int y, int ancla)
El
primer parámetro es el texto que queremos mostrar. Los parámetros x e y
es la posición donde queremos situar el texto dentro de la pantalla.
El cuarto parámetro indica cuál es el punto de referencia para situar
el texto en las coordenadas deseadas. Los valores posibles son TOP, BASELINE y BUTTOM para la posición vertical del texto y LEFT, HCENTER y RIGHT
para la posición horizontal del texto. Por ejemplo, si quisiéramos
posicionar un texto en la posición 100,100 y con centro en la esquina
superior izquierda utilizaremos la siguiente línea:
g.drawString (“Hola.”, 100, 100, Graphics.LEFT | Graphics.TOP);
Ahora que tenemos control sobre la posición del texto, nos falta por controlar el tipo de letra que queremos utilizar.
void setFont(Font fuente)
Esta función selecciona la fuente a utilizar. El método getFont() de la clase Font nos devuelve un objeto de tipo Font que podemos utilizar con setFont().
static Font getFont (int espaciado, int estilo, int tamaño)
Los valores posibles para estos parámetros son:
Para... | Variables |
---|---|
Tamaño | SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE |
Estilo | STYLE_PLAIN, STYLE_ITALICS, STYLE_BOLD, STYLE_UNDERLINED |
Espaciado | FACE_SYSTEM, FACE_MONOSPACE, FACE_PROPORTIONAL |
Veamos un ejemplo:
Font fuente = Font.getFont (Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_MEDIUM); g.setFont(fuente);
Imágenes
Las
primitivas gráficas nos permiten ya cierta capacidad de dibujar
gráficos, pero para crear un videojuego, necesitamos algo más
elaborado. La clase Graphics nos ofrece dos métodos:
public static Image createImage(String name) throws IOException
El método createImage()
carga un archivo gráfico en formato .PNG. Dependiendo del dispositivo
podrá soportar más formatos gráficos, pero en principio, al menos, debe
soportar el formato .PNG. Recuerda que los gráficos (y el resto de
recursos, como sonidos, etc...) han de estar en el directorio ‘res’.
boolean drawImage(Image img, int x, int y, int ancla)
El último parámetro es similar al de drawString(). Sus posibles valores son TOP, VCENTER y BUTTON para la posición vertical y LEFT, HCENTER, RIGHT para la posición horizontal.
Veamos un ejemplo:
Image img = Image.createImage(“\logo.png”); g.drawImage (img, 10, 10, Graphics.HCENTER, Graphics.VCENTER);
El siguiente código es un ejemplo real de lo que hemos visto en éste capítulo.
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class Canvas2 extends MIDlet implements CommandListener { private Command exitCommand; private Display display; private SSCanvas screen; public Canvas2() { display=Display.getDisplay(this); exitCommand = new Command("Salir",Command.SCREEN,2); screen=new SSCanvas(); screen.addCommand(exitCommand); screen.setCommandListener(this); } public void startApp() throws MIDletStateChangeException { display.setCurrent(screen); } public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void commandAction(Command c, Displayable s) { if (c == exitCommand) { destroyApp(false); notifyDestroyed(); } } } class SSCanvas extends Canvas { public void paint(Graphics g) { Image img=null; // Borrar la pantalla g.setColor(255,255,255); g.fillRect (0, 0, getWidth(), getHeight()); // Dibujar línea g.setColor(10,200,100); g.drawLine (0, 80, getWidth(), 80); // Poner texto Font fuente = Font.getFont (Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_MEDIUM); g.setFont(fuente); g.drawString("J2ME", getWidth()/2, 10,Graphics.BASELINE|Graphics.HCENTER); // Cargar y mostrar gráfico try { img = Image.createImage("/logo.png"); } catch (Exception e) { System.err.println("error: " + e); } g.drawImage (img, getWidth()/2, 40, Graphics.HCENTER|Graphics.VCENTER); } }
No hay comentarios.:
Publicar un comentario