Heyyyyyyyyyyyyyyy

Aprende a programar microcontroladores en C... http://tecdigitaldelbajio.com/software-tarjeta.html

viernes, 5 de noviembre de 2010

Ejemplo #23 Animación usando la Clase Sprite



Ya se ha visto en el blog varios ejemplos de la clase GameCanvas, una clase de la API para juegos de Java Micro Edition, contenida en el paquete javax.microedition.lcdui.game, pero este paquete tiene más clases en total son cinco clases más que ayudan al desarrollo de juegos, una de ellas es la clase Sprite, que hoy es la que se va analizar.

¿Qué es un Sprite?
Un Sprite es cualquier objeto gráfico que esta aparece en la pantalla del juego, ya se vio en el ejemplo #19 como realizar la animación de una pelotita por toda la pantalla, pues ese es un objeto gráfico, ese es un Sprite.
Sprite Animados
Existen dos tipos de sprite: los sprite estáticos, una imagen vale más que mil palabras y en la figura siguiente se muestran dos sprite estáticos, el fondo y la pelotita que, como recordará el lector se mueve por toda la pantalla y rebota, aún así a pesar de ello la pelotita es un Sprite estático.



Ahora vea la siguiente animación, ahí se muestra un sprite animado,  qué es el otro tipo de sprite.
>

El Sprite, animado se forma por dos o más imágenes, en el caso de la animación anterior, que por cierto muestra a Mario, un famoso personaje de los video juegos que va caminando, se forma por 3 imágenes, las cuales son mostradas en la figura siguiente
 
Las tres imágenes se diseñaron para que juntas puedan simular que Mario camina.

En el ambiente de los juegos cada imagen es llamada “frame” o se podría decir fotograma en español, para realizar la animación, Java necesita las imágenes tal y como se muestran en la imagen anterior, un fotograma seguido del otro, en un arreglo horizontal como el de la figura o también se puede hacer en un arreglo vertical, es importante el tamaño, muy importante, en este caso, la imagen para cada fotograma mide 32 pixeles de ancho y 62 de alto, la imagen con los tres fotogramas juntos mide 96*62, Java para optimizar obtiene los datos de cada uno de los fotogramas de una sola imagen, en otros tiempos era necesario ingresar una a una las imágenes, ahora no es necesario, se carga una imagen con los fotogramas y Java hace el resto..
Por cierto,  a cada fotograma Java le asigna un índice, un único número, que inicia en 0 y termina con el último fotograma.
Código para la creación del sprite


El primer paso para crear un Sprite, es cargar las imágenes en variables de tipo Image, tal y como se observa en el siguiente código:
        mario = Image.createImage("/Mario96_62.gif");
        fondo = Image.createImage("/fondo.jpg");
No se muestra pero, es obvio que las variables “fondo” y “mario” deben ser declaradas antes de este código como variables de tipo Image, esto ya se hizo en ejemplos anteriores, también recuerde que estas instrucciones deben ser encerradas con su try y catch, tampoco se muestra por que ya se vio en ejemplos anteriores del blog y también el MIDlet donde se probo NO fue creado con el "hello MIDlet" como otros proyectos por eso la ruta de la imagen no lleva el "/hello/".
El segundo paso es la creación del Sprite, primeramente deben declarar dos variables de tipo sprite así:
       Sprite sprFondo;
       Sprite sprMario;
Con lo anterior apenas se reserva espacio en memoria, falta el código que de verdad crea los sprites, por cierto son dos tipos diferentes de Sprite, el fondo que va a ser un sprite estático y el de Mario caminando que es un Sprite animado,  el código siguiente crea el sprite para el fondo:
     sprFondo = new Sprite(fondo);
Con lo anterior se crea el sprite, vea que simple fue, el constructor de la clase solo lleva un parámetro que es la imagen y listo, ahora vea el código para el Sprite animado:
sprMario = new Sprite(mario, 32, 62);
El constructor ahora lleva tres parámetros, uno que es la imagen la que contiene los tres fotogramas y dos parámetros más que son el ancho y alto de cada fotograma y listo, Java se encarga de manipular los fotogramas y mostrarlos en la pantalla del celular, uno tras otro.
Es muy importante la dimensión, en base al ancho (32) del fotograma que se envía al constructor con el código anterior, Java espera una imagen que sea múltiplo de 32, por eso es que nuestra imagen de mide 96*62, así Java sabe que solo son tres fotogramas los que se reproducirán automáticamente, cualquier dimensión que no sea múltiplo del ancho o del alto Java no cargaría la imagen al momento de ejecutar el programa y no podríamos ver ninguna animación.
Dibujando el Sprite
Para mostrar en la pantalla el sprite se debe hacer uso del método paint, así:
sprMario.paint(g);
sprFondo.paint(g);
Este método lleva como parámetro el objeto “g” que es el objeto de tipo Graphics usado para dibujar en el GameCanvas como ya se ha visto en ejemplos pasados. Este método se escribe dentro del while(true) del método run(), recuerde que en este método se realiza la animación como se vio en ejemplos pasados.
Moviendo los fotogramas
El método nextFrame, me permite ir avanzando por los fotogramas de la animación, si yo no lo uso, el sprite animado simplemente se quedaría en una única imagen y no se movería, el método debe ir dentro del ciclo while, del método run, así se usa:
sprMario.nextFrame();
Cada que se ejecuta este método, el sprite avanza un fotograma, automáticamente Java controla esto, así que cuando llega al tercer fotograma en nuestro caso, se vuelve a mostrar el primer fotograma y así sucesivamente, en un ciclo infinito.
Moviendo el Sprite
Existe un método que me permite mover el sprite, el método es llamado “move” y con él se mueve el Sprite a la velocidad que uno desee, un ejemplo del uso de este método es como sigue:
sprMario.move(5, 5);
Con esa instrucción el sprite se mueve en el eje x y en el eje y a una velocidad de 5 pixeles, esto implica que “mario caminaría” en diagonal, si deseo que camine en línea recta que es lo normal para un sprite como el que estamos trabajando sería así:
sprMario.move(5, 0);
Vea la coordenada en Y esta en 0 así no hay incremento en Y y el Sprite avanzaría en línea recta.
Por otro lado, el sprite automáticamente realiza los incrementos de la variable, así que yo no me preocupo en incrementar la posición para realizar la animación, en verdad que esta clase me evita mucho código y me facilita las cosas muchísimo.
¿Dónde aparece el Sprite?
Para poder definir donde debe aparecer el Sprite, por “default” aparece en la posición (0,0) de la pantalla,  se usa el método setPosition, por ejemplo:
sprMario.setPosition(10, 90);
Ubicará al Sprite dentro del GameCanvas en la posición 10 en x y 90 en Y, con este método se puede colocar el Sprite donde nosotros deseemos.
Video-Tutorial
Finalmente el video muestra el ejemplo completo que hace que el sprite de Mario camine en línea recta, por la pantalla. Se anima al lector para que experimente cambiando la posición y velocidad para que vaya viendo por si mismo los cambios y así queden más claros los ejemplos y las instrucciones vistas en este articulo.
El video inicia ya con el Midlet creado y la subclase AnimacionSprite que deriva con GameCanvas, inclusive ya con el código para el botón de Salir, se baso en el Ejemplo #18 y el
#19
 


Aún así aquí les dejo comprimido todas las carpetas que genera NetBeans 6.8, para este ejemplo, puedes probar el archivo JAR directamente en tu celular, este como se recordará está en la carpeta “dist”, inclusive, en la carpeta “src” está el código fuente además de las imágenes usadas en el ejemplo, obvio incluye la imagen de Mario con los tres fotogramas.


Clic AQUI para leer más...!

viernes, 15 de octubre de 2010

Ejemplo #22 "Como enviar datos de la interfaz de alto nivel al GameCanvas"



Como continuación del ejemplo #21, ahora se verá en este ejemplo como enviar datos desde la interfaz de alto nivel a la interfaz de bajo nivel, este es una forma para poder capturar datos del usuario y usarlos en la clase GameCanvas, recuerde que en esta clase no existe forma alguna para que el usuario introduzca los datos.

El ejemplo de hoy va a hacer uso del código Java del ejemplo #19, el cuál puedes ver dando clic aqui, el ejemplo, como se recordará muestra la animación de una pelotita que está rebotando por toda la pantalla, una y otra vez, pero lo hace a una velocidad constante siempre, hoy se mostrará cómo se puede elegir desde la interfaz de alto nivel, la velocidad de la pelotita la cual se enviará a la interfaz de bajo nivel para que la pelotita responda a esta velocidad.

Interfaz de alto nivel

La imagen siguiente muestra la interfaz de alto nivel para este ejemplo:






Si has seguido el blog desde los artículos iníciales, sabrás fácilmente realizar la interfaz de usuario mostrada en la figura anterior, lleva dos TextField y un okCommand.

Por otro lado, en el ejemplo #19 se hace uso de la clase llamada “Animacion” también vista ya en varios ejemplos del blog, el nombre de la clase es importante para poder mandarla llamar desde la interfaz de alto nivel

Vea el código siguiente:

int velx = Integer.parseInt(textField.getString());
int vely = Integer.parseInt(textField1.getString());

Con ese par de instrucciones se obtiene el valor que el usuario ingreso en los TextField, en las variables de tipo entero llamadas “velx” y “vely”, estas variables se envían como parámetros a la interaz de bajo nivel, tal y como se observa en la siguiente instrucción:

Animacion canvas = new Animacion(this, velx, vely);

Recuerde con esa instrucción se crea un objeto llamado “canvas” de la clase “Animación, vea las variables “velx”, y “velY” son enviadas a la clase “Animacion” como parámetros. Así de fácil se envían los datos de la interfaz de alto nivel a la clase que deriva de GameCanvas.

El código completo, cuando se presiona el comando que nos envía a la interfaz de bajo nivel entonces queda así:

int velx = Integer.parseInt(textField.getString());
int vely = Integer.parseInt(textField1.getString());
Animacion gameCanvas = new Animacion(this, velx, vely);
Display.getDisplay(this).setCurrent(gameCanvas);

Si no tienes idea de donde se ubica este código al final del post viene el video tutorial para que no quede duda alguna.

Cambios a la clase "Animacion"
Este es el código final del ejemplo #19 que hacia rebotar la pelotita por toda la pantalla:

import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class Animacion extends GameCanvas implements Runnable {
    Graphics g;
    Thread subproceso;
    Image fondo, pelota;
    public Animacion() {
        super(true);
        g = getGraphics();
        try {
            fondo = Image.createImage("/fondo.jpg");
            pelota = Image.createImage("/pelotita.gif");
        } catch (Exception e) { }
        subproceso = new Thread(this);
        subproceso.start();
    }

    public void run() {
        int coordX = 0;
        int coordY = 0;
        int velX = 5;
        int velY = 3;
        int alto = getHeight();
        int ancho = getWidth();   
        while(true) {
            g.drawImage(fondo, 0, 0, Graphics.TOP | Graphics.LEFT);
            g.drawImage(pelota, coordX, coordY, Graphics.TOP | Graphics.LEFT);
            try {
                subproceso.sleep(30);
            } catch (InterruptedException e) { }
            coordX = coordX + velX;
            coordY = coordY + velY;
            if ((coordX + pelota.getWidth()) > ancho || (coordX < 0))
                velX = -velX;
            if ((coordY + pelota.getHeight()) > alto || (coordY < 0))
                velY = -velY;
            flushGraphics();
        }
    }
}

Vea las variables "velX" y "velY", se declaran en el método run() y ahí son inicializadas con un valor fijo de 5 y 3 respectivamente, bueno pues en primer lugar hay que quitarlas de ahí, porque ahora los valores para estas variables vienen de la interfaz de alto nivel, se declaran a continuación de la definición de la clase, con eso basta para poder las usar en todo lo largo del programa.

Otro cambio es el constructor que ahora recibe tres parámetros, el primero es el MIDlet y los otros dos son las variables de la velocidad que se enviaron desde la interfaz de alto nivel, enseguida se muestra parte del código para el constructor:

// Declaración de las variables (después de la clase)

   int velX;
   int velY;
   public Animacion(HelloMIDlet mid, int vx, int vy) {
      // Aquí va el código para el constructor
      VelX = vx;
      VelY = vy;
}

Justo aquí se asignan los valores que vienen de la interfaz de alto nivel a las variables de la clase, con esto basta para poder comunicarnos, para poder enviar datos desde la interfaz de alto nivel, al hacer lo anterior la velocidad de la pelotita va respondiendo al valor que se ingreso en la interfaz.

Básicamente eso son los cambios, más significativos, lo que sigue es repetir lo que se hizo en la entrada anterior (ejemplo #21), que es lo de agregar los comandos para cambiarse de una interfaz a otra, esto ya se explico con detalle, en ese ejercicio, así que no tiene caso volverlo repetir.

Fiel a mi costumbre y para evitar malos entendidos, y para eliminar las dudas que pudieran surgir de lo visto arriba, a continuación se muestra el video tutorial para este ejemplo.


Aún así, por si hubiera dudas del video puesto que hubo una parte de copiar y pegar, voy a colocar en este enlace, un archivo comprimido que incluye toda la carpeta que genera NetBeans para este ejemplo, la versión que se uso fue la 6.8, ahí está el código fuente completo, incluso en la carpeta “dist” se encuentra el archivo JAR para enviarlo directo al celular y probar este ejemplo en el teléfono.



Clic AQUI para leer más...!

miércoles, 6 de octubre de 2010

Ejemplo #21 “Hola mundo” con interfaces de alto nivel y de bajo nivel en el mismo MIDlet



En modo gráfico (interfaces de bajo nivel), no existe forma alguna para poder capturar valores tal y como se hace con las interfaces de alto nivel, ahí simplemente se coloca un TextField y se capturan valores como ya se ha visto en varios ejemplos en este blog, en la clase GameCanvas no existe esa posibilidad hay que usar otros medios y uno de ellos es mezclando las interfaces de bajo nivel con las de alto nivel.

Por ejemplo, pensando en el único ejemplo de animación que hemos visto, el de la pelotita que rebota por toda la pantalla, sería interesante poder elegir la velocidad a la que rebota la pelotita, sería interesante que el usuario escribierá que velocidad desea y que la animación respondiera a ello, bueno pues este ejemplo es el primer paso para llegar ahí a la lectura de datos en modo gráfico, así que iniciemos.

Hola Mundo con interfaces de alto nivel

Existe una entrada del blog, de hecho es casi de las iniciales que muestra cómo crear el clásico ejemplo “hola mundo” con interfaces de alto nivel, lo puedes consultar aquí para que lo recuerdes:

Basándonos en ese ejemplo fácilmente se puede crear esta pantalla



Veamos ahora el "hola mundo" en modo gráfico.
“Hola Mundo” con interfaces de bajo nivel

Por otro lado el blog tiene un articulo llamado “Ejemplo #17 Hola Mundo usando GameCanvas” el cuál puedes ver dando clic aqui, el resultado del código se puede ver en la siguiente pantalla
La idea es agregar un botón o comando a cada una de las interfaces, que me permita cambiarme de una interfaz a otro, por lo pronto, este ejemplo solo mostrará los mensajes que se muestran en las imágenes de arriba. Vamos a iniciar agregando el botón en la interfaz de alto nivel porque es más fácil.

Agregando el Command a la interfaz de alto nivel

La idea recuerde es agregar un botón o comando para cambiarme a la interfaz de bajo nivel, existe otra entrada del blog, llamada Ejemplo #6 como usar objetos de tipo Command, puedes consultarlo dando clic aquí, ahí se observa con detalle cómo se puede agregar un comando, como el de la figura siguiente:

El comando se llama “Modo Gráfico” y me permitirá cambiarme de interfaz, es muy fácil crear un comando usando interfaces de alto nivel, siguiendo las instrucciones del ejemplo #6, básicamente solo es de arrastrar y soltar el comando.

Cuando se presione el comando se debe crear el objeto de la clase GameCanvas, para que aparezca en la pantalla, afortunadamente existe otro artículo en el blog, bueno, hay varios que muestran como agregar código cuando se presiona el botón, el artículo se llama Ejemplo #7 “programa que calcula el área de un rectángulo”, en la parte final viene como agregar el código cuando se presione el comando, lo puedes consultar dando clic aquí.

Justo donde se indica en el ejemplo #7 se debe agregar el código (si no deseas ver el ejemplo, no te preocupes, al final viene el video-tutorial). El primer paso es crear una instancia de la clase que deriva de GameCanvas, para ello se debe conocer el nombre de la clase, la clase definida en el Ejemplo #17 se llama EjemploGameCanvas, para mostrar en pantalla lo que está en la clase GameCanvas se agrega el siguiente código:

EjemploGameCanvas gCanvas = new EjemploGameCanvas();
Display.getDisplay(this).setCurrent(gCanvas);

Primero se crea el objeto de la clase EjemploGameCanvas y posteriomente se muestra en pantalla este objeto, logrando que se ve el mensaje de “Hola mundo…”.
Por otro lado, si se desea interactuar en los dos modos de pantalla, se debe enviar una referencia del modo de texto al modo grafico, para poder trabajar en los dos lados, si no lo hago así no podré regresar del modo gráfico al modo de texto, basta pues agregar como parámetro la palabra “this”, que en este caso “this” hace referencia al MIDlet principal, entonces el código final queda así:

EjemploGameCanvas gCanvas = new EjemploGameCanvas(this);
Display.getDisplay(this).setCurrent(gCanvas);

Más adelante se verá el uso que se le dará a ese parámetro que fue enviado al Canvas.

Como lo mencionaba, si se tienen dudas de donde ubicar el código, al final de este post, como siempre, el video tutorial dará todas las respuestas. Pasemos entonces a la interfaz de bajo nivel que es algo más complicado que lo visto ahora.

Agregando el Command a la interfaz de bajo nivel

La idea recuerde, es agregar a la clase GameCanvas también, un botón o comando para que al presionarlo pueda cerrar está pantalla en modo gráfico y abrir la pantalla mostrando la interfaz de alto nivel.

Desgraciadamente en el modo gráfico, tengo que hacerlo todo manualmente, no es como en las interfaces de alto nivel, como se vio arriba, donde solo se arrastran y sueltan los botones en el área de trabajo y NetBeans genera todo el código, no aquí no es así, hay que teclearlo todo, eso es bueno porque así se aprende nuevo código nuevas funciones que no se aprendieron con las interfaces de alto nivel y que NetBeans genero automáticamente.

Vemos primeramente el código final del ejemplo #17, el código Java que me permite mostrar el “hola mundo…” en bajo nivel, ya se analizó a detalle y quedo así:

public class EjemploGameCanvas extends GameCanvas implements Runnable {
    Graphics g;
    public EjemploGameCanvas () {
        super(true); // código del constructor
        g = getGraphics();
       Thread subproceso = new Thread(this);
       subproceso.start();
    }
    public void run() {
         // pantalla en negro
        g.setColor(0x000000);
        g.fillRect(0, 0, getWidth(), getHeight());
       // dibujo de las letras “hola mundo…
       g.setColor(0xff00FF);
       g.drawString("Hola mundo, con GameCanvas", 0, 60, Graphics.LEFT || Graphics.TOP);
       flushGraphics();
   }
}

Agregando el parámetro al constructor

Vea el constructor, obviamente no tiene parámetros, nosotros desde la interfaz de alto nivel le enviamos uno, que era, dicho sea de paso el MIDlet (por medio de la palabra “this”), hay que recibir el parámetro con una variable para que haya una correspondencia, recuerde el post de los métodos con parámetros.

El MIDlet, fue creado automáticamente por Netbeans, viendo el código se observa que el MIDlet se llama HelloMidlet entonces el parámetro se tiene que recibir como una variable o más bien dicho como una instancia de tipo HelloMidlet así:

public EjemploGameCanvas ( HelloMIDlet    hm) {

// código del constructor

}

Se recibe como parámetro la instancia o el objeto de la clase HelloMIDlet, es llamada "hm", debe haber una variable declarada después de la clase, de ese mismo tipo para poder almacenar el párametro que llega desde el MIDlet  y también para posteriormente usarla a lo largo de toda la clase que deriva de GameCanvas, el código es así:

HelloMIDlet     hellomidlet;

Esta variable se inicializa dentro del constructor con el parámetro que llego de la interfaz de alto nivel, así:

hellomidlet = hm;

Con esto, por decirlo así se tiene el MIDlet dentro de GameCanvas y se puede usar en cualquier lado de la clase, por medio del objeto llamado “hellomidlet” el código completo de la clase va quedando así:

public class EjemploGameCanvas extends GameCanvas implements Runnable {
   Graphics g;
   HelloMidlet   hellomidlet;
   public EjemploGameCanvas (HelloMIDlet    hm) {
      super(true); // código del constructor
      hellomidlet = hm;
      g = getGraphics();
     Thread subproceso = new Thread(this);
     subproceso.start();
   }

  public void run() {
   // pantalla en negro
     g.setColor(0x000000);
     g.fillRect(0, 0, getWidth(), getHeight());
  // dibujo de las letras “hola mundo…
     g.setColor(0xff00FF);
     g.drawString("Hola mundo, con GameCanvas", 0, 60, Graphics.LEFT || Graphics.TOP);
     flushGraphics();
  }
}

Como agregar el Command al GameCanvas

Aún no se ha agregado ningún botón o comando, veamos que se necesita para agregar los botones con código

Agregar la interfaz CommandListener



Para agregar un botón o comando, primeramente se tiene que agregar la interfaz CommandListener, al igual que la interfaz Runnable, se agrega a la definición de la clase así:

public class EjemploGameCanvas extends GameCanvas implements Runnable, CommandListener {

Esta interfaz me permite “escuchar” los eventos generados por los comandos o botones que se agreguen.

Se debe agregar la siguiente instrucción, arriba, en la sección de los "imports":

import javax.microedition.lcdui.*;
Necesaria para poder usar el CommandListener

Por otro lado, no basta con agregar la interfaz CommandListener para “escuchar” los comandos, debemos indicar, que los comandos se van a “escuchar” en el GameCanvas, esto se logra con la siguiente instrucción, es como un enlace entre el CommandListener y el GameCanvas actual

setCommandListener(this);

Recuerde agregar el “this”, palabra reservada de java que habla del contexto actual, en otras palabras el “this” es en este caso, como si se hiciera referencia a la clase que deriva de GameCanvas. Este es el enlace para que se “escuchen” los comandos dentro de la clase EjemploGameCanvas, esa instrucción va en el constructor de la clase, como se verá más adelante.

La interfaz CommandListener, tiene un único método que se llama CommandAction, algo parecido con la interfaz Runnable que tiene a su único método llamado Run().

El método CommandAction, me permite saber que comando se ha presionado, el método  lleva dos parámetros como se observa:

public void commandAction(Command command, Displayable displayable) {

     //Código para decodificar las acciones del Command

}

Uno de los parámetros es llamado “command” contiene el comando que se ha presionado, recuerde puede haber varios “Commands”, con este parámetro sabremos cual es el presionado, el otro parámetro indica en que pantalla se ha presionado el comando, que en este ejemplo no es relevante.

Aquí se hace un paréntesis para saber cómo se agrega el botón físicamente al GameCanvas, para agregar un botón o comando se usa la clase Command, haciendo uso de esta clase fácilmente se puede crear un objeto Command, el constructor para hacerlo es así:

Command (Etiqueta, tipo_de_comando, prioridad)

El primer parámetro lleva una etiqueta o palabra que parecerá en el celular como nombre del comando, la etiqueta es importante porque es la que el usuario del programa ve cuando ejecuta la aplicación, el siguiente parámetro especifica el tipo de comando, esto se vio ya en un post anterior como se mencionó arriba, el último parámetro indica la prioridad en que se desplegará el comando en el teléfono, por que puede haber más de un objeto Command, este último parámetro es un número entero.

Un ejemplo para la creación de un objeto Command sería así:

Command cmd = New Command(“Salir”, Command.Exit, 1);

El objeto se llama cmd, el usuario verá “salir” en el teléfono, al presionarlo se cierra la aplicación por que el Command es de tipo “Exit”.

Aún así la sentencia anterior no muestra ningún comando en la pantalla, este tiene que agregarse al Canvas, esto se logra fácilmente con el método

addCommand( Command cmd)

El método en verdad agrega el comando al GameCanvas, lleva como parámetro precisamente un objeto del tipo Command, esto es bueno pues así nos evita declarar la variabla “cmd” vista hace rato, entonces es posible agregar el comando al GameCanvas así:

addCommand ( new Command("Regresar", Command.OK, 1));

El addCommand, se agregan por lo general en el constructor que es el primer código que se ejecuta de la clase, así que la clase completa va viéndose así:

public class EjemploGameCanvas extends GameCanvas implements Runnable, CommandListener{
   Graphics g;
    public EjemploGameCanvas () {
        super(true); // código del constructor
        setCommandListener(this);
        addCommand ( new Command("Regresar", Command.OK, 1));
        g = getGraphics();
        Thread subproceso = new Thread(this);
        subproceso.start();
    }
    public void run() {
       // pantalla en negro
       g.setColor(0x000000);
       g.fillRect(0, 0, getWidth(), getHeight());
       // dibujo de las letras “hola mundo…
       g.setColor(0xff00FF);
       g.drawString("Hola mundo, con GameCanvas", 0, 60, Graphics.LEFT || Graphics.TOP);
       flushGraphics();
    }
//Clase que detecta los comandos
    public void commandAction(Command command, Displayable displayable) {

          //código que detecta el comando
    }
}

Como agregar el código al método commandAction

Finalmente se debe agregar el código al método commandAction, cada que es presionado el botón, se ejecuta este código, el código primero se “fija” cuál es el comando presionado, esto pensando en que puede haber varios botones, el método que me indica cual botón se presiono es llamado getCommandType, y es un método de la clase Command, así se puede detectar el botón presionado

if(command.getCommandType() == Command.OK) {

    // se ejecuta elcódigo cuando se presiona el okCommand
}

Justo al presionar este botón, se tiene que mostrar la pantalla con la interfaz de alto nivel, para hacerlo se usa la clase Display, usando además la variable que hacer referencia al MIDlet “hellomidlet” esto se logra así:

Display.getDisplay(hellomidlet).setCurrent(hellomidlet.getForm());
Esté método se agrega dentro del if anterior y listo se termina el ejercicio, el código completo se muestra enseguida. Al final se observa donde se ubica la instrucción anterior:


import javax.microedition.lcdui.*;

public class EjemploGameCanvas extends GameCanvas implements Runnable, CommandListener{
    HelloMIDlet hellomidlet;
    Graphics g; // objeto gráfico
    public EjemploGameCanvas (HelloMIDlet hm) {
        super(true); // código del constructor
        hellomidlet = hm;
        setCommandListener(this);
        addCommand(new Command("Regresar", Command.OK, 1));
        g = getGraphics();
       Thread subproceso = new Thread(this);
        subproceso.start();
    }
    public void run() {
       // pantalla en negro
       g.setColor(0x000000);
       g.fillRect(0, 0, getWidth(), getHeight());
       // dibujo de las letras “hola mundo…
       g.setColor(0xff00FF);
       g.drawString("Hola mundo, con GameCanvas", 0, 60, Graphics.LEFT || Graphics.TOP);
       flushGraphics();
    }
    public void commandAction( Command cmd, Displayable displayable) {
       if (cmd.getCommandType()== Command.OK)
              Display.getDisplay(hellomidlet).setCurrent(hellomidlet.getForm());
    }
}

Bueno con estos e termina el post, pero fiel a mi costumbre, para evitar dudas de donde se ubica el código y todo eso, aqui les dejo el video-tutorial, guiandose con el, no debe haber dudas de ningún tipo.




Clic AQUI para leer más...!

sábado, 25 de septiembre de 2010

Métodos creados por el usuario -- Parte II



En la entrada anterior del blog quedaron pendientes este par de temas relacionados con métodos creados por el usuario:

• Los métodos que regresan valores
• Los métodos con parámetros

Métodos que regresan valores

Voy a repetir la sintaxis para crear un método definido por el usuario:

Identificador_de_acceso valor_de_regreso Nombre_del_metodo( parametros ) {

     //Código del método

}

Un método que regresa un valor también requiere un identificador de acceso que ya se vio en el post pasado, para nuestro ejemplo se usará private, por otro lado el valor de regreso, es el tipo de datos (puede ser int, float double etc.) que va a regresar el método, por ejemplo, el método que voy a diseñar regresa el ancho de una imagen, el ancho es un número enero que se da en pixeles, el método entonces va a regresar un número entero, aparte se va a llamar obtAncho y no tiene parámetros, entonces el método va quedando así:

private int obtAncho( ) {

   //Código del método

}

El ejemplo simplemente regresa el ancho, en los códigos vistos en los últimos post, se observa como obtener el ancho de una imagen, de la pelotita específicamente y era así:

pelota.getWidth();

Pues ese código es el que se va a gregar al método. Los métodos que regresan valores deben llevar a fuerzas la palabra
return

Esa instrucción termina el método y regresa el valor que este después del return, el método completo que regresa el ancho de la imagen queda finalmente así:

private int obtAncho( ) {
   return pelota.getWidth();
}

Eso es todo, el método se puede invocar o mandar llamar así:

imgAncho = obtAncho( );

Contrario a lo que se vio en el post pasado, los métodos que no regresan valores simplemente se invocan con el nombre del método, los que si regresan deben ser invocados por medio de una variable, como se ve en la instrucción anterior, hasta aquí vamos a dejar eso de los métodos que regresan valores, pero más adelante vamos a realizar algún ejemplo para reforzar este tema que fue un poco superficial.

Métodos con parámetros

Vea el siguiente método:

Public void estVelocidad( int x) {
    VelX = x;
}

El método es publico, y no regresa ningún valor, se llama estVelocidad y lleva un parámetro, contrario a todos los métodos vistos anteriormente, entre paréntesis, lleva la declaración de una variable, en este ejemplo la variable se llama x y es de tipo entero, esta variable es el parámetro y sirve para comunicarse con el método.

La regla es bien simple, se agregan los parámetros como una declaración de una variable, en el ejemplo la variable se llama “x” y es de tipo entero.

Para invocar el método, se hace de una forma por demás sencilla, el método no regresa valores es de tipo void como se observa, entonces solo se coloca el nombre del método y entre paréntesis el valor del parámetro así:
estVelocidad(5);

Con la sentencia anterior el valor de “5” es enviado al parámetro, ese valor llega a la variable “x” del método y entonces la sentencia que está dentro del método, esta:

velX = x;

hace que la variable “velX” tome el valor de 5.

Fácilmente puedo mandar llamar el método y cambiar de velocidad, pensando en el ejemplo de la pelotita, con simplemente llamar el método se establece la velocidad en X, otro ejemplo para invocar el método sería así:

estVelocidad(3);



Se manda llamar el método pero vea ahora, lleva entre paréntesis el valor de "3", este valor se refleja en el parámetro y ahora la variable "velX" toma el valor de "3".

El ejemplo es muy simple pero a lo largo del blog se van a ver las ventajas de usar métodos.

Es posible agregar más parámetros, los necesarios, incluso pueden ser hasa de diferentes tipos solo basta con separarlos con comas, por ejemplo, vea el siguiente método usado para calcular el area de un triangulo, recibe como parámetros dos variables la base y la altura:

private int areaTriangulo(int base, int altura) {

     return ((a*b)/2)

}

El método, tiene parámetros y parte regresa valores de tipo entero que es precisamente el resultado del area del triangulo, para invocar el método basta llamarlo así:

Area = areaTriangulo(5, 6);

Al ejecutar esa línea la variable Area tendrá el valor calculado en el método, el número “5” se transfiere a la variable “base” y el número “6” a la variable “altura”, el método con esos valores hace el calculo ahí indicado y lo regresa a la variable donde se mando llamar el método. Este ejmplo se ve claramente que los parámetros permiten enviar información al método, en ele ejemplo se envía el "5" y el "6" y por cierto el método es capaz de ahora enviar la información a la clase donde se manda llamar.

Bueno espero me haya explicado bien, con esto terminamos la sintaxis de los métodos, espero mostrar algunos ejemplos para reforzar este tema.



Clic AQUI para leer más...!

miércoles, 15 de septiembre de 2010

Métodos creados por el usuario -- Parte I



Hoy se va a seguir trabajando con el mismo código que se vio en el último ejemplo, el de la pelotita que era movida por el teclado del celular, para mostrar otro concepto de la sintaxis de Java, la creación de métodos definidos por el usuario.

Ya se ha trabajado con muchísimos métodos a lo largo del blog, por ejemplo:


  Clase                    Método       
TextField             getString()               
                            setText()                   
Graphics             drawArc()
                            drawString()
                           drawImage()
GameCanvas      flushGraphics()

Todos absolutamente todos los métodos fueron creados por Sun Microsystem cuando desarrollo java y están agrupados en paquetes de clases a los que se tiene acceso por medio de la instrucción import. Hoy se va hablar de métodos pero de otro tipo, no los creados por Sun, si no, los métodos definidos por el usuario.


Métodos Definidos por el usuario

Un método es como una subrutina o un pequeño segmento de código que en términos generales sirve para dividir o descomponer un problema grande en partes más pequeñas que se invocan o se llaman desde la mima clase o desde otras clase

El siguiente segmento de código muestra el método llamado constructor, que se hizo en el post del ejemplo #20 y en el #19 :

El constructor entre otras cosas, carga las imágenes que se van a usar en el programa y crea un subproceso para el control de la animación, se puede dividir esta tarea, en partes bien definidas que son cargar las imágenes y crear el subproceso, se puede entonces crear un par de métodos que haga eso, pero veamos esto con calma.
public Animacion() {
  super(true);
  g = getGraphics();
  try {
     fondo = Image.createImage("/fondo.jpg");
     pelota = Image.createImage("/pelotita.gif");
  } catch (Exception e) { }
  subproceso = new Thread(this);
  subproceso.start();
}


La sintaxis para crear un método definido por el usuario es en términos generales así:

Identificador_de_acceso    valor_de_regreso    Nombre_del_metodo( parametros ) {

         //Código del método

}

Enseguida se explican las cuatro partes que consta el método

1. Identificador de acceso

El identificador de acceso es algo así como la protección que tiene el método y es que el método creado por el usuario puede invocarse desde la misma clase o desde otras clases, el identificador de acceso nos da ciertos niveles de seguridad, existen varios tipos de identificadores de acceso:

• private
• protected
• public
• package

El lector debe elegir un tipo para usarlo en la definición del método, el método creado debe iniciar con una de esas palabras reservadas de Java, ¿pero cúal usar? Enseguida se da una definición superficial de cada uno de estos niveles de acceso.
a) Private

Este es el nivel de acceso más restringido, un método privado solo se puede invocar o solo se tiene acceso desde la misma clase donde está definido, los métodos privados son digámoslo así secretos para todos menos para la clase donde están ubicados, justo este tipo de acceso es el que se va usar en los métodos que vamos a crear, ¿Por qué? Sencillo porque el programa solo consta de una clase (bueno en realidad son dos clases el MIDlet y la clase que hereda de GameCanvas que es donde está todo el código, por eso digo que solo consta de una clase), así que no necesitamos invocar este método desde otros lados, programas que constan de varias clases si requieren de otro identificador de acceso.

Vamos a tomar la definición de la clase vista anteriormente para ir formando nuestro método, entonces, se debe agregar la palabara private al inicio del método así:

private valor_de_regreso Nombre_del_metodo( parametros ) {

    //Código del método

}

b) Protected

Este nivel de acceso permite invocar el método desde la misma clase o desde las subclases, recuerde una subclase es la que deriva de otra y hereda sus métodos y propiedades, por ejemplo la clase del ejemplo #20 se llama Animación y deriva de la clase GameCanvas, Game Canvas es la clase y Animación es la subclase, esto es el concepto de herencia, que por lo pronto no ahondaremos en este concepto.

c) Public

Este identificador de acceso es el más sencillo y se ha visto ya en varios métodos que se han realizado, por ejemplo la definición del método run del ejemplo #19 es así:

public void run( ) {

    //código del método run
}

Note el identificador de acceso public, como siempre va al inicio del método, este tipo de acceso significa que todas las clases de todos los paquetes de clases tienen acceso al método, un paquete de clases, es un grupo de clases que se relacionan, por ejemplo, Java tiene el paquete de clases llamado Game, en donde está ubicada la clase GameCanvas y otras clases más que se relacionan porque sirven para la programación de juegos para el celular, recuerde los paquetes de clases se agregan al programa en Java usando la palabra import.

d) Package

Este nivel de acceso permite invocar métodos desde cualquier clase que este en el mismo paquete.

2. Valor de Regreso

Este es el segundo punto en la definición del método. Java por fuerza requiere que los métodos regresen un valor a la clase donde se invocan, valor se refiere a algún tipo de dato que se calculo o en el método, el tipo de datos son los ya conocidos, por ejemplo int, boolean, float, double, en el caso que el método creado no regrese ningún valor se coloca la palabra reservada void.

Regresando a nuestro ejemplo, deseamos crear un método para cargar las imágenes y otro para crear un subproceso, las imágenes se cargan con una simple instrucción e igual el subproceso, en otras palabras estos métodos no requieren que se regrese ningún valor, entonces se usa el void como valor de retorno, el método que vamos creando toma la siguiente forma:

private void Nombre_del_metodo( parametros ) {

//Código del método

}

En el siguiente post se hablará de los métodos que regresan valores.

3. Nombre del método

El nombre del método es la tercera parte de la definición del método, este nombre es elegido por el usuario, puede ser cualquiera pero recuerde las reglas básicas: no se vale escribir espacios, no se vale iniciar con un número o carácter alfanumérico, solo se vale el guión bajo.

En nuestro ejemplo el método va a cargar las imágenes, así que como nombre usamos: cargarImagenes entonces el método va quedando así:

private void cargarImagenes( parametros ) {

//Código del método

}

4.- Parámetros

La última parte de la definición del método son los parámetros, estos van después del nombre del método, y deben ir entre paréntesis, los parámetros que en algunos casos no son necesario, sirven como una especie de comunicación entre la clase que los invoca y el método creado por el usuario, en otras palabras, los parámetros son el medio para enviar información desde la clase que los invoca al método creado.

En el método que estamos diseñando no se requiere enviar ninguna información de nada, esto significa que no lleva parámetros por ende, los paréntesis van vacios así:

private void cargarImagenes( ) {

//Código del método

}

Listo la definición del método está terminada, ahora solo va el código necesario para cargar la imagen este código se vio arriba en el constructor de la clase Animación, el método completo y terminado queda así:

private void cargarImagenes( ){
   try {
   fondo = Image.createImage("/fondo.jpg");
   pelota = Image.createImage("/pelotita.gif");
   } catch (Exception e) { }
}

El lugar para colocar este código es en cualquier parte dentro de la clase, no importa donde esté Java lo busca.

También en otro post se mostrarán algunos métodos que si llevan parámetros.

Invocación del método

Para que este método se ejecute se debe mandar llamar o invocar desde alguna parte la clase, en este caso obviamente es desde el constructor, para hacerlo basta con colocar el nombre del método seguido de sus parámetros entre paréntesis, así:

cargarImagenes();

Entonces el constructor ya con la llamada al método queda así:

public Animacion() {
   super(true);
   g = getGraphics();
   cargarImagenes( );
   subproceso = new Thread(this);
   subproceso.start();

}

Eso es todo, cuando el NetBeans encuentre la invocación al método, el flujo de programa cambia, busca el método y ejecuta las instrucciones que ahí se indican, al terminar el método el flujo de programa se regresa a donde se quedo, esto queda más claro con una animación, una animación vale más que mil palabras.

La siguiente animación muestra el método creado junto con el constructor, así como se muestra es como Java ejecuta el método, todo inicia en el constructor, las instrucciones que están en el constructor es lo que se ejecuta primero, note como cambia el flujo de programa cuando se encuentra la instrucción para mandar llamar el método y observe también como al terminar el método el flujo de programa regresa a donde se había quedado.







Método para crear el subproceso

Enseguida se muestra la creación de otro método, el método que se diseñará simplemente crea el subproceso, ya sabemos que todo se inicia con el identificador de acceso, igual que el anterior lo colocamos como “prívate”, luego sigue el tipo de retorno, tampoco en este caso se regresa nada así que se coloca la palabra “void”, luego va el nombre del método, lo llamaremos “crearSubproceso”, luego va entre paréntesis la lista de parámetros, este método no los requiere así que los paréntesis van vacios, con lo anterior fácilmente se crea el método así:

private void crearSubproceso(){
   subproceso = new Thread(this);
   subproceso.start();
}

Para invocar el método, como ya se vio, basta con colocar su nombre así:

crearSubproceso()

Código Completo

El siguiente código muestra el constructor, note donde se ubica la instrucción para mandar llamar los métodos, junto con los dos métodos creados en esta sección, recuerde la ubicación de los métodos no lleva un orden pueden estar primero o después del constructor, Java los busca y los ejecuta, este es el código con los métodos creados por el usuario:

public Animacion() {
   super(true);
   g = getGraphics();
   cargarImagenes();
   crearSubproceso();
}

private void cargarImagenes(){
  try {
    fondo = Image.createImage("/fondo.jpg");
    pelota = Image.createImage("/pelotita.gif");
  } catch (Exception e) { }
}

private void crearSubproceso(){
  subproceso = new Thread(this);
  subproceso.start();
}

Observación final

Enseguida vuelvo a repetir el código para el constructor para el ejemplo #20 tal y como se mostro inicialmente:

public Animacion() {
   super(true);
   g = getGraphics();
   try {
      fondo = Image.createImage("/fondo.jpg");
      pelota = Image.createImage("/pelotita.gif");
   } catch (Exception e) { }
   subproceso = new Thread(this);
   subproceso.start();
}

Compare este constructor con todo el código anterior el de los métodos creados, los dos hacen exactamente lo mismo, crear las imágenes y el subproceso, pareciera que no se ve ventaja alguna, y quizá así es para este caso, pero créanme es altamente recomendable pensar en términos de métodos, en términos de dividir el problema en partes, por decirlo de alguna manera, las partes son los métodos, se anima al lector para que así lo haga y en adelante así se harán los video-tutoriales siguientes, son muchas las ventajas de usarlos, como se verá en un futuro.

Próxima entrada del blog

Este tema fue muy largo y aún así nos quedaron dos temas pendientes:

• Los métodos que regresan valores
• Los métodos con parámetros

Esto se abordara en la próxima entrada, que ojala sea esta misma semana.



Clic AQUI para leer más...!