TLlop - Clon del Tetris

Llop Site Home > JAVA > TLlop > Pieza

Pieza:

Clase Pieza

package ejercicio_5;

import java.lang.*;
import javax.swing.*;

/** Título: TLlop
    Descripción: Prácticas capítulo 11, ejercicio 5
    Copyright: Copyright (c) 2005
    Empresa: Casa_Llop
    @author Albert_Lobo
    @version 1.5  */

/** Clase cuyos objetos representan alguna de las 35 piezas disponibles en el juego. 

    Las piezas se representan con coordenadas -las posiciones relativas de cada cuadradillo-,
    e iconos para pintarlas. */
public class Pieza
{
  // Los colores de pieza disponibles.
  /** Cadena constante que corresponde a la descripción del color amarillo. */
  public static final String AMARILLO = "Amarillo";
  /** Cadena constante que corresponde a la descripción del color azul. */
  public static final String AZUL = "Azul";
  /** Cadena constante que corresponde a la descripción del color blanco. */
  public static final String BLANCO = "Blanco";
  /** Cadena constante que corresponde a la descripción del color gris. */
  public static final String GRIS = "Gris";
  /** Cadena constante que corresponde a la descripción del color lila. */
  public static final String LILA = "Lila";
  /** Cadena constante que corresponde a la descripción del color marrón. */
  public static final String MARRON = "Marron";
  /** Cadena constante que corresponde a la descripción del color naranja. */
  public static final String NARANJA = "Naranja";
  /** Cadena constante que corresponde a la descripción del color rojo. */
  public static final String ROJO = "Rojo";
  /** Cadena constante que corresponde a la descripción del color turquesa. */
  public static final String TURQUESA = "Turquesa";
  /** Cadena constante que corresponde a la descripción del color verde. */
  public static final String VERDE = "Verde";
  /** Cadena constante que corresponde a la descripción del color verde pálido. */
  public static final String VERDE_PALIDO = "VerdePalido";

  // Los diseños de pieza disponibles.
  /** Cadena constante con la descripción del diseño de la pieza -a cuadradillos. */
  public static final String CUADRADILLO = "cuadradillo";
  /** Cadena constante con la descripción del diseño de la pieza -a circulillos. */
  public static final String CIRCULILLO = "circulillo";
  /** Cadena constante con la descripción del diseño de la pieza -a estrellitas. */
  public static final String ESTRELLITA = "estrellita";
  /** Cadena constante con la descripción del diseño de la pieza -a cuadradillos semi-transparentes. */
  public static final String ACIDO = "acido";
  /** Cadena constante con la descripción del diseño de la pieza -con las piezas de un teselado. */
  public static final String ENCAJE = "encaje";

  // Los posibles movimientos de la pieza.
  /** Entero constante que representa el movimiento a la izquierda de la pieza. */
  public static final byte IZQUIERDA = 0;
  /** Entero constante que representa el movimiento a la derecha de la pieza. */
  public static final byte DERECHA = 1;
  /** Entero constante que representa el movimiento abajo de la pieza. */
  public static final byte ABAJO = 2;
  /** Entero constante que representa la rotación de la pieza en sentido horario. */
  public static final byte GIRO_HORARIO = 3;
  /** Entero constante que representa la rotación de la pieza en sentido anti-horario. */
  public static final byte GIRO_ANTIHORARIO = 4;

  // Las piezas de siempre.
  /** Constante que representa el cuadrado. */
  public static final byte CUADRADO = 0;
  /** Constante que representa la barra. */
  public static final byte BARRA = 1;
  /** Constante que representa la ese. */
  public static final byte ESE = 2;
  /** Constante que representa la zeta. */
  public static final byte ZETA = 3;
  /** Constante que representa la ele invertida. */
  public static final byte ELE_INVERTIDA = 4;
  /** Constante que representa la ele. */
  public static final byte ELE = 5;
  /** Constante que representa la te. */
  public static final byte TE = 6;
  // Piezas opcionales.
  /** Constante que representa la pieza destructora. */
  public static final byte DESTRUCTORA = 7;
  /** Constante que representa el cuadradillo único. */
  public static final byte UN_CUADRADO = 8;
  /** Constante que representa la barra de dos cuadradillos. */
  public static final byte BARRA_DOS = 9;
  /** Constante que representa la diagonal de dos. */
  public static final byte ESCALERA_DOS = 10;
  /** Constante que representa la barra de tres cuadradillos. */
  public static final byte BARRA_TRES = 11;
  /** Constante que representa la ese de tres. */
  public static final byte ESE_TRES = 12;
  /** Constante que representa la zeta de tres. */
  public static final byte ZETA_TRES = 13;
  /** Constante que representa la diagonal de tres. */
  public static final byte ESCALERA_TRES = 14;
  /** Constante que representa la ele de tres. */
  public static final byte ELE_TRES = 15;
  /** Constante que representa la uve de tres. */
  public static final byte TE_TRES = 16;
  /** Constante que representa las olas (de nuevo, y a partir de aquí, de 4 cuadradillos). */
  public static final byte OLAS_CUATRO = 17;
  /** Constante que representa las olas invertidas. */
  public static final byte OLAS_INVERTIDAS_CUATRO = 18;
  /** Constante que representa las barras de dos paralelas. */
  public static final byte PARALELAS_CUATRO = 19;
  /** Constante que representa la ese separada. */
  public static final byte ESE_SEPARADA_CUATRO = 20;
  /** Constante que representa la zeta separada. */
  public static final byte ZETA_SEPARADA_CUATRO = 21;
  /** Constante que representa la diagonal. */
  public static final byte ESCALERA_CUATRO = 22;
  /** Constante que representa la coma. */
  public static final byte COMA_CUATRO = 23;
  /** Constante que representa la coma invertida. */
  public static final byte COMA_INVERTIDA_CUATRO = 24;
  /** Constante que representa el ángulo recto. */
  public static final byte ANGULO_RECTO_CUATRO = 25;
  /** Constante que representa la uve. */
  public static final byte UVE_CUATRO = 26;
  /** Constante que representa la uve invertida. */
  public static final byte UVE_INVERTIDA_CUATRO = 27;
  /** Constante que representa la ese larga. */
  public static final byte ESE_LARGA_CUATRO = 28;
  /** Constante que representa la zeta larga. */
  public static final byte ZETA_LARGA_CUATRO = 29;
  /** Constante que representa el sombrero. */
  public static final byte SOMBRERO_CUATRO = 30;
  /** Constante que representa la flecha. */
  public static final byte FLECHA_CUATRO = 31;
  /** Constante que representa el acento cerrado. */
  public static final byte ACENTO_CERRADO_CUATRO = 32;
  /** Constante que representa el acento abierto. */
  public static final byte ACENTO_ABIERTO_CUATRO = 33;
  /** Constante que representa la media aspa. */
  public static final byte MEDIA_ASPA_CUATRO = 34;

  // Identificador de la pieza: su valor será el de una de las constantes arriba.
  private byte IDPieza;
  // 'PanelCuadricula' al que la pieza está pegada.
  private PanelCuadricula cuadriculaActual;
  // Las coordenadas de la posición de la pieza dentro de su cuadrícula.
  private byte coordenadaX;
  private byte coordenadaY;
  // Número de veces que rota la pieza antes de volver a su posición inicial.
  private byte numeroOrientaciones;
  // Array con las coordenadas de cada cuadradillo de la pieza (respecto de 'coordenadaX' y
  // 'coordenadaY'). En la 1ª fila hay las coordenadas en el eje X, y en la 2ª, las del eje Y.
  private byte coordenadas [][];
  // Icono de los cuadradillos que forman las piezas. Será uno u otro según el diseño de las piezas.
  private ImageIcon iconoPieza;
  // Instancia de la clase con los sonidos: nos interesa para que la pieza suene al rotar, tocar fondo,...
  private Sonido sonido;

  /** Constructor. La pieza creada será una de las 35 definidas en las constantes de la clase.
      Inicializa las coordenadas de los cuadradillos mediante un 'switch ()'. Su cuadrícula no se
      inicializa por ahora, así que las coordenadas en la cuadrícula son unas por defecto.
      @param pieza byte          : Número correspondiente a la pieza a crear -usar constantes de clase.
      @param diseno String       : Cadena con la descripción del diseño de los cuadradillos de las piezas.
      @param nuevoSonido Sonido  : Objeto cuya finalidad es tocar efectos sonoros para la pieza. */
  public Pieza (byte pieza, String diseno, Sonido nuevoSonido)
  {
    IDPieza = pieza;
    sonido = nuevoSonido;
    /** Como la cuadrícula es 'null', esas coordenadas son sólo provisionales. */
    cuadriculaActual = null;
    coordenadaX = 0;
    coordenadaY = 5;

    /** Patrón: - Da con la pieza a inicializar, le da un número de orientaciones, las coordenadas de
        sus cuadradillos, y define el icono -cada pieza de un mismo color para no liar al jugador-. */
    switch (pieza)
    {
      case CUADRADO:
        numeroOrientaciones = 1;
        coordenadas = new byte [][] {{-1, 0, -1, 0}, {0, 0, 1, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Blanco.gif", "Cuadrado");
        break;
      case BARRA:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {0, 0, 0, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Rojo.gif", "Barra");
        break;
      case ESE:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{0, 1, -1, 0}, {0, 0, 1, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Azul.gif", "Ese");
        break;
      case ZETA:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-1, 0, 0, 1}, {0, 0, 1, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Verde.gif", "Zeta");
        break;
      case ELE_INVERTIDA:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 1, 1}, {0, 0, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Naranja.gif", "Ele invertida");
        break;
      case ELE:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, -1, 0, 1}, {1, 0, 0, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Amarillo.gif", "Ele");
        break;
      case TE:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 0, 1}, {0, 0, 1, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Gris.gif", "Te");
        break;
      case DESTRUCTORA:
        numeroOrientaciones = 1;
        coordenadas = new byte [][] {{0}, {0}};
        iconoPieza = Tetris.getImagen (diseno + "Destructor.gif", "Destructora");
        break;
      case UN_CUADRADO:
        numeroOrientaciones = 1;
        coordenadas = new byte [][] {{0}, {0}};
        iconoPieza = Tetris.getImagen (diseno + "Blanco.gif", "Un cuadradillo");
        break;
      case BARRA_DOS:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-1, 0}, {0, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Amarillo.gif", "Barra de dos");
        break;
      case ESCALERA_DOS:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-1, 0}, {1, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Azul.gif", "Diagonal de dos");
        break;
      case BARRA_TRES:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-1, 0, 1}, {0, 0, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Blanco.gif", "Barra de tres");
        break;
      case ESE_TRES:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 1}, {0, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Gris.gif", "Ese de tres");
        break;
      case ZETA_TRES:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 1}, {1, 0, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Lila.gif", "Zeta de tres");
        break;
      case ESCALERA_TRES:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-1, 0, 1}, {-1, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Marron.gif", "Diagonal de tres");
        break;
      case ELE_TRES:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, -1, 0}, {0, -1, -1}};
        iconoPieza = Tetris.getImagen (diseno + "Naranja.gif", "Ele de tres");
        break;
      case TE_TRES:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 1}, {-1, 0, -1}};
        iconoPieza = Tetris.getImagen (diseno + "Rojo.gif", "Te de tres");
        break;
      case OLAS_CUATRO:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {-1, 0, -1, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Turquesa.gif", "Olas");
        break;
      case OLAS_INVERTIDAS_CUATRO:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {0, -1, 0, -1}};
        iconoPieza = Tetris.getImagen (diseno + "Verde.gif", "Olas invertidas");
        break;
      case PARALELAS_CUATRO:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-1, -1, 1, 1}, {0, -1, 0, -1}};
        iconoPieza = Tetris.getImagen (diseno + "VerdePalido.gif", "Paralelas");
        break;
      case ESE_SEPARADA_CUATRO:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {-1, -1, 0, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Amarillo.gif", "Ese separada");
        break;
      case ZETA_SEPARADA_CUATRO:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {0, 0, -1, -1}};
        iconoPieza = Tetris.getImagen (diseno + "Azul.gif", "Zeta separada");
        break;
      case ESCALERA_CUATRO:
        numeroOrientaciones = 2;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {-2, -1, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Blanco.gif", "Diagonal");
        break;
      case COMA_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {1, 0, -1, -1}};
        iconoPieza = Tetris.getImagen (diseno + "Gris.gif", "Coma");
        break;
      case COMA_INVERTIDA_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {-1, -1, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Lila.gif", "Coma invertida");
        break;
      case ANGULO_RECTO_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, -1, 0, 1}, {1, 0, -1, -1}};
        iconoPieza = Tetris.getImagen (diseno + "Marron.gif", "Ángulo recto");
        break;
      case UVE_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, -1, 0, 1}, {1, 0, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Naranja.gif", "Uve");
        break;
      case UVE_INVERTIDA_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 1, 1}, {1, 0, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Rojo.gif", "Uve invertida");
        break;
      case ESE_LARGA_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {0, 0, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Turquesa.gif", "Ese larga");
        break;
      case ZETA_LARGA_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {1, 0, 0, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Verde.gif", "Zeta larga");
        break;
      case SOMBRERO_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-2, -1, 0, 1}, {1, 0, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "VerdePalido.gif", "Sombrero");
        break;
      case FLECHA_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 0, 1}, {-1, 0, 1, 0}};
        iconoPieza = Tetris.getImagen (diseno + "Lila.gif", "Flecha");
        break;
      case ACENTO_CERRADO_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 1, 1}, {-1, 0, 0, 1}};
        iconoPieza = Tetris.getImagen (diseno + "Marron.gif", "Acento cerrado");
        break;
      case ACENTO_ABIERTO_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, -1, 0, 1}, {1, 0, 0, -1}};
        iconoPieza = Tetris.getImagen (diseno + "Turquesa.gif", "Acento abierto");
        break;
      case MEDIA_ASPA_CUATRO:
        numeroOrientaciones = 4;
        coordenadas = new byte [][] {{-1, 0, 1, 1}, {-1, 0, -1, 1}};
        iconoPieza = Tetris.getImagen ("VerdePalido.gif", "Media aspa");
    }
  }

  /** Método para conocer la identidad de la pieza.
      @return byte  : El valor de la constante de clase correspondiente a esta pieza. */
  public byte getIDPieza ()
  {
    return IDPieza;
  }

  /** Método para conocer la coordenada X de la pieza en la cuadrícula.
      @return byte  : Posición de la pieza en el eje X de su cuadrícula. */
  public byte getCoordenadaX ()
  {
    return coordenadaX;
  }

  /** Método para conocer la coordenada Y de la pieza en la cuadrícula.
      @return byte  : Posición de la pieza en el eje Y de su cuadrícula. */
  public byte getCoordenadaY ()
  {
    return coordenadaY;
  }

  /** El retorno depende de si la cuadrícula de la pieza ha sido inicializada o es 'null'.
      @return boolean  : 'true' si la pieza está pegada a una cuadrícula, 'false' si no. */
  public boolean estaPegada ()
  {
    return cuadriculaActual != null;
  }

  /** Método que intenta 'pegar' una pieza a su cuadrícula. Según lo consiga o no habrá un retorno u otro.
      @param cuadr PanelCuadricula  : Cuadrícula a la que se desea pegar la pieza.
      @param centrar boolean        : 'true' si también se desea centrar la pieza por el eje Y.
      @return boolean               : 'true' si la pieza se ha pegado a la cuadrícula, y 'false si no. */
  public boolean pegar (PanelCuadricula cuadr, boolean centrar)
  {
    /** Por si la pieza estaba pegada a la cuadrícula siguiente y pasa a la de juego. */
    if (estaPegada ())
      despegar ();
    /** Se inicializa la cuadrícula de la pieza. */
    cuadriculaActual = cuadr;

    /** Se centra la pieza en su cuadrícula por el eje X, y por el eje Y según 'centrar'. */
    coordenadaX = (byte) (cuadriculaActual.getAnchura () / 2);
    if (centrar)
      coordenadaY = (byte) (cuadriculaActual.getAltura () / 2 - 1);
    else
      coordenadaY = 2;

    /** En este bucle se comprueba que la pieza no se pegará a la cuadrícula ocupando un cuadradillo
        ya relleno. Si lo hace, es que no puede pegarse a su cuadrícula, y lo refleja en el retorno. */
    for (byte i = 0; i < coordenadas [0].length; i++)
    {
      byte nuevaY = (byte) (coordenadaY + coordenadas [1][i]);
      byte nuevaX = (byte) (coordenadaX + coordenadas [0][i]);
      if (!cuadriculaActual.cuadradilloVacio (nuevaY, nuevaX))
      {
        cuadriculaActual = null;
        return false;
      }
    }

    /** Pone la pieza en la cuadrícula, y la repinta para que se vea. */
    pinta (iconoPieza);
    cuadriculaActual.repaint ();
    return true;                        // La pieza se ha 'pegado' bien.
  }

  /** Crea una tabla de 'String's con las constantes con descripciones de colores.
      @return String[]  : Array con los diferentes colores disponibles para las piezas. */
  public static String [] getColoresDisponibles ()
  {
    return new String [] {AMARILLO, AZUL, BLANCO, GRIS, LILA, MARRON, NARANJA, ROJO,
                          TURQUESA, VERDE, VERDE_PALIDO};
  }

  /** Crea una tabla de 'String's con las constantes de los diseños de pieza.
      @return String[]  : Los diseños de pieza disponibles. */
  public static String [] getDisenosDisponibles ()
  {
    return new String [] {CUADRADILLO, CIRCULILLO, ESTRELLITA, ACIDO, ENCAJE};
  }

  /** Pinta la pieza en su cuadrícula.
      @param icono ImageIcon  : Icono de los cuadradillos inidividuales que forman la piezas. */
  public void pinta (ImageIcon icono)
  {
    byte x;
    byte y;
    /** Calcula las coordenadas de cada cuadradillo en la cuadrícula, y en ella lo pega. */
    for (byte i = 0; i < coordenadas [0].length; i++)
    {
      x = (byte) (coordenadaX + coordenadas [0][i]);
      y = (byte) (coordenadaY + coordenadas [1][i]);
      cuadriculaActual.setIconoCuadradillo (y, x, icono);
    }
  }

  /** 'Despega' la pieza de su cuadrícula. */
  public void despegar ()
  {
    cuadriculaActual = null;
  }

  /** Metodo para saber si la pieza ha 'tocado fondo' (si puede moverse un espacio más abajo
      en su cuadrícula).
      @return boolean  : 'true' si la pieza puede bajar más, y false si no. */
  public boolean tocaFondo ()
  {
    /** La pieza destructora tiene un trato especial: sólo 'toca fondo' cuando llega al fondo de la
        cuadrícula; en tal caso, hay que hacerla deaparecer. */
    if (IDPieza == 7)
      if (coordenadaY == cuadriculaActual.getAltura () - 1)
      {
        pinta (null);
        cuadriculaActual.repaint ();
        return true;
      }
      else
        return false;
    /** Las piezas no 'tocan fondo' si pueden moverse abajo. */
    return !puedeMoverse (ABAJO);
  }

  /** Desplaza la pieza un espacio a la derecha en su cuadrícula, si puede. */
  public void derecha ()
  {
    /** Si la pieza es la destructora, y el cuadradillo al que va a moverse está ocupado, suena 'pum'. */
    if ((IDPieza == 7) && (coordenadaX + 1 < cuadriculaActual.getAnchura ()) &&
       (!cuadriculaActual.cuadradilloVacio (coordenadaY, (byte) (coordenadaX + 1))))
      sonido.pum ();

    /** La destructora siempre puede moverse a menos que llegue al límite de la cuadrícula.
        El resto de piezas deben pasar la función 'puedeMoverse ()'. */
    if (((IDPieza == 7) && (coordenadaX < cuadriculaActual.getAnchura () - 1)) || (puedeMoverse (DERECHA)))
    {
      pinta (null);                  // Se borra la pieza de la tabla.
      coordenadaX++;                 // La coordenada X cambia para reflejar el movimiento.
      pinta (iconoPieza);            // Se pone la pieza en su nuevo lugar.
      cuadriculaActual.repaint ();   // Se repinta la cuadrícula para que se vea el cambio.
    }
  }

  /** Desplaza la pieza un espacio a la izquierda en su cuadrícula, si puede. */
  public void izquierda ()
  {
    if ((IDPieza == 7) && (coordenadaX - 1 >= 0) &&
       (!cuadriculaActual.cuadradilloVacio (coordenadaY, (byte) (coordenadaX - 1))))
      sonido.pum ();

    if (((IDPieza == 7) && (coordenadaX > 0)) || (puedeMoverse (IZQUIERDA)))
    {
      pinta (null);
      coordenadaX--;
      pinta (iconoPieza);
      cuadriculaActual.repaint ();
    }
  }

  /** Desplaza la pieza un espacio abajo en su cuadrícula, si puede. */
  public void abajo ()
  {
    if ((IDPieza == 7) && (coordenadaY + 1 < cuadriculaActual.getAltura ()) &&
       (!cuadriculaActual.cuadradilloVacio ((byte) (coordenadaY + 1), coordenadaX)))
      sonido.pum ();

    if (((IDPieza == 7) && (coordenadaY < cuadriculaActual.getAltura () - 1)) || (puedeMoverse (ABAJO)))
    {
      pinta (null);
      coordenadaY++;
      pinta (iconoPieza);
      cuadriculaActual.repaint ();
    }
  }

  /** Deposita la pieza lo más abajo que puede de la cuadrícula. */
  public void abajoDelTodo ()
  {
    /** La destructora revienta todos los cuadradillos en la columna. */
    if (IDPieza == 7)
    {
      while (coordenadaY < cuadriculaActual.getAltura ())
      {
        pinta (null);
        coordenadaY++;
      }
      /** Hay que reajustar la coordenadaY para no dejar la pieza fuera de los límites de la cuadrícula. */
      coordenadaY--;
      return;
    }

    /** Mientras la pieza puda tirar abajo, lo hará. */
    while (puedeMoverse (ABAJO))
    {
      pinta (null);
      coordenadaY++;
      pinta (iconoPieza);
      cuadriculaActual.repaint ();
    }
  }

  /** Rota la pieza en sentido horario o anti-horario, si puede.
      @param rotacion byte  : Sentido de la rotación. Utilizar una de las 'constantes de
                              movimiento' de esta misma clase. */
  public void rota (byte rotacion)
  {
    /** Lo primero es mirar si la pieza tiene espacio para rotar. Si la pieza sólo tiene una orientación
        -como el cuadrado, o la destructora-, no tiene sentido seguir; si tiene dos orientaciones,
        la pieza sólo rotará en sentido horario; y si tiene cuatro, puede rotar en ambos sentidos. */
    if (numeroOrientaciones == 2)
    {
      if (!puedeMoverse (GIRO_HORARIO))
        return;
    }
    else if (numeroOrientaciones != 1)
    {
      if (!puedeMoverse (rotacion))
        return;
    }
    else
      return;

    pinta (null);
    if (numeroOrientaciones == 2)
      coordenadas = giroHorario ();
    else if (numeroOrientaciones != 1)
      if (rotacion == GIRO_HORARIO)
        coordenadas = giroHorario ();
      else
        coordenadas = giroAntihorario ();
    sonido.rotacion ();                      // La pieza emite un efecto sonoro.
    pinta (iconoPieza);
    cuadriculaActual.repaint ();
  }

  /** Calcula las coordenadas de la pieza tras someterse a un giro en sentido horario.
      @return byte[][]  : Coordenadas de la pieza tras rotar. */
  public byte [][] giroHorario ()
  {
    byte numeroCoordenadas = (byte) coordenadas [0].length;
    byte retorno [][] = new byte [2][numeroCoordenadas];
    /** Estos simples algoritmos recalculan la posición de cada cuadradillo.
        Sobre un papel cuadriculado es fácil ver lo que sucede. */
    for (byte i = 0; i < numeroCoordenadas; i++)
    {
      retorno [0][i] = coordenadas [1][i];
      retorno [1][i] = (byte) -coordenadas [0][i];
    }
    return retorno;
  }

  /** Calcula las coordenadas de la pieza tras someterse a un giro en sentido anti-horario.
      @return byte[][]  : Coordenadas de la pieza tras rotar. */
  public byte [][] giroAntihorario ()
  {
    byte numeroCoordenadas = (byte) coordenadas [0].length;
    byte retorno [][] = new byte [2][numeroCoordenadas];
    for (byte i = 0; i < numeroCoordenadas; i++)
    {
      retorno [0][i] = (byte) -coordenadas [1][i];
      retorno [1][i] = coordenadas [0][i];
    }
    return retorno;
  }

  /** Descubre si un cuadradillo de la cuadrícula corresponde a uno de los cuadradillos de esta pieza.
      @param y byte    : Coordenada X del cuadradillo en la cuadrícula.
      @param x byte    : Coordenada Y del cuadradillo en la cuadrícula.
      @return boolean  : 'true' si el cuadradillo de marras es parte de esta pieza, y 'false' si no. */
  public boolean estanDentro (byte y, byte x)
  {
    for (byte i = 0; i < coordenadas [0].length; i++)
      if ((x == coordenadaX + coordenadas [0][i]) && (y == coordenadaY + coordenadas [1][i]))
        return true;
    return false;
  }

  /** Descubre si la pieza puede hacer un movimiento dentro de la cuadrícula, y lo notifica en el retorno.
      @param movimiento byte  : Es preciso utilizar una de las 'constantes de movimiento' de esta clase.
      @return boolean         : 'true' si puede realizar el movimiento, y 'false' si no puede. */
  public boolean puedeMoverse (byte movimiento)
  {
    byte numeroCuadraditos = (byte) coordenadas [0].length;
    byte nuevasCoordenadas [][] = new byte [2][numeroCuadraditos];
    byte indice;

    /** Mediante este 'switch ()' se calculan las coordenadas que la pieza ocuparía en la cuadrícula
        después del movimiento. */
    switch (movimiento)
    {
      case IZQUIERDA:
        for (indice = 0; indice < numeroCuadraditos; indice++)
        {
          nuevasCoordenadas [0][indice] = (byte) (coordenadaX + coordenadas [0][indice] - 1);
          nuevasCoordenadas [1][indice] = (byte) (coordenadaY + coordenadas [1][indice]);
        }
        break;
      case DERECHA:
        for (indice = 0; indice < numeroCuadraditos; indice++)
        {
          nuevasCoordenadas [0][indice] = (byte) (coordenadaX + coordenadas [0][indice] + 1);
          nuevasCoordenadas [1][indice] = (byte) (coordenadaY + coordenadas [1][indice]);
        }
        break;
      case ABAJO:
        for (indice = 0; indice < numeroCuadraditos; indice++)
        {
          nuevasCoordenadas [0][indice] = (byte) (coordenadaX + coordenadas [0][indice]);
          nuevasCoordenadas [1][indice] = (byte) (coordenadaY + coordenadas [1][indice] + 1);
        }
        break;
      case GIRO_HORARIO:
        nuevasCoordenadas = giroHorario ();
        for (indice = 0; indice < numeroCuadraditos; indice++)
        {
          nuevasCoordenadas [0][indice] = (byte) (coordenadaX + nuevasCoordenadas [0][indice]);
          nuevasCoordenadas [1][indice] = (byte) (coordenadaY + nuevasCoordenadas [1][indice]);
        }
        break;
      case GIRO_ANTIHORARIO:
        nuevasCoordenadas = giroAntihorario ();
        for (indice = 0; indice < numeroCuadraditos; indice++)
        {
          nuevasCoordenadas [0][indice] = (byte) (coordenadaX + nuevasCoordenadas [0][indice]);
          nuevasCoordenadas [1][indice] = (byte) (coordenadaY + nuevasCoordenadas [1][indice]);
        }
    }

    /** Para que el movimiento sea posible, todos los cuadradillos deben:
          1 - Estar dentro de los confines de la cuadrícula, y
          2 - Ocupar: o un cuadradillo vacío,
                      o uno lleno que corresponda a la misma pieza. */
    for (indice = 0; indice < coordenadas [0].length; indice++)
      if (nuevasCoordenadas [1][indice] >= cuadriculaActual.getAltura () ||
         nuevasCoordenadas [0][indice] < 0 ||
         nuevasCoordenadas [0][indice] >= cuadriculaActual.getAnchura() ||
         (!estanDentro (nuevasCoordenadas [1][indice], nuevasCoordenadas [0][indice]) &&
         !cuadriculaActual.cuadradilloVacio (nuevasCoordenadas [1][indice], nuevasCoordenadas [0][indice])))
        return false;
    /** Si se ha superado el anterior bucle, es que no hay ningún impedimento para mover la pieza. */
    return true;
  }
}

¿Comentarios, sugerencias?: llopsite.at.yahoo.es | © 2005-07 Albert Lobo

Última actualización: 18-Feb-2007

Hosted by www.Geocities.ws

1