Juegos |
|||||||
Archivos necesarios: |
|||||||
En este trial haremos un pequeño juego de laberinto. Para poder crear juegos necesitamos combinar varias de las habilidades que ya conocemos. Vamos a tener que utilizar un Thread para que revise el estado del juego constantemente, vamos a utilizar un KeyListener para que el usuario pueda jugar, vamos a extender JComponent e incluso vamos a utilizar un poco de manejo de clases (incluyendo herencia) para darle variedad al juego. En el archivo de este Trial se incluyen varias clases. GameComponent es una clase que extiende JComponent y va a ser la que se encargue de mantener la animación, TrapList es una lista de trampas que se dibujan en el mapa, Crono y Link son dos clases que extienden la clase Hero. La clase GameComponent va a utilizar una instancia de la clase Hero y una instancia de la clase TrapList para agregar trampas al laberinto y pintar a nuestro heroe. |
|||||||
¿Por dónde empezar? |
|||||||
Primero vamos a analizar la clase GameComponent. Esta clase se encarga de hacer dos cosas principales: Iniciar el juego y mantener la animación. Para iniciar el juego únicamente necesitamos crear un objeto de tipo heroe y algunas trampas, después de eso iniciamos el Thread de animación que se va a encargar de dibujar la pantalla y de revisar si el juego ha terminado. |
|||||||
![]() |
Un Thread se encarga de realizar lo que se encuentra en el método run() de alguna clase que implemente la interfaz Runnable. En este caso queremos que realice dos cosas: Crear un buffer de la siguiente pantalla y pintar este buffer en la pantalla. Antes de ver el método en el que creamos el buffer vamos a analizar un poco más a detalle qué es y por qué lo necesitamos. Un buffer es un lugar en memoria en donde guardamos información que vamos a utilizar después, en escencia es lo mismo que una variable. En este programa hacemos un buffer para pintar en memoria y una vez que ya tengamos toda la imagen hecha en memoria mandarla al monitor en una sola pintada. Imaginemos que dibujamos un cuadrado blanco, sobre ese cuadrado blanco dibujamos unas montañas y unas nubes, sobre las montañas dibujamos un lago, sobre el lago ponemos algunos peces, al frente de la escena ponemos a nuestro heroe y ponemos algunas trampas en el suelo. Del cuadrado blanco original solamente se va a dibujar un pequeño pedazo, pero si no utilizamos un buffer primero se va a pintar ese cuadrado blanco completo y después se va a continuar con todo lo demás, lo que puede hacer que la animación se vea muy cortada. Cuando utilizamos un buffer primero creamos la imagen a memoria y luego la dibujamos una sola vez. |
||||||
Ya que vimos por qué es importante crear un buffer en un juego vamos a ver cómo crearlo. Lo primero que tenemos que hacer es crear un objeto Image que nos sirva como buffer (podemos hacerlo utilizando el método createImage() que recibe el ancho y el alto de la imagen), obtener el objeto Graphics que nos permite dibujar en ese Image mediante el método getGraphics(); Una vez que ya lo tengamos podemos utilizar el objeto Graphics para dibujar de la misma manera en que lo hacemos normalmente. Si quisieramos utilizar la funcionalidad avanzada que nos brinda Graphics2D podemos utilizar un cast para convertir el objeto Graphics que obtenemos con getGraphics(). |
![]() |
||||||
![]() |
Otra cosa importante en nuestro juego es poder reaccionar a eventos. Como nuestra clase GameComponent extiene a JComponent podemos agregar un KeyListener o un MouseListener mediante los métodos addKeyListener() y addMouseListener(). | ||||||
¿Y luego qué? |
|||||||
| Una vez que creamos nuestro GameComponent únicamente necesitamos crear las clases que van a agregarse al GameComponent para hacerlo funcionar, la clase principal debe mostrar un JFrame que tenga agregado el GameComponent, varias clases deben extender la clase Hero que tiene los métodos para crear, mover y dibujar al heroe y la clase TrapList que crea, mantiene y dibuja las trampas. | |||||||
Una de las cosas de las que se encarga la clase hero es de manejar las llamadas de teclado, esto lo hace mediante el método keyPressed(), en el que revisa qué tecla se presionó mediante el método getKeyCode() del KeyEvent que generó el evento y dependiendo de lo que sea mueve al personaje, cambia la dirección en que está viendo y cambia el frame de animación. El método draw de la clase Hero también es muy sencillo únicamente utiliza el método drawImage() para pintar el frame correspondiente dependiendo de la dirección en la que se encuentre viendo el personaje. Aún así resulta interesante ver la manera en que se utiliza un arreglo para guardar un grupo de BufferedImage que nos permite tenerlas en memoria y poderlas pintar más rápido. |
![]() |
||||||
![]() |
La clase TrapList utiliza un vector para guardar objetos de la clase Trap, en esta última clase tenemos un método muy interesante en el que utilizamos la ayuda de Java para saber si el heroe está atrapado o no. Primero creamos dos rectángulos del tamaño del heroe y de la trampa, después intersectamos los dos rectángulos mediante el método intersection y en caso de que el rectángulo sea mayor que 5x5 (para no ser muy estrictos en cuanto a cuándo se muere el heroe) regresa que si está atrapado. Para poder hacer más interesantes los juegos podemos utilizar algunos clips de audio como se ve en el Trial de sonido. |
||||||