ArkaLlop - Clon del Arkanoid
Llop Site Home > JAVA > ArkaLlop > Bonos
Bonos:
Clase Bonos 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 bonos de la partida. Contiene un array con todos los bonos, que no son más que 'sprites'. Se encarga de su movimiento, y controla si chocan con el fondo. */ public class Bonos implements Runnable { /** Constante que define la velocidad de caída de los bonos. */ private final static byte VELOCIDAD_BONO = 3; /** Constante que define cuántos tipos distintos de bonos hay. */ private final static byte TOTAL_BONOS = 9; /** Constante que representa el bono que acelera las bolas. */ public final static byte ACELERA_BOLAS = 0; /** Constante que representa el bono que decelera las bolas. */ public final static byte DECELERA_BOLAS = 1; /** Constante que representa el bono que divide en tres la bola. */ public final static byte TRES_BOLAS = 2; /** Constante que representa el bono que cambia el tamaño de las bolas. */ public final static byte TAMANO_BOLAS = 3; /** Constante que representa el bono que pone los cañones en la pala. */ public final static byte DISPAROS_PALA = 4; /** Constante que representa el bono que cambia la anchura de la pala. */ public final static byte ANCHURA_PALA = 5; /** Constante que representa el bono cambia la imantación de la pala. */ public final static byte IMAN_PALA = 6; /** Constante que representa el bono de 'vida extra'. */ public final static byte VIDA = 7; /** Constante que representa el bono que abre y cierra la puerta al siguiente nivel. */ public final static byte SIGUIENTE_NIVEL = 8; // Arrays para las imágenes de las animaciones (las del bono vivo, y la del bono petando), // y para sus correspondientes fotogramas. private Image imgBonoActivo [][]; private final static byte secuenciaVive [] = new byte [] {0, 0, 0, 1, 1, 1}; private Image imgBonoMuerto []; private final static byte secuenciaMuere [] = new byte [] {0, 0, 0, 1, 1, 1, 2, 2, 2}; // Imagen para un bono estresado. private Image imgBonoEstresado; // El número de bonos en pantalla, el número de bonos vivos, // y finalmente una tabla para los bonos individuales. private byte numBonosAnim; private byte numBonosReal; private Bono bono []; // El hilo que controlará los bonos, y la partida. private Thread hilo; private Partida partida; /** Constructor. @param nuevaPartida Partida Esta partida. */ public Bonos (Partida nuevaPartida) { // Inicializamos las variables. partida = nuevaPartida; inicializaImagenes (); bono = new Bono [] {new Bono (), new Bono (), new Bono (), new Bono (), new Bono (), new Bono (), new Bono (), new Bono (), new Bono (), new Bono ()}; hilo = new Thread (this); variablesPorDefecto (); } /** Genera un bono al azar, y lo sitúa donde estaba el ladrillo que acaba de reventar. @param posXLadrillo byte Coordenada X (en el array) del ladrillo que acaba de petar. @param posYLadrillo byte Coordenada Y (en el array) del ladrillo que acaba de petar. */ public synchronized void generaBono (byte posXLadrillo, byte posYLadrillo) { // No podemos permitir que el número de ladrillos sea negativo. if (numBonosAnim < 0) numBonosAnim = 0; // Habrá un máximo de 10 ladrillos -vivos o muertos- en pantalla. if (numBonosAnim < 10) { // Ajustamos las variables del nuevo bono. bono [numBonosAnim].setCoords (35 + posXLadrillo * 40, 102 + posYLadrillo * 20); bono [numBonosAnim].activo = true; bono [numBonosAnim].tipo = getTipoBonoAlAzar (); bono [numBonosAnim].resistencia = 5; // Ajustamos las variables que llevan la cuenta de los bonos. numBonosAnim++; numBonosReal++; // Ahora hay que poner el nuevo bono a la cola de los vivos, y hacer sonar el ruidito. defragBonoArr ((byte) (numBonosAnim - 1)); partida.suena (Sonido.SALE_BONO); } } /** Devuelve uno de los tipos de bono disponibles -las constantes de la clase. Nótese que los bonos de 'vida extra' y 'siguiente nivel' tienen una frecuencia de aparición cuatro veces menor que cualquier otro bono. @return byte Tipo de bono al azar -uno de los definidos en las constantes de la clase. */ private byte getTipoBonoAlAzar () { float numAleat = (float) (Math.random () * 30); if (numAleat < 1) return Bonos.VIDA; else if (numAleat < 2) return Bonos.SIGUIENTE_NIVEL; else if (numAleat < 6) return Bonos.TAMANO_BOLAS; else if (numAleat < 10) return Bonos.DISPAROS_PALA; else if (numAleat < 14) return Bonos.ACELERA_BOLAS; else if (numAleat < 18) return Bonos.DECELERA_BOLAS; else if (numAleat < 22) return Bonos.ANCHURA_PALA; else if (numAleat < 26) return Bonos.TRES_BOLAS; else return Bonos.IMAN_PALA; } /** Destruye un bono. @param indice byte Índice del bono en cuestión. */ public void mataBono (byte indice) { // Desactivar el bono, meterlo en su mitad del array, y ajustar cuenta de bonos vivos. bono [indice].activo = false; defragBonoArr (indice); numBonosReal--; // Hacer sonar ruidillo, y quitar bono de la vista en 1/3 de segundo. partida.suena (Sonido.PETA_BONO_ALIEN); bono [numBonosReal].alarma.schedule (new java.util.TimerTask () { public void run () { numBonosAnim--; } }, 330); } /** Intercambia la posición de dos bonos en la tabla: el indicado con el argumento con el último de los 'vivos' en la tabla. @param indice byte Índice del bono que se pondrá en el lugar del último 'activo'. */ public synchronized void defragBonoArr (byte indice) { if (indice != numBonosReal - 1) { Bono aux = bono [numBonosReal - 1]; bono [numBonosReal - 1] = bono [indice]; bono [indice] = aux; } } /** Permite saber si un disparo está activo. @param indice byte Índice del disparo en cuestión. @return boolean 'true' o 'false' según esté activo el tiro o no. */ public boolean estaActivo (byte indice) { return bono [indice].activo; } /** Permite saber si un disparo está estresado. @param indice byte Índice del disparo en cuestión. @return boolean 'true' o 'false' según esté estresado el tiro o no. */ public boolean estaEstresado (byte indice) { return bono [indice].estresado; } /** Notifica un impacto a un bono, y el daño que ha recibido. Si ya no le queda resistencia al bono, reventará. @param indice byte Índice del bono impactado. @param dano float Potencia del impacto -o el daño que recibe el bono. */ public void impactaBono (byte indice, float dano) { // Restar el daño de la resistencia. bono [indice].resistencia -= dano; // Miramos si el bono se va a romper ya para 'destruirlo' o 'estresarlo'. if (bono [indice].resistencia <= 0) mataBono (indice); else bono [indice].estresa (); } /** Devuelve la coordenada X de un bono. @param indice byte Índice del bono en cuestión. @return float Su coordenada X. */ public float getCoordX (byte indice) { return bono [indice].coordX; } /** Devuelve la coordenada Y de un bono. @param indice byte Índice del bono en cuestión. @return float Su coordenada Y. */ public float getCoordY (byte indice) { return bono [indice].coordY; } /** permite conocer el tipo de un bono. @param indice byte Índice del bono en cuestión. @return byte Tipo del bono. */ public byte getTipo (byte indice) { return bono [indice].tipo; } /** Permite conocer cuántos bonos hay en pantalla. @return byte Numero de bonos en pantalla. */ public byte getNumBonosAnim () { return numBonosAnim; } /** Pone a cero el número de bonos vivos y en pantalla. */ public void variablesPorDefecto () { numBonosAnim = 0; numBonosReal = 0; } /** Inicializa las imágenes. */ public void inicializaImagenes () { byte i; byte j; imgBonoActivo = new Image [TOTAL_BONOS][2]; for (i = 0; i < TOTAL_BONOS; i++) for (j = 0; j < 2; j++) imgBonoActivo [i][j] = ArkaLlop.getImagen ("bonoTipo" + i + j + ".gif"); imgBonoMuerto = new Image [3]; for (i = 0; i < imgBonoMuerto.length; i++) imgBonoMuerto [i] = ArkaLlop.getImagen ("bonoPetando" + i + ".gif"); imgBonoEstresado = ArkaLlop.getImagen ("bonoEstresado.gif"); } /** Devuelve el fotograma correspondiente a un bono. @param indice byte Índice del bono en el array. @return Image Imagen del bono. */ public Image getImagenBono (byte indice) { // 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 (bono [indice].activo) { if (bono [indice].estresado) return imgBonoEstresado; else { if (bono [indice].indiceAnimVive == 6) bono [indice].indiceAnimVive = 0; return imgBonoActivo [bono [indice].tipo][secuenciaVive [bono [indice].indiceAnimVive++]]; } } else { if (bono [indice].indiceAnimMuere == 9) bono [indice].indiceAnimMuere = 0; return imgBonoMuerto [secuenciaMuere [bono [indice].indiceAnimMuere++]]; } } /** Método propio del interfaz 'Runnable'. Mueve los bonos. */ 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) {} // Hay que mirar todos los bonos. for (byte i = 0; i < numBonosAnim; i++) { // Si está activo, el bono baja un poco. // Y si toca el fondo, se destruye. if (bono [i].activo) { bono [i].coordY += VELOCIDAD_BONO; if (bono [i].coordY > 510) mataBono (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 (); } } /** Arranca el hilo que mueve los bonos. */ public void arrancaHilo () { if (!hilo.isAlive ()) hilo.start (); } /** Clase interna que contiene la información de un bono individual. Su constructor, sus funciones y sus variables son privadas, ya que sólo debe acceder a ellas la misma clase 'Bonos'. */ private class Bono { // El tipo, las coordenadas, y la resistencia del bono. private byte tipo; private float coordX; private float coordY; private float resistencia; // Si está activo, si está estresado, y una alarma para programar eventos. private boolean activo; private boolean estresado; private java.util.Timer alarma; // Índices de la secuencia de animación del bono cuando está vivo, y cuando está reventando. private byte indiceAnimVive; private byte indiceAnimMuere; /** Constructor. */ private Bono () { coordX = coordY = tipo = indiceAnimVive = indiceAnimMuere = 0; activo = estresado = false; resistencia = 5; alarma = new java.util.Timer (); } /** Define las coordenadas del bono. @param nuevaCoordX float Nueva coordenada X del bono. @param nuevaCoordY float Nueva coordenada Y del bono. */ private void setCoords (float nuevaCoordX, float nuevaCoordY) { coordX = nuevaCoordX; coordY = nuevaCoordY; } /** 'Estresa' el bono -cambia su apariencia en pantalla para resaltar que ha recibido un impacto. */ private void estresa () { // La variable 'estresado' es 'true' durante un cuarto de segundo; // al repintarse la pantalla, el jugador verá la imagen 'imgBonoEstresado'. estresado = true; alarma.schedule (new java.util.TimerTask () { public void run () { estresado = false; } }, 250); } } }
¿Comentarios, sugerencias?: llopsite.at.yahoo.es | © 2005-07 Albert Lobo
Última actualización: 18-Feb-2007