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

Hosted by www.Geocities.ws

1