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

Hosted by www.Geocities.ws

1