Muchos deben conocer el juego «El laberinto del exorcista» o «The Maze» para los amantes de la lengua de Shakespeare, The Maze es un juego ya antiguo pero que se hizo pupular no por sus atractivos graficos ni por la complejidad del juego :), sino porque traia una sorpresa al final del tercer nivel, a la niña de la pelicula del exorcista, una imagen grotesca que daba miedo (a algunos) de los cuales pueden encontrarse muchos videos en yotube.
Pues bien, ese es el juego que crearemos a continuación en el lenguaje Java y con ayuda del IDE de Netbeans 6.9, manos a la obra.
1. Crea un proyecto nuevo en netbeans «laberinto«, en la clase principal crea un nuevo JFrame, llamalo interfaz.java, crea dos clases mas, Sound.java y panel.java, ademas agrega un nuevo paquete «mapas» donde colocaremos las imagenes que utilizaremos en el proyecto, no utilizaremos ninguna otra libreria adicional.
2. Utilizaremos para este juego, 5 imagenes en formato *.BMP para tratar de preservar la homogeneidad de los colores, las dimensiones son de 800 x 600 px. estas imagenes foman los diferentes nivel, la caratula del juego y la imagen de terror para el ultimo nivel. Estas imagenes son:
En lugar de la imagen de la niña del exorcista que a mi no me da miedo sino risa :), decidi colocar otra imagen, la de la actriz japonesa Takako Fuji, de la pelicula «El grito», esta imagen tampoco me da miedo, como te va a dar miedo semejante angelito ;), pero si v0y a colocar una imagen con la cual tendre una pesadilla, que sea una bonita pesadilla 😉
Continuemos mejor con el juego :), las ultimas imagenes, «box.bmp» imagen de 5×5 pixeles de color azul, sera nuestro cursor para el juego y la ultima imagen «ico.png» es una imagen PNG transparente igual de 5×5 px, esto para ocultar el puntero del mouse.
3. Ahora vamos a la programación, la clase principal donde se desarrollara todo el juego es la clase panel.java, una clase que se extiende de un JPanel, el codigo es:
package laberinto; import java.awt.Color; import java.awt.Cursor; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.LinkedList; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JPanel; /** * @web https://www.jc-mouse.net/ * @author Mouse */ public class panel extends JPanel implements MouseMotionListener,MouseListener{ /* IMAGENES A UTILIZAR */ private BufferedImage O; private BufferedImage MAPA_0; private BufferedImage MAPA_1; private BufferedImage MAPA_2; private BufferedImage MAPA_3; private BufferedImage FINAL; /* ALMACENA LA POSICION DEL CURSOR EN PANTALLA */ private int Pos_X; private int Pos_Y; /* CONTROLA EL AVANCE DE NIVELES */ private int NIVEL=0; /* almacena el color RGB del pixel donde esta posicionado en cursor */ private int color_RGB=0; private LinkedList<Point2D> puntos = new LinkedList<Point2D>(); public panel(){ this.setSize(800, 600); try {// SE CARGAN LAS IMAGENES EN MEMORIA MAPA_0 = ImageIO.read(getClass().getResource("/mapas/0.bmp")); MAPA_1 = ImageIO.read(getClass().getResource("/mapas/1.bmp")); MAPA_2 = ImageIO.read(getClass().getResource("/mapas/2.bmp")); MAPA_3 = ImageIO.read(getClass().getResource("/mapas/3.bmp")); FINAL = ImageIO.read(getClass().getResource("/mapas/4.bmp")); O = ImageIO.read(getClass().getResource("/mapas/box.bmp")); } catch (IOException ex) { } addMouseMotionListener(this); addMouseListener(this); //se oculta el mouse Image mano = new ImageIcon(getClass().getResource("/mapas/ico.png")).getImage(); Cursor miCursor= this.getToolkit().createCustomCursor(mano, new Point(0,0), "none"); this.setCursor(miCursor); } /* hace uso de la clase "Sound" y reproduce un archivo de audio WAV */ public void Play(){ new Sound( System.getProperty("user.dir") + "/wav/grito.wav" ).start(); } @Override public void paint(Graphics g) { Graphics2D g2 = (Graphics2D)g; switch(this.NIVEL) {//DE ACUERDO AL NIVEL EN EL QUE SE ENCUENTRE //DIBUJA LOS RESPECTIVOS MAPAS case 0: g2.drawImage(MAPA_0,0,0,this); break; case 1: g2.drawImage(MAPA_1,0,0,this); break; case 2: g2.drawImage(MAPA_2,0,0,this); break; case 3: g2.drawImage(MAPA_3,0,0,this); break; case 4: g2.drawImage(FINAL,0,0,this); break; } /* DIBUJA UN CUADRADO AZUL */ g2.drawImage(O,Pos_X,Pos_Y,this); /* DIBUJA EL TRAZO DE COLOR ROJO */ if( this.NIVEL > 0 && this.NIVEL < 4 ){ g.setColor(new Color(200,0,0)); Point2D p0 = puntos.get(0); for (int i = 0; i < puntos.size(); i++) { Point2D p1 = puntos.get(i); g.drawLine((int) p0.getX(), (int) p0.getY(), (int) p1.getX(), (int) p1.getY()); p0 = p1; } } } public void mouseDragged(MouseEvent e) { } /* AQUI SE MANEJAN TODOS LOS EVENTOS PARA EL JUEGO */ public void mouseMoved(MouseEvent e) { if(this.NIVEL != 4) { //obtiene la posicion del cursor en pantalla Pos_X = (int)e.getPoint().getX(); Pos_Y = (int)e.getPoint().getY(); puntos.add(e.getPoint()); //dependiendo del nivel donde se encuentre,dada las coordendas X,Y //del cursor, obtiene el color RGB que corresponde a la imagen del // nivel donde esta el jugador switch(this.NIVEL) { case 0: break;//no hace nada case 1: color_RGB = MAPA_1.getRGB(Pos_X, Pos_Y); break; case 2: color_RGB = MAPA_2.getRGB(Pos_X, Pos_Y); break; case 3: color_RGB = MAPA_3.getRGB(Pos_X, Pos_Y); break; case 4: break;//no hace nada } //dependiendo el color del pixel donde este el cursor realiza las acciones if(color_RGB==-52471){//rojo //llego a la meta, pasa al siguiente nivel this.NIVEL++; puntos.clear();//limpia lista de puntos puntos.add(e.getPoint());//añade primer punto }else if(color_RGB==-16711681){//celeste //esta dentro del camino correcto, no hace nada }else if(color_RGB==-16777216 && Pos_Y<180 && this.NIVEL==3){ //Si se encuentra en el nivel 3 y toca el color negro dentro los ultimos 180 pixeles //para llegar al final (color rojo) -> muestra la imagen de terror this.NIVEL=4; Play(); }else if(color_RGB==-16777216){//negro //para cualquier de los niveles, si toca este color, //retorna a la pagina de inicio this.NIVEL=0; } } this.repaint(); } /* PARA COMENZAR EL JUEGO DEBE HACERCE CLIC EN EL RECUADRO CELESTE QUE DICE "JUGAR" */ public void mouseClicked(MouseEvent e) { if(this.NIVEL==0){ Pos_X = (int)e.getPoint().getX(); Pos_Y = (int)e.getPoint().getY(); if(MAPA_0.getRGB(Pos_X, Pos_Y)==-16711681){//comenzar a jugar this.NIVEL=1; //inicia lista de puntos puntos.clear(); puntos.add(e.getPoint()); this.repaint(); } } } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } }
Esta comentado el extremo, incluso soy redundante en muchas cosas, pero creo que es mejor dejar todos los puntos claros.
4. La clase que sigue es «Sound.java», esta clase nos permite reproducir sonido WAV desde java, esta clase no es de mi propiedad :), es una clase que puedes encontrar en varios lugares de internet,no se quien es el autor, que me perdone si no lo cito, el codigo es:
import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.UnsupportedAudioFileException; /** * @web http://jc-mouse.blogspot.com/ * @author Mouse * Este código no es mio :), disculpas al autor, me olvide de donde lo baje */ public class Sound extends Thread{ private String filename; private Position curPosition; private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb enum Position { LEFT, RIGHT, NORMAL }; public Sound(String wavfile) { filename = wavfile; curPosition = Position.NORMAL; } public Sound(String wavfile, Position p) { filename = wavfile; curPosition = p; } @Override public void run() { File soundFile = new File(filename); if (!soundFile.exists()) { System.err.println("Wave file not found: " + filename); return; } AudioInputStream audioInputStream = null; try { audioInputStream = AudioSystem.getAudioInputStream(soundFile); } catch (UnsupportedAudioFileException e1) { return; } catch (IOException e1) { return; } AudioFormat format = audioInputStream.getFormat(); SourceDataLine auline = null; DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); try { auline = (SourceDataLine) AudioSystem.getLine(info); auline.open(format); } catch (LineUnavailableException e) { return; } catch (Exception e) { return; } if (auline.isControlSupported(FloatControl.Type.PAN)) { FloatControl pan = (FloatControl) auline .getControl(FloatControl.Type.PAN); if (curPosition == Position.RIGHT) pan.setValue(1.0f); else if (curPosition == Position.LEFT) pan.setValue(-1.0f); } auline.start(); int nBytesRead = 0; byte[] abData = new byte[EXTERNAL_BUFFER_SIZE]; try { while (nBytesRead != -1) { nBytesRead = audioInputStream.read(abData, 0, abData.length); if (nBytesRead >= 0) auline.write(abData, 0, nBytesRead); } } catch (IOException e) { //e.printStackTrace(); return; } finally { auline.drain(); auline.close(); } } }
5. Esto es todo lo que necesitamos, ahora debemos implementar estas clases en la clase principal, interfaz.java, el codigo es:
package laberinto; /** * @web http://jc-mouse.blogspot.com/ * @author Mouse */ public class interfaz extends javax.swing.JFrame { /** Creates new form interfaz */ public interfaz() { initComponents(); this.setSize(800, 630); panel p = new panel(); this.add(p); this.repaint(); this.setTitle("Laberinto del Diablo * [ jc-Mouse Bolivia]"); this.setLocationRelativeTo(null); } /* resto de codigo que genera netbeans) */ .... /** * @param args the command line arguments */ public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new interfaz().setVisible(true); } }); } // Variables declaration - do not modify // End of variables declaration }
Como se puede ver, en el unico lugar donde debemos colocar el codigo es en el constructor de la clase, creamos una instancia a nuestra clase panel.java y añadimos a la interfaz. no debe tocarse nada más.
Compila el proyecto y ya debe estar todo listo.
Explicación: Para no complicarse la vida con sprite, colisiones, etc, en este juego decidi basarme en los colores de la imagen y en los eventos del raton, esa es la razon por la que se utilizan imagenes BMP porque ete formato preserva la homogeneidad del color en toda la imagen, el juego es muy sencillo, mientras se mueve el mouse por pantalla, se obtiene el valor RGB de la posicion donde esta el mouse, despues compara este color con unas simples reglas, osea mientras el cursor del raton se encuentre en el color celeste, el juego interpreta que esta en el camino correcto, cuando toca el color negro, quiere decir que se salio del camino, perdio el juego, cuando llega al color rojo, pasa al siguiente nivel, asi de simple.
Si quieres todo el codigo fuente del proyecto, sigue el siguiente enlace:
http://link.jc-mouse.net/?id=LABCODJAVX
Y si quieres el juego listo para asustar, lo puedes descarga desde aqui:
http://link.jc-mouse.net/?id=GAMLAB2TWS
eso es todo :/