Mega Code Archive

 
Categories / JavaScript DHTML / Page Components
 

Tetris in Javascript

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>     <head>         <title>Tetr&iacute;ssimus &copy; (by Joan Alba Maldonado)</title>         <!-- (c) Tetrissimus - Programa realizado por Joan Alba Maldonado (granvino@granvino.com). Prohibido publicar, reproducir o modificar sin citar expresamente al autor original.    Tetrissimus   by Joan Alba Maldonado (100% DHTML).                 granvino@granvino.com   Prohibited to publish, reproduce or modify without maintain author's name.   Approximate date: 7 of March 2006 (fixes beyond 16 of August 2006).   Dedicated to Yasmina Llaveria del Castillo.                           -->         <script language="JavaScript1.2" type="text/javascript">             <!--                 //(c) Tetrissimus - Programa realizado por Joan Alba Maldonado (granvino@granvino.com). Prohibido publicar, reproducir o modificar sin citar expresamente al autor original.                 //Variable que activa el mapa modo debug:                 var mostrar_mapa_debug = false;                                  //Variable que guarda el primer evento del teclado, por razones de compatibilidad:                 var primer_evento = "";                                  //Se dibuja el mapa en una varialbe tipo string:                 var mapa = "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000" +                            "000000000000";                                             //Se declara la matriz para guardar el mapa:                 var mapa_matriz = new Array();                                  //El numero de columnas del mapa:                 var numero_columnas = 12;                 //El numero de filas del mapa:                 var numero_filas = 22;                                  //Variable que contiene el ancho de cada celda (tile o panel):                 var panel_width = 20;                 //Varialbe que contiene el alto de cada celda (tile o panel):                 var panel_height = 20;                 //Velocidad de caida de las piezas (entre menor, mas rapido):                 var velocidad_inicial = 1500; //Velocidad inicial.                 var velocidad = velocidad_inicial; //Velocidad que ira incrementandose (al decrementar la variable).                                  //Pizels de desplazamiento en la caida de las piezas:                 var desplazamiento_inicial = panel_height * 1; //Desplazamiento inicial.                 var desplazamiento = desplazamiento_inicial; //Desplazamiento que ira incrementandose.                          //Se realiza un bucle para guardar el mapa en la matriz:                 for (x=0; x<mapa.length; x++) { mapa_matriz[x] = mapa.substring(x, x+1); }                 //Variable que guarda el numero de la pieza actual:                 var numero_pieza = 0;                 //Variable que guarda el numero de la pieza siguiente:                 var numero_pieza_siguiente = 0;                                  //Matriz que contiene la coleccion de piezas, con su ancho, alto y color:                 var pieza = new Array();                                  //Varialbe para saber si una pieza se ha elevado verticalmente al ser rotada:                 var al_rotar_se_ha_elevado = false;                 //Variable donde se guardara el Interval del movimiento de la pieza cayendo:                 var movimiento_pieza = setInterval("", 1);                 //Variable donde se guardara el Timeout que hara que el mensaje del centro de la pantalla se oculte:                 var ocultar_mensaje = setTimeout("", 1);                 //Variable donde se guarda el numero de piezas:                 var numero_piezas = 0;                 //Variable que indica si se ha acabado el juego o todavia no:                 var game_over = false; //Todavia no se ha acabado el juego.                 //Variable que define las lineas necesarias para cambiar de nivel:                 var lineas_necesarias = 6;                                  //Variable que cuenta cuantas lineas se han realizado en el nivel actual:                 var lineas_nivel_actual = 0;                                  //Variable donde se guarda la puntuacion:                 var puntuacion = 0;                                  //Variable donde se guada el nivel:                 var nivel = 1;                                  //Contador de niveles, que cuando llega a 10 se sube el desplazamiento de las piezas (se desplazan mas espcio hacia abajo, para hacerlo mas dificil):                 var contador_niveles_desplazamiento = 0;                                  //Variable que impide el Game Over, cuando ya ha ocurrido:                 var impedir_game_over = false;                 //Matriz vacia que se utilizara para cuando se llame a mostrar_mapa:                 var guardar_mapa_anterior = new Array();                 //Funcion que crea las piezas, con su ancho, alto y color:                 function crear_piezas()                  {                     //Pieza 1:                     pieza[1] = new Array();                     pieza[1]["forma"] = "1" +                                         "1" +                                         "1" +                                         "1";                     pieza[1]["width"] = 1;                     pieza[1]["height"] = 4;                     pieza[1]["color"] = "#aaffdd";                     //Pieza 2:                     pieza[2] = new Array();                     pieza[2]["forma"] = "22" +                                         "22";                     pieza[2]["width"] = 2;                     pieza[2]["height"] = 2;                     pieza[2]["color"] = "#ffffdd";                     //Pieza 3:                     pieza[3] = new Array();                     pieza[3]["forma"] = "33" +                                         "03" +                                         "03";                     pieza[3]["width"] = 2;                     pieza[3]["height"] = 3;                     pieza[3]["color"] = "#ddaaff";                     //Pieza 4:                     pieza[4] = new Array();                     pieza[4]["forma"] = "44" +                                         "40" +                                         "40";                     pieza[4]["width"] = 2;                     pieza[4]["height"] = 3;                     pieza[4]["color"] = "#ffaadd";                     //Pieza 5:                     pieza[5] = new Array();                     pieza[5]["forma"] = "055" +                                         "550";                     pieza[5]["width"] = 3;                     pieza[5]["height"] = 2;                     pieza[5]["color"] = "#ffddff";                     //Pieza 6:                     pieza[6] = new Array();                     pieza[6]["forma"] = "660" +                                         "066";                     pieza[6]["width"] = 3;                     pieza[6]["height"] = 2;                     pieza[6]["color"] = "#aaddff";                     //Pieza 7:                     pieza[7] = new Array();                     pieza[7]["forma"] = "070" +                                         "777";                     pieza[7]["width"] = 3;                     pieza[7]["height"] = 2;                     pieza[7]["color"] = "#ffddaa";                     //Pieza 8: //                    pieza[8] = new Array();   //                  pieza[8]["forma"] = "808" + //                                        "080" + //                                        "080";     //                pieza[8]["width"] = 3;       //              pieza[8]["height"] = 3;         //            pieza[8]["color"] = "orange";                     //Se guarda el numero de piezas:                     numero_piezas = pieza.length - 1;                  }                                                   //Funcion que inicia el juego:                 function iniciar_juego()                  {                     //Se setea que aun no se ha acabado el juego:                     game_over = false;                     //Desbloquea el impedir game over:                     impedir_game_over = false;                     //Se crean las piezas:                     crear_piezas();                                          //Se setea la velocidad a la inicial:                     velocidad = velocidad_inicial;                     //Se setea el desplazamiento al inicial:                     desplazamiento = desplazamiento_inicial;                                          //Se deifne el contador de niveles que incrementa el desplazamiento, a 0:                     contador_niveles_desplazamiento = 0;                                          //Se definen las lineas del nivel actual a 0;                     lineas_nivel_actual = 0;                                          //Se define el marcador de puntuacio a 0:                     puntuacion = 0;                                          //Se define el nivel a 1:                     nivel = 1;                     //Se define el numero de pieza actual a 0 (ninguno):                     var numero_pieza = 0;                     //Se define el numero de pieza siguiente a 0 (ninguno):                     var numero_pieza_siguiente = 0;                     //Vaciar mapa (recorre la matriz, cambiando todo por 0):                     for (x=0; x<mapa_matriz.length; x++) { mapa_matriz[x] = "0"; }                                          //Se recoge el mapa en una matriz, para calcular las diferencias con este y el posterior:                     mapa_matriz_anterior = guardar_mapa_anterior;                                          //Se muestra el mapa:                     mostrar_mapa(mapa_matriz, mapa_matriz_anterior);                     //Se actualiza el marcador:                     actualizar_marcador();                                          //Se muestra el mensaje de "Comienza el juego":                     mostrar_mensaje("The game begins");                                          //Sacamos una pieza:                     sacar_pieza();                  }                 //Funcion que actualiza la matriz del mapa:                 function actualizar_mapa(numero_pieza)                  {                     //Si se ha enviado como pieza el cero, es que no hay piezas:                     if (numero_pieza == 0)                      {                         //Recorre la matriz, cambiando todo lo que no sea 0 ni X por 0:                         for (x=0; x<mapa_matriz.length; x++)                          {                             //Si no es 0 ni X, lo cambia a 0:                             if (mapa_matriz[x] != "0" && mapa_matriz[x] != "X") { mapa_matriz[x] = "0"; }                          }                      }                     //Pero si se ha enviado otro numero, mayor que cero:                     else if (numero_pieza > 0)                      {                         //Se borra la pieza del mapa:                         actualizar_mapa(0);                                                  //Se calcula en que posicion de la matriz comienza la pieza:                         matriz_posicion_x = numero_columnas - (parseInt(document.getElementById("pieza").style.left) / panel_width);                         matriz_posicion_y = parseInt(document.getElementById("pieza").style.top) / panel_height + 1;                         //Esta es la posicion inicial (la clave de la matriz) donde comienza la pieza:                         matriz_posicion_inicial = (numero_columnas * matriz_posicion_y) - matriz_posicion_x;                         //Se actualiza la matriz pintando la pieza en ella, segun la posicion: //                        for (x=0; x<mapa_matriz.length; x++)                         for (x=matriz_posicion_inicial; x<matriz_posicion_inicial+pieza[numero_pieza]["forma"].length; x++)                          {                             //Si estamos en el indice donde comienza la pieza:                             if (x == matriz_posicion_inicial)                              {                                 //El contador de columnas:                                 contador_columnas = 0;                                 //La variable que se suma para saltar una fila:                                 saltar_fila = 0;                                 for (y=0; y<pieza[numero_pieza]["forma"].length; y++)                                  {                                     //Se toma como posicion de la matriz la posicion inicial y se le suma la variable que hace saltar filas:                                     posicion_matriz_actual = x + saltar_fila;                                     //Si la posicion actual de la pieza no es un cero, se graba en la matriz:                                     if (pieza[numero_pieza]["forma"].substring(y, y+1) != "0") {mapa_matriz[posicion_matriz_actual] = pieza[numero_pieza]["forma"].substring(y, y+1); } //Se pinta la pieza.                                     //Se incrementa el contador de columnas:                                     contador_columnas++;                                     //Se incrementa la variable para saltar filas:                                     saltar_fila++;                                     //Si el contador de columnas es mayor al ancho de la pieza, se salta una fila:                                     if (contador_columnas >= pieza[numero_pieza]["width"]) { contador_columnas = 0; saltar_fila += numero_columnas - pieza[numero_pieza]["width"]; }                                  }                              }                          }                      }                  }                                 //Funcion que activa/desactiva la visualizacion del mapa en modo debug:                 function activar_desactivar_mapa_debug(modo)                  {                     //Si no se ha enviado alternar, no se alterna el estado:                     if (modo != "alternar") { var alternar_estado = mostrar_mapa_debug; }                     //...pero si se ha enviado alternar, se alterna:                     else { var alternar_estado = mostrar_mapa_debug ? false: true; }                                          //Si se ha desactivado, setea para que no se muestre el mapa y esconde el mapa:                     if (!alternar_estado) { mostrar_mapa_debug = false; document.getElementById("mapa_debug").style.visibility = "hidden"; document.formulario.casilla.checked = false; }                     //Si no (se ha activado), lo vuelve a activar y a hacer visible:                     else { mostrar_mapa_debug = true; document.getElementById("mapa_debug").style.visibility = "visible"; document.formulario.casilla.checked = true; mapa_matriz_anterior = guardar_mapa_anterior; mostrar_mapa(mapa_matriz, mapa_matriz_anterior); }                  }                 //Funcion que muestra el mapa en modo debug:                 function mostrar_mapa(mapa_matriz, mapa_matriz_anterior)                  {                     //Si se ha enviado la misma matriz actual que la anterior, sale de la funcion (no hay nada que actualizar):                     if (mapa_matriz == mapa_matriz_anterior) { return; }                     //Se setea el contador de columnas a cero:                     var columnas_contador = 0;                     //Se setea el contador de filas a cero:                     var filas_contador = 0;                     //Variable que guardara el color a utilizar en cada celda (tile o panel):                     var color_panel;                     //Se borra el mapa: //                    document.getElementById("mapa").innerHTML = ""; //                    if (mostrar_mapa_debug) { document.getElementById("mapa_debug").innerHTML = ""; } //Si esta en modo debug, tambien se borra el mapa debug.                     //Se crean las variables que guardaran la informacion del mapa:                     var mapa_bucle_temp = "";                     var mapa_debug_bucle_temp = "";                     //Se realiza un bucle para mostrar el contenido de la matriz en el espacio de debug:                      for (x=0; x<mapa_matriz.length; x++)                       {                          //Se calcula que color utilizar, segun el caracter de celda (tile o panel):                          if (mapa_matriz[x] == "X") { color_panel = "#555555"; } //Color gris oscuro (caracter X, piezas ya colocadas).                          else if (mapa_matriz[x] != 0) { color_panel = pieza[mapa_matriz[x]]["color"]; } //Color de la pieza segun su numero.                                                   //Calcular la posicion de la celda (tile o panel):                          panel_x = columnas_contador * panel_width; //Posicion horizontal.                          panel_y = filas_contador * panel_height; //Posicion vertical.                          //Se muestra la imagen en la celda, siempre que no este vacia (0) y que haya habido un cambio desde la anterior:                          if (mapa_matriz[x] != 0 && mapa_matriz[x] != mapa_matriz_anterior[x]) { mapa_bucle_temp += '<div style="background:'+color_panel+'; top:'+panel_y+'px; left:'+panel_x+'px; width:'+panel_width+'px; height:'+panel_height+'px; position:absolute; padding:0px; font-size:1px; filter:alpha(opacity=80); opacity:0.8; -moz-opacity:0.8; z-index:5000;"></div>'; }                          //Si esta activado el mapa debug, se escribe en el:                          if (mostrar_mapa_debug) { mapa_debug_bucle_temp += mapa_matriz[x]; }                          //Se incrementa el contador de columnas:                          columnas_contador++;                          //Si se alcanza el numero maximo de columnas, se baja una fila y se setea otra vez el contador a cero y se incrementa el contador de filas (si esta el mapa en modo debug, se baja una linea en este):                          if (columnas_contador == numero_columnas) { columnas_contador = 0; filas_contador++; if (mostrar_mapa_debug) { mapa_debug_bucle_temp += "<br>"; } }                       }                                            //Se vuelcan las variables en el mapa:                      document.getElementById("mapa").innerHTML = mapa_bucle_temp;                      if (mostrar_mapa_debug) { document.getElementById("mapa_debug").innerHTML = mapa_debug_bucle_temp; } //Si esta en modo debug, tambien se vuelca el mapa en modo debug.                  }                 //Funcion que saca una pieza al escenario:                 function sacar_pieza()                  {                     //Si ya ha habido game over, se sale de la funcion:                     if (impedir_game_over) { return; }                                          //Si aun no seh a escogido ninguna pieza, se escoge una aleatoriamente:                     if (numero_pieza == 0) { numero_pieza = elegir_pieza(); }                     //Si antes ya se habia escogido alguna, se setea la actual como la siguiente:                     else { numero_pieza = numero_pieza_siguiente; }                     //Ponemos el numero de la pieza siguiente, escogido aleatoriamente, en una variable:                     numero_pieza_siguiente = elegir_pieza();                                          //Se muestra la pieza siguiente:                     mostrar_pieza_siguiente(numero_pieza_siguiente);                     //Setear conforme todavia no se ha elevado verticalmente la pieza al ser rotada:                     al_rotar_se_ha_elevado = false;                     //Borrar esto:                     //numero_pieza = 1;                     //Devolver las piezas a su estado inicial:                     crear_piezas();                     //Se recoge el mapa en una matriz, para calcular las diferencias con este y el posterior:                     mapa_matriz_anterior = guardar_mapa_anterior;                     //Calcular ancho y alto de la pieza, segun el numero enviado:                     pieza_width = pieza[numero_pieza]["width"];                     pieza_height = pieza[numero_pieza]["height"];                                          //Se situa horizontalmente en el centro:                     //document.getElementById("pieza").style.left = parseInt( (numero_columnas * panel_width) / 2 - pieza_width * panel_width) + "px";                     document.getElementById("pieza").style.left = "0px";                     //Se situa verticalmente arriba:                     document.getElementById("pieza").style.top = "0px";                     mover_pieza(0, 0);                     //Se actualiza el mapa:                     //actualizar_mapa(numero_pieza);mostrar_mapa_debug(mapa_matriz);                                          //Se muestra el mapa:                     mostrar_mapa(mapa_matriz, mapa_matriz_anterior);                     //Elimina el movimiento de la pieza cayendo, por si aun existia:                     clearInterval(movimiento_pieza);                     //Crea el movimiento de la pieza cayendo:                     movimiento_pieza = setInterval("mapa_matriz_anterior = guardar_mapa_anterior; mover_pieza('mantener', parseInt(document.getElementById('pieza').style.top) + desplazamiento); mostrar_mapa(mapa_matriz, mapa_matriz_anterior);", velocidad);                  }                 //Funcion que elige una pieza aleatoriamente:                 function elegir_pieza()                  {                     //Variable que escoge un numero aleatorio entre 1 y 8:                     var numero_aleatorio = parseInt(Math.random() * numero_piezas) + 1;                                          //Retorna el numero escogido de la pieza:                     return numero_aleatorio;                  }                 //Funcion que mueve la pieza segun las coordenadas enviadas:                 function mover_pieza(posicion_x, posicion_y)                  {                     //Si ya ha habido game over, se sale de la funcion:                     if (impedir_game_over) { return; }                                          //Si se ha enviado mantener posicion horizontal, no mover la pieza (conservar la X de esta):                     if (posicion_x == "mantener") { posicion_x = parseInt(document.getElementById("pieza").style.left); }                                          //Variable para saber si la pieza ha tocado fondo:                     var ha_tocado_fondo = false;                     //Si la pieza esta en el limite de abajo, situa la pieza lo maximo posible hacia abajo y se setea la variable ha_tocado_fondo a true:                     if (posicion_y > panel_height * numero_filas - pieza[numero_pieza]["height"] * panel_height) { posicion_y = panel_height * numero_filas - pieza[numero_pieza]["height"] * panel_height; ha_tocado_fondo = true; }                     //Si la pieza esta en el limite izquierdo, situa la pieza lo maximo posible hacia la izquierda:                     if (posicion_x <= 0) { posicion_x = 0; }                     //Si la pieza esta en el limite derecho, situa la pieza lo maximo posible hacia la derecha:                     if (posicion_x + panel_width * pieza[numero_pieza]["width"] > panel_width * numero_columnas) { posicion_x = panel_width * numero_columnas - pieza[numero_pieza]["width"] * panel_width; }                                          //Variables que impiden el movimiento horizontal si a la izquierda o a la derecha de la pieza hay otra ya colocada:                     impedir_movimiento_derecho = false;                     impedir_movimiento_izquierdo = false;                     //Realizar un bucle en la matriz:                     for (x=0; x<mapa_matriz.length; x++)                      {                         //Si la posicion actual de la matriz contiene un caracter que no es 0 ni X, contiene una pieza:                         if (mapa_matriz[x] != "0" && mapa_matriz[x] != "X")                          {                                                          //Si existe un caracter a la derecha del actual (no excede el tama??e la matriz):                             if (x + 1 <= mapa_matriz.length)                              {                                 //Si el caracter que hay a la derecha es una X, impedir movimiento horizontal:                                 if (mapa_matriz[x+1] == "X") { impedir_movimiento_derecho = true; } //Se impide movimiento horizontal hacia la derecha.                              }                                                          //Si existe un caracter a la izquierda del actual (no es menor a 0):                             if (x - 1 >= 0)                              {                                 //Si el caracter que hay a la izquierda es una X, impedir movimiento horizontal:                                 if (mapa_matriz[x-1] == "X") { impedir_movimiento_izquierdo = true; } //Se impide movimiento horizontal hacia la izquierda.                              }                          }                      }                                          //Si la posicion horizontal es hacia la izquierda y no esta impedida o es a la derecha y tampoco esta impedida, mueve la pieza horizontalmente:                     posicion_x_actual = parseInt(document.getElementById("pieza").style.left);                     if (posicion_x_actual > posicion_x && !impedir_movimiento_izquierdo || posicion_x_actual < posicion_x && !impedir_movimiento_derecho)                      {                         document.getElementById("pieza").style.left = posicion_x + "px"; //Se situa la pieza en la posicion horizontal dada.                      }                                          //Se situa la pieza en la posicion vertical dada:                                         document.getElementById("pieza").style.top = posicion_y + "px";                                          //Se actualiza el mapa con la nueva posicion de la pieza:                     actualizar_mapa(numero_pieza);                     //Calcular colision:                     var ha_colisionado = calcular_colision();                     //Si la posicion vertical de la pieza la situa abajo del todo, se convierte todo el mapa que no sea 0 a X:                     if (ha_tocado_fondo || ha_colisionado)                      {                         //Elimina el movimiento de la pieza cayendo, por si existia anteriormente:                         //clearInterval(movimiento_pieza);                         //Da 1 punto:                         puntuacion += 1;                                      //Se setea todo lo que haya en el mapa como X (ya colocado):                         for (x=0; x<mapa_matriz.length; x++) { if (mapa_matriz[x] != "0") { mapa_matriz[x] = "X"; } }                         //Se hace bajar la pieza un panel, para que quede bien al pausar el juego:                         document.getElementById("pieza").style.top = parseInt(document.getElementById("pieza").style.top) + panel_height + "px";                         actualizar_mapa();                         mostrar_mapa(mapa_matriz, mapa_matriz_anterior);                                                  //Calculamos si se ha llegado arriba del todo y se acaba el juego:                         hay_game_over = calcular_game_over();                         //Se saca una pieza:                         if (!hay_game_over) { sacar_pieza(); }                      }                                          //Calcular si se ha hecho linea:                     calcular_linea();                                          //Se muestra el mapa: //                    mostrar_mapa(mapa_matriz); //                    mostrar_mapa(mapa_matriz, mapa_matriz_anterior);                                       }                                  //Funcion que calcula si una pieza ha chocado con otra (poniendose encima):                 function calcular_colision()                  {                     //Variable que calcula si ha colisionado o no:                     var ha_colisionado = false;                                          //Realizar bucle en la matriz, buscar caracteres que no sean 0 ni X y calcular si justo debajo tienen una X:                     for (x=0; x<mapa_matriz.length; x++)                      {                         //Si la posicion actual de la matriz contiene un caracter que no es 0 ni X, contiene una pieza:                         if (mapa_matriz[x] != "0" && mapa_matriz[x] != "X")                          {                                                          //Si existe un caracter debajo del actual (no excede el tama??e la matriz):                             if (x + numero_columnas <= mapa_matriz.length)                              {                                 //Si el caracter que hay debajo es una X, ha colisionado:                                 if (mapa_matriz[x+numero_columnas] == "X") { ha_colisionado = true; break; } //Ha habido colision y sale del bucle.                              }                          }                      }                     //Si ha colisionado:                     if (ha_colisionado)                      {                         //Retorna true:                         return true;                      }                     //...y si no:                     else { return false; } //Retorna false;                  }                 //Funcion que calcula si ha habido linea:                 function calcular_linea()                  {                     //Calcular si ha habido linea y calcular cuantas:                     var columnas_contador = 0;                     if (!numero_de_lineas) { var numero_de_lineas = 0; }                     var ha_habido_linea = false;                     var hay_linea = true;                     for (var x=0; x<mapa_matriz.length; x++)                      {                         columnas_contador++;                         if (mapa_matriz[x] != "X") { hay_linea = false; }                         if (columnas_contador == numero_columnas)                          {                             if (hay_linea)                              {                                 //Cambiar las X de la linea por 0:                                 for (var y=x-numero_columnas+1; y<=x; y++)                                  {                                     mapa_matriz[y] = "0";                                  }                                                                  //Bajar lineas:                                 se_ha_bajado_linea = hacer_caer_cuadros();                                                                  //Volver a llamar a la funcion recursivamente si se ha bajado alguna linea, para ver si al bajar las piezas colocadas ha habido mas lineas: //                                if (se_ha_bajado_linea) { calcular_linea(); }                                 //calcular_linea();                                                                  //Incrementar el contador de lineas:                                 numero_de_lineas++;                                 ha_habido_linea = true;                                                                 }                             columnas_contador = 0;                             hay_linea = true;                          }                         //actualizar_mapa(numero_pieza);                                               }                                                              //Si ha habido linea, dar puntos segun cuantas lineas ha haya habido:                     dar_puntos(numero_de_lineas);                                       }                 //Funcion que hace caer los cuadros (X) cuando debajo no tienen nada (0):                 function hacer_caer_cuadros(posicion_final)                  {                      //Todavia no se ha bajado ninguna linea:                      se_ha_bajado_linea = false;                                          //Calcula si la linea esta en el aire o no:                     var esta_en_el_aire = true;                                   //Bucle que va de arriba a abajo, haciendo caer las piezas: //                     for (z=mapa_matriz.length-numero_columnas; z>=numero_columnas+1; z-=numero_columnas)                      for (z=mapa_matriz.length-numero_columnas; z>=numero_columnas; z-=numero_columnas)                       { //                        alert(z);                         //Calcula si la linea esta en el aire o no:                         esta_en_el_aire = true;                                                  //Comprueba que la linea este en el aire:                         for (k=z; k<=z+numero_columnas-1; k++) { if (k > mapa_matriz.length || mapa_matriz[k] != "0" || z > numero_columnas && mapa_matriz[k-numero_columnas] != "X" && mapa_matriz[k-numero_columnas] != "0") { esta_en_el_aire = false; } }                                                  //Si esta en el aire, se baja la linea:                         if (esta_en_el_aire)                          { //                        alert(z);                            for (k=z; k<=z+numero_columnas-1; k++)                              {                                   //Se replica la pieza en el cuadro de abajo:                                   mapa_matriz[k] = mapa_matriz[k-numero_columnas];                                   //Se borra la pieza en el cuadro actual:                                   mapa_matriz[k-numero_columnas] = "0";                                   //Setear conforme se ha bajado una linea:                                   se_ha_bajado_linea = true;                                    //                        mostrar_mapa(mapa_matriz, mapa_matriz_anterior);                              }                             //Se setea como que ya no estan en el aire:                             esta_en_el_aire = false;                           }                                               }                     if (se_ha_bajado_linea) { return true; }                     else { return false; }                  }                 //Funcion que rota la pieza:                 function rotar_pieza(direccion)                  {                     //Se inviert el ancho y el alto de la pieza:                     var width_original = pieza[numero_pieza]["width"]; //El width anterior.                     var height_original = pieza[numero_pieza]["height"]; //El height anterior.                     pieza[numero_pieza]["width"] = height_original; //El nuevo width es el height.                     pieza[numero_pieza]["height"] = width_original; //El numero height es el width anterior.                                          //Se setea la matriz donde se guardara la nueva pieza:                     var nueva_pieza_matriz = new Array(); //Se declara la matriz.                                          //Variables que serviran para realizar los bucles:                     var contador1 = 0;                     var contador2 = height_original;                     var contador3 = width_original;                                         //Si se ha de rotar la pieza a la derecha:                     if (direccion == "derecha")                      {                         //Se realiza un bucle por la pieza actual, y se guarda rotada a la derecha en la nueva pieza:                         for (x=0; x<pieza[numero_pieza]["forma"].length; x++)                          {                             //Formula que yo mismo descubri, despues de mucho pensar x):                             var formula = (contador1 * height_original) + (contador2  - 1);                             nueva_pieza_matriz[formula] = pieza[numero_pieza]["forma"].substring(x,x+1);                             contador1++;                             contador3--;                             if (contador3 == 0) { contador3 = width_original; contador1 = 0; contador2--; }                          }                      }                                         //...O si se ha de rotar la pieza hacia la izquierda (o tres veces hacia la derecha):                     else if (direccion == "izquierda")                      {                         //Se realiza un bucle por la pieza actual, y se guarda rotada a la derecha en la nueva pieza:                         for (x=pieza[numero_pieza]["forma"].length; x>0; x--)                          {                             //Formula que yo mismo descubri, despues de mucho pensar x):                             var formula = (contador1 * height_original) + (contador2  - 1);                             nueva_pieza_matriz[formula] = pieza[numero_pieza]["forma"].substring(x-1,x);                             contador1++;                             contador3--;                             if (contador3 == 0) { contador3 = width_original; contador1 = 0; contador2--; }                          }                      }                     //Posicion vertical de la pieza                                          posicion_y = parseInt(document.getElementById("pieza").style.top);                                          //Calcular si al rotarse la pieza va a estar encima de alguna X, entonces moverla a un lugar cercano (hasta en posicion horizontal - ancho pieza, posicion horizontal + ancho pieza, posicion vertical + alto pieza o en posicion vertical - alto pieza) con 0.                     //Calcular si la pieza va a chocar al rotarse con alguna pieza inferior o lateral:                     //* Si hay piezas debajo, elevar la pieza un cuadro.                     //* Si hay piezas al lado, mover la pieza al lado contrario.                     //* Si la nueva posicion calculada no es posible (hay X en lo que va a ocupar), no rotar la pieza y salir de la funcion.                                          //Si la pieza va a estar demasiado cerca del borde inferior (abajo) o de alguna pieza inferior, se sube un poco hacia arriba:                     if (posicion_y + pieza[numero_pieza]["height"] * panel_height >= numero_filas * panel_height) { posicion_y -= parseInt(pieza[numero_pieza]["height"] / 2 + 1) * panel_height; al_rotar_se_ha_elevado = true; }                     //...y si no, y ya ha sido elevada anteriormente al rotarse, se vuelve a bajar:                     else if (al_rotar_se_ha_elevado) { posicion_y += parseInt(pieza[numero_pieza]["width"] / 2 + 1) * panel_height; }                     //Variable donde se guardara la forma de la nueva pieza rotada:                     var nueva_pieza = "";                     //Se realiza un bucle para introducir lo que hay en la matriz en una variable de texto plano:                     for (x = 0; x<nueva_pieza_matriz.length; x++)                      {                         nueva_pieza += nueva_pieza_matriz[x];                      }                     //Se setea la forma de la pieza actual a la nueva pieza que hemos rotado:                     pieza[numero_pieza]["forma"] = nueva_pieza;                                          //Retorna la posicion vertical de la pieza:                     return posicion_y;                  }                 //Funcion que da puntos, segun un numero de lineas enviado:                 function dar_puntos (numero_lineas)                  {                     //Variable donde se guardara el mensaje a mostrar, si es necesario:                     var mensaje = "";                                          //Dar puntos, segun las lineas:                     if (numero_lineas == 4) { puntuacion += 400; mensaje = "Tetris"; } //Se han hecho 4 lineas (tetris).                     else if (numero_lineas == 3) { puntuacion += 300; mensaje = "Triple"; } //Se han hecho 3 lineas (triple).                     else if (numero_lineas == 2) { puntuacion += 200; mensaje = "Double"; } //Se han hecho 2 lineas (doble).                     else if (numero_lineas == 1) { puntuacion += 100; mensaje = "Single"; } //Se ha hecho 1 linea (simple).                                                              //Mostrar en medio de la pantalla cuantas lineas se han hecho, siempre que se haya hecho alguna, y suma al contador de lineas:                     if (mensaje != "") { mostrar_mensaje(mensaje); lineas_nivel_actual++; }                                          //Si elas lineas del nivel actual alcanza o supera las necesarias para pasar de nivel, se llama a la funcion de pasar de nivel:                     if (lineas_nivel_actual >= lineas_necesarias)                      {                         pasar_nivel();                      }                                          //Actualizar marcador:                     actualizar_marcador();                  }                                   //Funcion que pasa de nivel cada X lineas:                 function pasar_nivel()                  {                     //Si esta habiendo game over, salir de la funcion:                     if (impedir_game_over) { return; }                                          //Calcular si el numero de lineas realizadas en el nivel actual es igual o supera a lineas_necesarias, y entonces cambia de nivel:                     if (lineas_nivel_actual >= lineas_necesarias)                      {                         //Se define el contador de lineas de cada nivel a cero:                         lineas_nivel_actual = 0;                         //Se incrementa el contador de niveles, que al llegar a 10 incrementa el desplazamiento de la pieza:                         contador_niveles_desplazamiento++;                         //Se suma un nivel:                         nivel++;                                                  //Se sube la velocidad inicial (ahora la pieza tardara 50 milisegundos menos en caer hacia abajo en cada movimiento):                         if (velocidad_inicial - 25 >= 0) { velocidad -= 25; }                                                  //Si el contador de niveles llega a 10, se sube el desplazamiento de la pieza (ahora la pieza se desplazara mas en cada caida):                         if (contador_niveles_desplazamiento >= 10 && desplazamiento_inicial <= panel_height * numero_filas) { desplazamiento += panel_height; contador_niveles_desplazamiento = 0; }                                                  //Se dan 1000 puntos:                         puntuacion += 1000;                      }                     //Mostrar en pantalla que se ha pasado de nivel:                     mostrar_mensaje("Welcome to level "+nivel);                                          //Actualizar marcador:                     actualizar_marcador();                  }                 //Funcion que actualiza el marcador:                 function actualizar_marcador()                  {                     //Actualiza el marcador (barra de estado):                     document.getElementById("estado").innerHTML = "&nbsp; Level: "+nivel+" | Score: "+puntuacion;                                          if (game_over) { document.getElementById("estado").innerHTML += " | [Game Over]"; }                  }                 //Funcion que muestra la pieza siguiente:                 function mostrar_pieza_siguiente(numero_pieza_siguiente)                  {                     //Variable que contendra la pieza siguiente pintada (los div):                     var pieza_pintada = "";                     //Posicion de la pieza en el cuadro de "pieza siguiente":                     posicion_y = panel_height; //Posicion vertical inicial.                     posicion_x = panel_width; //Posicion horizontal inicial.                                          //Contador de columnas, para saber cuando bajar la celda:                     var contador_columnas = 0;                     //Se realiza un bucle hasta cumplir el numero de celdas que tenga la pieza:                     for (x=0; x<pieza[numero_pieza_siguiente]["forma"].length; x++)                      {                         //Se coge el color de la pieza:                         color_pieza = pieza[numero_pieza_siguiente]["color"];                         //Si la celda actual no esta vacia (0), se pinta (se crea un div con las posiciones correspondientes):                         if (pieza[numero_pieza_siguiente]["forma"].substring(x,x+1) != "0") { pieza_pintada += '<div style="background:'+color_pieza+'; left:'+posicion_x+'; top:'+posicion_y+'; width:'+panel_width+'; height:'+panel_height+'; font-size:1px; position:absolute; z-index:5001;"></div>'; }                         //Se incrementa la posicion horizontal:                         posicion_x += panel_width;                         //Se incrementa una columna:                         contador_columnas++;                         //Si se ha llegado al fin de las columnas, se baja una fila y se setea las columnas a 0:                         if (contador_columnas >= pieza[numero_pieza_siguiente]["width"]) { contador_columnas = 0; posicion_y += panel_height; posicion_x = panel_width; }                      }                                          //Se muestra la ficha que hemos "pintado":                     document.getElementById("pieza_siguiente").innerHTML = "Next piece: "+pieza_pintada;                  }                                  //Funcion que muestra un mensaje en medio de la pantalla, durante un tiempo:                 function mostrar_mensaje(mensaje)                  {                     //Se borra el Timeout anterior por si ya existia de antes:                     clearTimeout(ocultar_mensaje);                     //Se pone el teto en el recuadro:                     document.getElementById("mensaje").innerHTML = mensaje;                     //Se hace visible el recuadro:                     document.getElementById("mensaje").style.visibility = "visible";                     //Se esconde el recuadro a los 1500 milisegundos (un segundo y medio):                     ocultar_mensaje = setTimeout("document.getElementById('mensaje').style.visibility = 'hidden';", 1500);                  }                                 //Funcion que calcula si se ha llegado al tope de la pantalla, y si es asi da GameOver:                 function calcular_game_over()                  {                     //Si ya se ha ejecutado game over, sale de la funcion:                     if (impedir_game_over) { return; }                                          //Variable que definira si se ha llegado arriba del todo o no:                     var se_ha_llegado_arriba = false;                                          //Calcular si se ha llegado al fin del mapa, con un bucle:                     for (x=0; x<numero_columnas; x++)                      {                         //Si arriba del mapa hay otra cosa que no es un 0, se ha llegado arriba:                         if (mapa_matriz[x] != "0") { se_ha_llegado_arriba = true; }                      }                                          //Si ha llegado arriba del todo, hace el game over y luego inicia otro juego nuevo:                     if (se_ha_llegado_arriba)                      {                         //Setea el game over:                         game_over = true;                                              //Actualizar marcador:                         actualizar_marcador();                                              //Se muestra el mensaje:                         mostrar_mensaje("Game Over");                                              //Impedir Game Over:                         impedir_game_over = true;                         //Se alerta:                         alert("Game Over");                                              //Se comienza el juego en 2 segundos:                         setTimeout("iniciar_juego();", 2000);                                               return true;                      }                                          else { return false; } //No ha habido game over.                                       }                 //Funcion que recoge el mapa en la variable mapa_matriz_anterior()                 function guardar_mapa_anterior()                  {                     var mapa_matriz_anterior = new Array();                     for (x=0; x<mapa_matriz.length; x++)                      {                         mapa_matriz_anterior[x] = mapa_matriz[x];                      }                     return mapa_matriz_anterior;                  }                 //Funcion que captura la tecla pulsada y realiza la funcion necesaria:                 function pulsar_tecla(e, evento_actual)                  {                     //Si esta en pausa el juego, se sale de la funcion:                     if (!movimiento_pieza) { return; }                     //Se recoge el mapa en una matriz, para calcular las diferencias con este y el posterior:                     mapa_matriz_anterior = guardar_mapa_anterior;                     //Si el primer evento esta vacio, se le introduce como valor el evento actual (el que ha llamado a esta funcion):                     if (primer_evento == "") { primer_evento = evento_actual; }                     //Si el primer evento no es igual al evento actual (el que ha llamado a esta funcion), se vacia el primer evento (para que a la proxima llamada entre en la funcion) y se sale de la funcion:                     if (primer_evento != evento_actual) { primer_evento = ""; return; }                     //Capturamos la tacla pulsada, segun navegador:                     if (e.keyCode) { var unicode = e.keyCode; }                     //else if (event.keyCode) { var unicode = event.keyCode; }                     else if (window.Event && e.which) { var unicode = e.which; }                     else { var unicode = 40; } //Si no existe, por defecto se utiliza la flecha hacia abajo.                     //Se obtiene la posicion actual de la pieza:                     posicion_x = parseInt(document.getElementById("pieza").style.left); //Posicion horizontal.                     posicion_y = parseInt(document.getElementById("pieza").style.top); //Posicion vertical.                     //Si se pulsa la flecha hacia abajo, se suman 20 pixels verticales:                     if (unicode == 40) { posicion_y += 20; }                     //...y si se pulsa la flecha hacia la derecha, se suman 20 pixels horizontales:                     else if (unicode == 39) { posicion_x += 20; }                     //...y si se pulsa la flecha hacia la izquierda, se restan 20 pixels horizontales:                     else if (unicode == 37) { posicion_x -= 20; }                     //...y si se pulsa flecha arriba (38), control (17), intro (13) o . (190), se rota la pieza hacia la derecha:                     else if (unicode == 38 || unicode == 17 || unicode == 13 || unicode == 190) { posicion_y = rotar_pieza("derecha"); }                     //...y si se pulsa shift (16), espacio (32), 0 (96) o insert (45), se rota la pieza hacia la izquierda:                     else if (unicode == 16 || unicode == 32 || unicode == 96 || unicode == 45) { posicion_y = rotar_pieza("izquierda"); }                                          //Se mueve la pieza:                     mover_pieza(posicion_x, posicion_y);                     //Se muestra el mapa:                     mostrar_mapa(mapa_matriz, mapa_matriz_anterior);                  }                 //Funcion que pausa o reanuda el juego:                 function pausar_reanudar_juego()                  {                     //Si la pieza no esta moviendose, se reanuda:                     if (!movimiento_pieza) { movimiento_pieza = setInterval("mapa_matriz_anterior = guardar_mapa_anterior; mover_pieza('mantener', parseInt(document.getElementById('pieza').style.top) + desplazamiento); mostrar_mapa(mapa_matriz, mapa_matriz_anterior);", velocidad); mostrar_mensaje("Game resumed"); document.getElementById("pausar").innerHTML = "[ Pause ]"; document.getElementById("pausar").title = "Click here to pause game"; }                     //...pero si ya esta moviendose, se pausa:                     else { clearInterval(movimiento_pieza); movimiento_pieza = false; document.getElementById("mensaje").innerHTML = "Game paused"; document.getElementById("mensaje").style.visibility = "visible"; setTimeout('document.getElementById("mensaje").innerHTML = "Game paused"; document.getElementById("mensaje").style.visibility = "visible";', 1500); document.getElementById("pausar").innerHTML = "[ Resume ]"; document.getElementById("pausar").title = "Click here to resume game"; }                  }             //-->         </script>     </head>     <body onLoad="javascript:activar_desactivar_mapa_debug('mantener'); iniciar_juego();" onKeyDown="javascript:pulsar_tecla(event, 'onkeypress');" onKeyPress="javascript:pulsar_tecla(event, 'onkeydown');" bgcolor="#eeeeff" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">         <!-- Zona de juego: -->         <div id="zona_juego" style="background:#555555; color:#555555; visibility:visible; top:10px; left:20px; width:244px; height:442px; position:absolute; padding:0px; border:0px; font-size:1px; z-index:1;">             <!-- Mapa: -->             <div id="mapa" style="background:url('fondo.gif'); color:#000000; visibility:visible; top:0px; left:2px; width:242px; height:442px; position:absolute; padding:0px; border:0px; font-size:1px; z-index:2;"></div>             <!-- Fin de Mapa. -->             <!-- Pieza: -->             <div id="pieza" style="background:transparent; color:#ffffff; visibility:hidden; position:absolute; left:0px; top:0px; font-size:1px; z-index:3;"></div>             <!-- Fin de Pieza. -->             <!-- Mensaje: -->             <div id="mensaje" style="background:#cc0000; color:#ffffff; visibility:visible; top:210px; left:11px; width:225px; height:20px; position:absolute; padding:0px; border:0px; font-size:12px; line-height:14px; font-family:verdana; font-weight:bold; filter:alpha(opacity=80); opacity:0.8; -moz-opacity:0.8; text-align:center; z-index:4;">                 Loading...             </div>             <!-- Fin de Mensaje. -->         </div>         <!-- Fin de Zona de juego. -->         <!-- Pieza siguiente: -->         <div id="pieza_siguiente" style="background:#102020; color:#ffffff; visibility:visible; top:10px; left:270px; width:120px; height:120px; position:absolute; padding:0px; border:0px; font-size:12px; font-weight:bold; text-align:center; z-index:5;">             Loading...         </div>         <!-- Fin de Pieza siguiente. -->         <!-- Barra de estado: -->         <div id="estado" style="background:#000077; color:#ffffff; visibility:visible; top:453px; left:20px; width:244px; height:20px; position:absolute; padding:0px; border:0px; font-size:10px; line-height:18px; font-family:verdana; font-weight:bold; z-index:6;">             &nbsp; Loading...         </div>         <div id="autor" style="background:transparent; color:#aa0000; visibility:visible; top:473px; left:20px; width:244px; height:20px; position:absolute; padding:0px; border:0px; font-size:9px; line-height:15px; font-family:verdana; font-weight:bold; text-align:center; z-index:7;">             Tetr&iacute;ssimus&copy; by Joan Alba Maldonado         </div>         <!-- Fin de Barra de estado. -->         <!-- Mapa en modo debug: -->         <div id="mapa_debug" style="top:135px; left:270px; background:cyan; visibility:hidden; color:#000066; position:absolute; padding:4px; border:0px; text-align:center; font-family:arial; font-size:12px; z-index:8;">         </div>         <div id="opcion_debug" style="visibility:visible; top:470px; left:270px; padding:0px; background:cyan; color:#000066; position:absolute; padding:4px; border:0px; text-align:center; font-weight:bold; font-family:arial; font-size:12px; line-height:20px; z-index:9;">             <form name="formulario" id="formulario" style="display:inline;">                 <label for="casilla" title="Shows map on debug mode (text)" accesskey="m">                     <input type="checkbox" name="casilla" id="casilla" onClick="javascript:activar_desactivar_mapa_debug('alternar');" checked> Show debug mode <u>m</u>ap &nbsp;                 </label>             </form>         </div>         <!-- Fin de Mapa en modo debug. -->         <!-- Boton de Pausa: -->         <div id="pausar" style="top:450px; left:360px; background:transparent; visibility:visible; color:#660000; position:absolute; padding:4px; border:0px; text-align:center; font-family:arial; font-size:12px; cursor: pointer; cursor: hand; z-index:8;" onClick="javascript:pausar_reanudar_juego();" title="Click here to pause game">             [ Pause ]         </div>         <!-- Fin de Boton de Pausa. -->         <!-- Informacion: -->         <div style="left:400px; top:10px; height:0px; position:absolute; border:0px; padding:0px; background:transparent; color:#333333; text-align:left; line-height:20px; text-decoration:none; font-family:verdana; font-size:12px; z-index:10;">             &copy; <b>Tetr&iacute;ssimus</b> 0.15a             <br>             &nbsp;&nbsp;by <i>Joan Alba Maldonado</i> (<a href="mailto:granvino@granvino.com;">granvino@granvino.com</a>) &nbsp;<sup>(100% DHTML)</sup>             <br>&nbsp;&nbsp;- Prohibited to publish, reproduce or modify without maintain author's name.             <br>             &nbsp;&nbsp;<tt>* Use the keyboard arrow to move, and up arrow (also spacebar, control,             <br>             &nbsp;&nbsp;  shift or return) to rotate piece. Under Opera, leave the mouse cursor             <br>             &nbsp;&nbsp;  over game zone.</tt>             <br>             &nbsp;&nbsp;<i>Dedicated to Yasmina Llaveria del Castillo</i>         <!-- Fin de Informacion. -->     </body> </html>