ArkaLlop - Clon del Arkanoid
Llop Site Home > JAVA > ArkaLlop > Aliens
Aliens:
Clase Aliens package arkallop; import java.awt.*; /** Título: ArkaLlop Descripción: Prácticas capítulo 11, ejercicio 4 Copyright: Copyright (c) 2005 Empresa: Casa_Llop @author Albert_Lobo @version 1.0 */ /** Clase que representa los aliens de la partida. Contiene un array con todos los aliens, que no son más que 'sprites'. Trata todo lo respectivo a ellos: su movimiento, si chocan contra otro 'sprite' o las paredes, sus animaciones... */ public class Aliens implements Runnable { // Array para las imágenes de una animación: la del alien vivo. private Image imgVivo []; // Array de bytes que define los fotogramas de la animación del alien vivo. private final static byte secuenciaAlienVivo [] = new byte [] {0, 0, 0, 1, 1, 1, 2, 2, 2}; // Tablas de imgenes y bytes que gestionan la animación del alien explotando. private Image imgMuert []; private final static byte secuenciaAlienMuerto [] = new byte [] {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4}; // Cada alien debe tener constancia de la pala, los ladrillos y los bonos, para saber cómo rebotar. private Pala pala; private Nivel nivel; private Bonos bono; // El número de aliens en pantalla, el número de aliens vivos, // y finalmente una tabla para los aliens individuales. private byte numAliensAnim; private byte numAliensReal; private Alien alien []; // Asumimos que los aliens son redondos. Su diámetro y el radio. private byte diam; private byte rad; // El hilo que controlará los aliens, y la partida. private Thread hilo; private Partida partida; /** Constructor. @param nuevaPartida Partida Esta partida. */ public Aliens (Partida nuevaPartida) { // Inicializamos las variables. partida = nuevaPartida; inicializaImagenes (); alien = new Alien [] {new Alien (), new Alien (), new Alien (), new Alien (), new Alien (), new Alien ()}; hilo = new Thread (this); diam = (byte) imgVivo [0].getWidth (null); rad = (byte) (diam / 2); } /** Pone a cero el número de aliens vivos y en pantalla. */ public void variablesPorDefecto () { numAliensAnim = 0; numAliensReal = 0; } /** Arranca el hilo que mueve los aliens. */ public void arrancaHilo () { if (!hilo.isAlive ()) hilo.start (); } /** Inicializa las imágenes. */ private void inicializaImagenes () { byte i; imgVivo = new Image [3]; for (i = 0; i < imgVivo.length; i++) imgVivo [i] = ArkaLlop.getImagen ("alienVivo" + i + ".gif"); imgMuert = new Image [5]; for (i = 0; i < imgMuert.length; i++) imgMuert [i] = ArkaLlop.getImagen ("alienMuerto" + i + ".gif"); } /** Define la pala. @param nuevaPala Pala La pala. */ public void setPala (Pala nuevaPala) { pala = nuevaPala; } /** Define el nivel. @param nuevoNivel Nivel El nivel. */ public void setNivel (Nivel nuevoNivel) { nivel = nuevoNivel; } /** Define los bonos. @param nuevoBono Bonos Los bonos. */ public void setBonos (Bonos nuevoBono) { bono = nuevoBono; } /** Devuelve cuántos aliens que se mostrarán en pantalla. @return byte Número de aliens para mostrar en pantalla. */ public byte getNumAliensAnim () { return numAliensAnim; } /** Devuelve el fotograma correspondiente al alien especificado en el argumento. @param indice byte Índice del alien en el array. @return Image Imagen del alien. */ public Image getImagen (byte indice) { // Devuelve una imagen de la animación del alien vivo, o muerto. // A cada llamada a este método se devuelve la siguiente imagen de la secuencia; // cuando el índice llega al final, vuelve a cero. if (alien [indice].vive) { if (alien [indice].indiceAnimVivo == 9) alien [indice].indiceAnimVivo = 0; return imgVivo [secuenciaAlienVivo [alien [indice].indiceAnimVivo++]]; } else { if (alien [indice].indiceAnimMuerto == 15) alien [indice].indiceAnimMuerto = 0; return imgMuert [secuenciaAlienMuerto [alien [indice].indiceAnimMuerto++]]; } } /** Método propio del interfaz 'Runnable'. Gestiona la interacción de los aliens con su entorno. */ public void run () { // Variable que almacenará los milisegundos entre vuelta y vuelta del bucle. long tmpOffset = System.currentTimeMillis (); while (true) { // Mientras el juego esté pausado, que duerma un poco el hilo. while (partida.getPausa ()) try { hilo.sleep (10); } catch (InterruptedException e) {} // En este bucle gestionamos los aliens en pantalla. for (byte i = 0; i < numAliensAnim; i++) { // El alien tiene que estar vivo. if (alien [i].vive) { // Si el alien corre demasiado, reventará. if ((Math.pow (alien [i].vectX, 2) + Math.pow (alien [i].vectY, 2)) > 800) { mataAlien (i); continue; } // Mueve al alien. alien [i].coordX += alien [i].vectX; alien [i].coordY += alien [i].vectY; // Comprueba si ha chocado contra la pared, un bono, un ladrillo, contra otro alien, o la pala. choquePared (i); choqueBono (i); choqueLadrillo (i); if (numAliensAnim > 1) choqueAlien (i); if (alien [i].coordY + diam > 510) choquePala (i); } } // Se calcula cuánto ha pasado desde que empezó la vuelta del bucle. // Este valor se descontará del tiempo de descanso del hilo. // El hilo descansaría 50 milisegundos, así que si 'tmpOffset' es demasiado, // lo ajustamos para que el hilo duerma al menos 10 milésimas. tmpOffset = System.currentTimeMillis () - tmpOffset; if (tmpOffset > 40) tmpOffset = 40; try { Thread.sleep (50 - tmpOffset); } catch (InterruptedException e) {} tmpOffset = System.currentTimeMillis (); } } /** Función que mira si un alien ha chocado con la pala. De ser así, 'mata' al alien. @param indice byte Índice del alien. */ private void choquePala (byte indice) { // Empezamos optimistas para el alien. boolean hayChoque = false; // ¿Ha chocado con la superficie de la pala? if ((alien [indice].coordX + rad >= pala.getCoordX () + 6) && (alien [indice].coordX + rad <= pala.getCoordX () + pala.getAnchura () - 6)) hayChoque = true; // ¿Ha chocado con alguno de los bordes de la pala? else if ((alien [indice].coordX + rad > pala.getCoordX () + pala.getAnchura () - 6) && (alien [indice].coordX + (diam * .125) <= pala.getCoordX () + pala.getAnchura ())) { short vectChoqX = (short) ((alien [indice].coordX + rad) - (pala.getCoordX () + pala.getAnchura () - 6)); short vectChoqY = (short) ((alien [indice].coordY + rad) - 520); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < Math.pow (rad + 8, 2)) hayChoque = true; } else if ((alien [indice].coordX + (diam * .875) >= pala.getCoordX ()) && (alien [indice].coordX + rad < pala.getCoordX () + 6)) { short vectChoqX = (short) ((alien [indice].coordX + rad) - (pala.getCoordX () + 6)); short vectChoqY = (short) ((alien [indice].coordY + rad) - 520); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < Math.pow (rad + 8, 2)) hayChoque = true; } // Si ha habido choque, suma 500 puntos a la partida, y mata al alien. if (hayChoque) { partida.sumaPuntos (500); mataAlien (indice); } } /** Comprueba si el alien ha chocado con algún ladrillo. En tal caso, lo cambia de dirección. @param indice byte Índice del alien en cuestión. */ private void choqueLadrillo (byte indice) { // Según la dirección y el sentido del alien, el choque se podría dar por diferentes puntos del // ladrillo. if (alien [indice].vectX == 0) { if (alien [indice].vectY > 0) { if (choqLadAbajo (indice) || choqLadAbajoIzq (indice) || choqLadAbajoDer (indice)) return; } else { if (choqLadArriba (indice) || choqLadArribaIzq (indice) || choqLadArribaDer (indice)) return; } } else if (alien [indice].vectY == 0) { if (alien [indice].vectX > 0) { if (choqLadDerecha (indice) || choqLadArribaDer (indice) || choqLadAbajoDer (indice)) return; } else { if (choqLadIzquierda (indice) || choqLadArribaIzq (indice) || choqLadAbajoIzq (indice)) return; } } else if (alien [indice].vectX > 0) { if (alien [indice].vectY > 0) { if (choqLadAbajoDer (indice) || choqLadAbajo (indice) || choqLadDerecha (indice) || choqLadArribaDer (indice) || choqLadAbajoIzq (indice)) return; } else { if (choqLadArribaDer (indice) || choqLadArriba (indice) || choqLadDerecha (indice) || choqLadArribaIzq (indice) || choqLadAbajoDer (indice)) return; } } else { if (alien [indice].vectY > 0) { if (choqLadAbajoIzq (indice) || choqLadAbajo (indice) || choqLadIzquierda (indice) || choqLadArribaIzq (indice) || choqLadAbajoDer (indice)) return; } else { if (choqLadArribaIzq (indice) || choqLadArriba (indice) || choqLadIzquierda (indice) || choqLadArribaDer (indice) || choqLadAbajoIzq (indice)) return; } } } /** Comprueba si un alien ha chocado contra la parte de arriba del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadArriba (byte indice) { // Lo primero es calcular las coordenadas del ladrillo que se encuentra bajo el alien. float posLadX = (alien [indice].coordX + rad - 30) / 40; float posLadY = (alien [indice].coordY - 100) / 20; // Miramos si el ladrillo podría existir (el muro puede llegar a tener 11 ladrillos de ancho // por 13 de alto), y luego si hay ladrillo o no en ese sitio. // Si se produce choque, ajustamos el movimiento del alien, y devolvemos 'true'. if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { alien [indice].vectY *= -1; return true; } // No ha habido choque. return false; // El resto de funciones que miran si hubo choque contra un ladrillo, tienen una mecánica idéntica. } /** Comprueba si un alien ha chocado con el ángulo superior izquierdo del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadArribaIzq (byte indice) { short rCuad = (short) (Math.pow (rad, 2)); float posLadX = (alien [indice].coordX - 30) / 40; float posLadY = (alien [indice].coordY - 100) / 20; if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { float vectChoqX = (alien [indice].coordX + rad - 30) - ((byte) (posLadX + 1) * 40 - 1); float vectChoqY = (alien [indice].coordY + rad - 100) - ((byte) (posLadY + 1) * 20 - 1); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { ajustaVector (alien [indice].vectX, alien [indice].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indice); return true; } } return false; } /** Comprueba si un alien ha chocado contra el ángulo superior derecho del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadArribaDer (byte indice) { short rCuad = (short) (Math.pow (rad, 2)); float posLadX = (alien [indice].coordX + diam - 30) / 40; float posLadY = (alien [indice].coordY - 100) / 20; if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { float vectChoqX = (alien [indice].coordX + rad - 30) - ((byte) (posLadX) * 40 + 1); float vectChoqY = (alien [indice].coordY + rad - 100) - ((byte) (posLadY + 1) * 20 - 1); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { ajustaVector (alien [indice].vectX, alien [indice].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indice); return true; } } return false; } /** Comprueba si un alien ha chocado contra la base del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadAbajo (byte indice) { float posLadX = (alien [indice].coordX + rad - 30) / 40; float posLadY = (alien [indice].coordY + diam - 100) / 20; if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { alien [indice].vectY *= -1; return true; } return false; } /** Comprueba si un alien ha chocado contra el lado izquierdo del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadIzquierda (byte indice) { float posLadX = (alien [indice].coordX - 30) / 40; float posLadY = (alien [indice].coordY + rad - 100) / 20; if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { alien [indice].vectX *= -1; return true; } return false; } /** Comprueba si un alien ha chocado contra el lado derecho del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadDerecha (byte indice) { float posLadX = (alien [indice].coordX + diam - 30) / 40; float posLadY = (alien [indice].coordY + rad - 100) / 20; if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { alien [indice].vectX *= -1; return true; } return false; } /** Comprueba si un alien ha chocado contra el ángulo inferior izquierdo del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadAbajoIzq (byte indice) { short rCuad = (short) (Math.pow (rad, 2)); float posLadX = (alien [indice].coordX - 30) / 40; float posLadY = (alien [indice].coordY + diam - 100) / 20; if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { float vectChoqX = (alien [indice].coordX + rad - 30) - ((byte) (posLadX + 1) * 40 - 1); float vectChoqY = (alien [indice].coordY + rad - 100) - ((byte) (posLadY) * 20 + 1); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { ajustaVector (alien [indice].vectX, alien [indice].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indice); return true; } } return false; } /** Comprueba si un alien ha chocado contra el ángulo inferior derecho del ladrillo, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqLadAbajoDer (byte indice) { short rCuad = (short) (Math.pow (rad, 2)); float posLadX = (alien [indice].coordX + diam - 30) / 40; float posLadY = (alien [indice].coordY + diam - 100) / 20; if ((posLadX >= 0) && (posLadX < 11) && (posLadY >= 0) && (posLadY < 13) && (nivel.getResistLadrillo ((byte) posLadX, (byte) posLadY) > 0)) { float vectChoqX = (alien [indice].coordX + rad - 30) - ((byte) (posLadX) * 40 + 1); float vectChoqY = (alien [indice].coordY + rad - 100) - ((byte) (posLadY) * 20 + 1); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { ajustaVector (alien [indice].vectX, alien [indice].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indice); return true; } } return false; } /** Ajusta el vector de movimiento de un alien. Se utiliza cuando el alien ha chocado con alguno de los ángulos de un ladrillo, o un bono. @param vectReboteX float El componente X del vector de movimiento del alien. @param vectReboteY float El componente Y del vector de movimiento del alien. @param vectChoqX float El componente X del vector de choque. @param vectChoqY float El componente Y del vector de choque. @param modCuadVectChoq float El módulo del vector de choque al cuadrado. @param indice byte El índice del alien en cuestión. */ private void ajustaVector (float vectReboteX, float vectReboteY, float vectChoqX, float vectChoqY, float modCuadVectChoq, byte indice) { float nuevoVectX = ((-vectReboteX) * vectChoqX * vectChoqX + (-vectReboteY) * vectChoqX * vectChoqY + vectReboteX * vectChoqY * vectChoqY - vectReboteY * vectChoqX * vectChoqY) / modCuadVectChoq; float nuevoVectY = ((-vectReboteX) * vectChoqX * vectChoqY + (-vectReboteY) * vectChoqY * vectChoqY + vectReboteX * vectChoqX * vectChoqY - vectReboteY * vectChoqX * vectChoqX) / modCuadVectChoq; alien [indice].setVect (nuevoVectX, nuevoVectY); } /** Comprueba si el alien ha chocado con algún bono. En tal caso, lo cambia de dirección. @param indice byte Índice del alien en cuestión. */ private void choqueBono (byte indice) { // Hay que comprobar todos los bonos en pantalla. byte numBonos = bono.getNumBonosAnim (); for (byte i = 0; i < numBonos; i++) { // Si el bono está estallando, seguimos. if (!bono.estaActivo (i)) continue; // Igual que con los ladrillos, según la dirección y el sentido del alien, // el choque se podría dar por diferentes puntos del bono. if (alien [indice].vectX == 0) { if (alien [indice].vectY > 0) { if (choqBonoAbajo (indice, i) || choqBonoAbajoIzq (indice, i) || choqBonoAbajoDer (indice, i)) return; } else { if (choqBonoArriba (indice, i) || choqBonoArribaIzq (indice, i) || choqBonoArribaDer (indice, i)) return; } } else if (alien [indice].vectY == 0) { if (alien [indice].vectX > 0) { if (choqBonoDerecha (indice, i) || choqBonoArribaDer (indice, i) || choqBonoAbajoDer (indice, i)) return; } else { if (choqBonoIzquierda (indice, i) || choqBonoArribaIzq (indice, i) || choqBonoAbajoIzq (indice, i)) return; } } else if (alien [indice].vectX > 0) { if (alien [indice].vectY > 0) { if (choqBonoAbajoDer (indice, i) || choqBonoAbajo (indice, i) || choqBonoDerecha (indice, i) || choqBonoArribaDer (indice, i) || choqBonoAbajoIzq (indice, i)) return; } else { if (choqBonoArribaDer (indice, i) || choqBonoArriba (indice, i) || choqBonoDerecha (indice, i) || choqBonoArribaIzq (indice, i) || choqBonoAbajoDer (indice, i)) return; } } else { if (alien [indice].vectY > 0) { if (choqBonoAbajoIzq (indice, i) || choqBonoAbajo (indice, i) || choqBonoIzquierda (indice, i) || choqBonoArribaIzq (indice, i) || choqBonoAbajoDer (indice, i)) return; } else { if (choqBonoArribaIzq (indice, i) || choqBonoArriba (indice, i) || choqBonoIzquierda (indice, i) || choqBonoArribaDer (indice, i) || choqBonoAbajoIzq (indice, i)) return; } } } } /** Comprueba si un alien ha chocado contra el lado de arriba de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoArriba (byte indAlien, byte indBono) { if ((alien [indAlien].coordX + rad > bono.getCoordX (indBono)) && (alien [indAlien].coordX + rad < bono.getCoordX (indBono) + 30) && (alien [indAlien].coordY < bono.getCoordY (indBono) + 10) && (alien [indAlien].coordY > bono.getCoordY (indBono))) { bono.mataBono (indBono); alien [indAlien].vectY *= -1; return true; } return false; } /** Comprueba si un alien ha chocado contra el ángulo superior izquierdo de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoArribaIzq (byte indAlien, byte indBono) { short rCuad = (short) (Math.pow (rad, 2)); float vectChoqX = (alien [indAlien].coordX + rad) - (bono.getCoordX (indBono) + 30); float vectChoqY = (alien [indAlien].coordY + rad) - (bono.getCoordY (indBono) + 10); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { bono.mataBono (indBono); ajustaVector (alien [indAlien].vectX, alien [indAlien].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indAlien); return true; } return false; } /** Comprueba si un alien ha chocado contra el ángulo superior derecho de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoArribaDer (byte indAlien, byte indBono) { short rCuad = (short) (Math.pow (rad, 2)); float vectChoqX = (alien [indAlien].coordX + rad) - (bono.getCoordX (indBono)); float vectChoqY = (alien [indAlien].coordY + rad) - (bono.getCoordY (indBono) + 10); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { bono.mataBono (indBono); ajustaVector (alien [indAlien].vectX, alien [indAlien].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indAlien); return true; } return false; } /** Comprueba si un alien ha chocado contra la base de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoAbajo (byte indAlien, byte indBono) { if ((alien [indAlien].coordX + rad > bono.getCoordX (indBono)) && (alien [indAlien].coordX + rad < bono.getCoordX (indBono) + 30) && (alien [indAlien].coordY + diam > bono.getCoordY (indBono)) && (alien [indAlien].coordY + diam < bono.getCoordY (indBono) + 10)) { bono.mataBono (indBono); alien [indAlien].vectY *= -1; return true; } return false; } /** Comprueba si un alien ha chocado contra el lado izquierdo de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoIzquierda (byte indAlien, byte indBono) { if ((alien [indAlien].coordY + rad > bono.getCoordY (indBono)) && (alien [indAlien].coordY + rad < bono.getCoordY (indBono) + 10) && (alien [indAlien].coordX < bono.getCoordX (indBono) + 30) && (alien [indAlien].coordX > bono.getCoordX (indBono))) { bono.mataBono (indBono); alien [indAlien].vectX *= -1; return true; } return false; } /** Comprueba si un alien ha chocado contra el lado derecho de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoDerecha (byte indAlien, byte indBono) { if ((alien [indAlien].coordY + rad > bono.getCoordY (indBono)) && (alien [indAlien].coordY + rad < bono.getCoordY (indBono) + 10) && (alien [indAlien].coordX > bono.getCoordX (indBono)) && (alien [indAlien].coordX < bono.getCoordX (indBono) + 30)) { bono.mataBono (indBono); alien [indAlien].vectX *= -1; return true; } return false; } /** Comprueba si un alien ha chocado contra el ángulo inferior izquierdo de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoAbajoIzq (byte indAlien, byte indBono) { short rCuad = (short) (Math.pow (rad, 2)); float vectChoqX = (alien [indAlien].coordX + rad) - (bono.getCoordX (indBono) + 30); float vectChoqY = (alien [indAlien].coordY + rad) - (bono.getCoordY (indBono)); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { bono.mataBono (indBono); ajustaVector (alien [indAlien].vectX, alien [indAlien].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indAlien); return true; } return false; } /** Comprueba si un alien ha chocado contra el ángulo inferior derecho de un bono, y devuelve un valor booleano según lo averiguado. Si hay choque, se ajusta el vector de movimiento del alien, y se 'mata' el bono. @param indAlien byte Índice del alien en cuestión. @param indBono byte Índice del bono de marras. @return boolean 'true' o 'false' según el alien haya chocado o no. */ private boolean choqBonoAbajoDer (byte indAlien, byte indBono) { short rCuad = (short) (Math.pow (rad, 2)); float vectChoqX = (alien [indAlien].coordX + rad) - (bono.getCoordX (indBono)); float vectChoqY = (alien [indAlien].coordY + rad) - (bono.getCoordY (indBono)); float modCuadVectChoq = (float) (Math.pow (vectChoqX, 2) + Math.pow (vectChoqY, 2)); if (modCuadVectChoq < rCuad) { bono.mataBono (indBono); ajustaVector (alien [indAlien].vectX, alien [indAlien].vectY, vectChoqX, vectChoqY, modCuadVectChoq, indAlien); return true; } return false; } /** Devuelve la coordenada X de un alien. @param indice byte Índice del alien en cuestión. @return float Su coordenada X. */ public float getCoordX (byte indice) { return alien [indice].coordX; } /** Devuelve la coordenada Y de un alien. @param indice byte Índice del alien en cuestión. @return float Su coordenada Y. */ public float getCoordY (byte indice) { return alien [indice].coordY; } /** Devuelve el componente X del vector de movimiento de un alien. @param indice byte Índice del alien en cuestión. @return float Componente X de su vector de movimiento. */ public float getVectX (byte indice) { return alien [indice].vectX; } /** Devuelve el componente Y del vector de movimiento de un alien. @param indice byte Índice del alien en cuestión. @return float Componente Y de su vector de movimiento. */ public float getVectY (byte indice) { return alien [indice].vectY; } /** Devuelve el radio de los aliens. @return byte Radio de los aliens. */ public byte getRad () { return rad; } /** Genera un alien, y lo sitúa bajo una de las tres vainas. @param vaina byte Vaina de la que 'sale' el nuevo alien. */ private synchronized void generaAlien (byte vaina) { // Si el número de aliens en pantalla se vuelve negativo alguna vez, vuelve a 0. if (numAliensAnim < 0) numAliensAnim = 0; // Habrá un máximo de 6 aliens en pantalla, y aquí nos aseguramos. if (numAliensAnim < 6) { // Definimos las variables del alien. alien [numAliensAnim].setCoords (94 + vaina * 140, 40); alien [numAliensAnim].setVect (2, 2); alien [numAliensAnim].vive = true; // Ajustamos la cuenta de aliens vivos y en pantalla. numAliensAnim++; numAliensReal++; // Pasamos los aliens muriendo al final de la tabla. defragAlienArr ((byte) (numAliensAnim - 1)); // Suena un ruidillo. partida.suena (Sonido.SALE_ALIEN); } } /** 'Mata' un alien. @param indice byte Índice del alien en cuestión. */ private synchronized void mataAlien (byte indice) { alien [indice].vive = false; defragAlienArr (indice); numAliensReal--; partida.suena (Sonido.PETA_BONO_ALIEN); alien [numAliensReal].alarma.schedule (new java.util.TimerTask () { public void run () { numAliensAnim--; } }, 500); } /** Método que intercambia la posición de dos aliens en la tabla: el indicado con el argumento con el último de los 'vivos' en la tabla. @param indice byte Índice del alien que se pondrá en el lugar del último 'vivo'. */ private synchronized void defragAlienArr (byte indice) { if (indice != numAliensReal - 1) { Alien aux = alien [numAliensReal - 1]; alien [numAliensReal - 1] = alien [indice]; alien [indice] = aux; } } /** Comprueba si un alien choca contra una de las paredes del escenario. Si es así, ajusta el vector de movimiento del alien. @param indice byte Índice del alien en cuestión. */ private void choquePared (byte indice) { // ¿Ha chocado con el lado izquierdo? if (alien [indice].coordX < 30) { alien [indice].coordX = (short) (2 * 30 - alien [indice].coordX); alien [indice].vectX *= -1; } // ¿Ha chocado con el lado derecho? if (alien [indice].coordX + diam > 470) { alien [indice].coordX = (short) (2 * (470 - diam) - alien [indice].coordX); alien [indice].vectX *= -1; } // ¿Ha chocado con el techo? if (alien [indice].coordY < 40) { alien [indice].coordY = (short) (2 * 40 - alien [indice].coordY); alien [indice].vectY *= -1; } // ¿Ha chocado con el suelo? if (alien [indice].coordY + diam > 520) { alien [indice].coordY = (short) (2 * (520 - diam) - alien [indice].coordY); alien [indice].vectY *= -1; } } /** En esta función se comprueba si un alien ha chocado con otro; si lo ha hecho, calcula la nueva velocidad y dirección de los dos aliens. @param indice byte Índice del alien en cuestión. */ private void choqueAlien (byte indice) { // Comprobamos si el alien ha chocado con alguno de los que hay en pantalla. for (byte i = 0; i < numAliensAnim; i++) { // El bucle se salta una vuelta cuando el otro alien está muerto, // o es el mismo. if ((indice == i) || (!alien [i].vive)) continue; // Primero miramos si el 'clip' de los dos aliens se superponen. float vectChoqX = alien [indice].coordX - alien [i].coordX; float vectChoqY = alien [indice].coordY - alien [i].coordY; if (((vectChoqX < 16) && (vectChoqX > - 16)) || ((vectChoqY < 16) && (vectChoqY > - 16))) { float modVectCuad = (float) (Math.pow (alien [indice].coordX - alien [i].coordX, 2) + Math.pow (alien [indice].coordY - alien [i].coordY, 2)); // Miramos si los dos aliens están demasiado juntos. if (modVectCuad < Math.pow (diam, 2)) { // Sólo hay choque si uno se acerca al otro. if (((alien [indice].vectX * vectChoqX + alien [indice].vectY * vectChoqY) - (alien [i].vectX * vectChoqX + alien [i].vectY * vectChoqY)) < 0) { float nuevoVectXBola = (alien [i].vectX * vectChoqX * vectChoqX + alien [i].vectY * vectChoqX * vectChoqY + alien [indice].vectX * vectChoqY * vectChoqY - alien [indice].vectY * vectChoqX * vectChoqY) / modVectCuad; float nuevoVectYBola = (alien [i].vectX * vectChoqX * vectChoqY + alien [i].vectY * vectChoqY * vectChoqY - alien [indice].vectX * vectChoqX * vectChoqY + alien [indice].vectY * vectChoqX * vectChoqX) / modVectCuad; float nuevoVectXOtrBola = (alien [indice].vectX * vectChoqX * vectChoqX + alien [indice].vectY * vectChoqX * vectChoqY + alien [i].vectX * vectChoqY * vectChoqY - alien [i].vectY * vectChoqX * vectChoqY) / modVectCuad; float nuevoVectYOtrBola = (alien [indice].vectX * vectChoqX * vectChoqY + alien [indice].vectY * vectChoqY * vectChoqY - alien [i].vectX * vectChoqX * vectChoqY + alien [i].vectY * vectChoqX * vectChoqX) / modVectCuad; alien [indice].setVect (nuevoVectXBola, nuevoVectYBola); alien [i].setVect (nuevoVectXOtrBola, nuevoVectYOtrBola); } } } } } /** Devuelve un booleano que indica si un alien está vivo o no. @param indice byte Índice del alien en cuestión. @return boolean 'true' o 'false' según el alien esté vivo o no. */ public boolean estaVivo (byte indice) { return alien [indice].vive; } /** Clase interna que contiene la información de un alien individual. Su constructor, sus funciones y
sus variables son privadas, ya que sólo debe acceder a ellas la misma clase 'Aliens'. */ private class Alien { // Las coordenadas del alien en la pantalla. private float coordX; private float coordY; // Componentes del vector de movimiento del alien. private float vectX; private float vectY; // Si el alien está vivo. private boolean vive; // Índices de la secuencia de animación del alien cuando está vivo, y cuando está muerto. private byte indiceAnimVivo; private byte indiceAnimMuerto; // Alarma para programar algunos sucesos. private java.util.Timer alarma; /** Constructor. */ private Alien () { coordX = coordY = vectX = vectY = indiceAnimVivo = indiceAnimMuerto = 0; vive = false; alarma = new java.util.Timer (); } /** Define las coordenadas del alien. @param nuevaCoordX float Nueva coordenada X del alien. @param nuevaCoordY float Nueva coordenada Y del alien. */ private void setCoords (float nuevaCoordX, float nuevaCoordY) { coordX = nuevaCoordX; coordY = nuevaCoordY; } /** Define los componentes del vector de movimiento del alien. @param nuevoVectX float Nuevo componente X del vector de movimiento del alien. @param nuevoVectY float Nuevo componente Y del vector de movimiento del alien. */ private void setVect (float nuevoVectX, float nuevoVectY) { vectX = nuevoVectX; vectY = nuevoVectY; } } }
¿Comentarios, sugerencias?: llopsite.at.yahoo.es | © 2005-07 Albert Lobo
Última actualización: 18-Feb-2007