viernes, 20 de febrero de 2015

WEB_P2


Rompecabezas URJC

Continuamos con la segunda parte de mi tutorial sobre como hacer un juego utilizando javascrip, html y css. Vamos a mejorar la versión anterior del rompecabezas que tenéis publicado en la primera parte de Rompecabezas URJC.
En esta publicación vamos a mejorar el rompecabezas en 5 PASOS.
PASO 0: ¿Qué tenemos y qué vamos a hacer?
    En resumen tenemos una tabla básica de html, donde en cada celda hemos introducido una imagen y gracias a la interactividad que ofrece javascrip somos capaces de mover fichas adyacentes a la imagen en blanco.
    Objetivos en este hito2 del rompecabezas URJC:
  1. Cronometro: Realizar un cronometro con html, css y javascrip, en cuanto demos al botón "START".
  2. Juego Terminado: Realización de una función javascrip que nos permita saber si hemos completado el puzzle.
  3. Carrusel: Tener un listado de puzzles para poder cambiar dinámicamente. lo explico mas detalladamente en el PASO 3.
  4. Cookie: Añadir una acreditación a cada usuario que acceda a la pagina con un tiempo de expiración de una hora.
PASO 1: Cronometro.

   Queremos llevar el tiempo que tarda un usuario en realizar nuestro rompecabezas. para ello vamos a utilizar varias variables globales como:


var cronometro = 0; //Tiempo inicial

var visor;

var marcha = 0;

Las cuales vamos a utilizar en las siguientes funciones:

    La función StartClock.

function Startclock() {
    visor = document.getElementById("reloj"); //localizar pantalla del reloj 
    inicial = new Date(); //fecha inicial (en el momento de pulsar)
    elcrono = setInterval(tiempo,10); //poner en marcha el temporizador.
    marcha = 1;
}

*Nota: StartClock es la encargada de poner en funcionamiento nuestro cronometro.

    La función tiempo:


function tiempo() { 

    actual=new Date(); //fecha a cada instante

    cronometro= actual - inicial; //milisegundos transcurridos.

    cr=new Date(); //pasamos el num. de milisegundos a objeto fecha. 
    cr.setTime(cronometro); 
    sg=cr.getSeconds(); //segundos
    mn=cr.getMinutes(); //minutos
    ho=cr.getHours()-1; //horas
    //poner siempre 2 cifras en los números
    if (sg<10) {sg="0"+sg;}
    if (mn<10) {mn="0"+mn;}
    //llevar resultado al visor.
    visor.innerHTML= ho+" : "+mn+" : "+sg;
}

*Nota: Esta función es la encargada de modificar el documento html.

    Con estas dos funciones seremos capaces de activar el cronometro cada vez que empecemos un rompecabezas. 

    En este PASO 1 también voy a explicar como para y reiniciar el reloj, que serán dos funciones que se disparan cuando completemos el puzzle y cuando cambiemos de un puzzle a otro.

   La función StopClock.

function StopClock() {
     clearInterval(elcrono); //parar el crono
}

   La función ResetClock.

function ResetClock () {
  visor = document.getElementById("reloj");
  if (marcha == 1){
    clearInterval(elcrono);
    marcha = 0;
  }
  cronometro = 0;
  visor.innerHTML= "0 : 00 : 00";

}

    Para tener presencia en nuestra web solo nos faltaría añadir tres etiquetas button (START, REST, STOP) y una etiqueta div con identificador a nuestro documento html.

<button onClick="StartClock()">START</button>
<button onClick="ResetClock()">RESET</button>
<button onClick="StopClock()">STOP</button>
<div id="reloj">
       0 : 00 : 00
 </div>

   Si implementamos todo esto en nuestro antiguo código, conseguiríamos la siguiente apariencia.
También recordar, que podemos dar estilo a nuestro reloj, utilizando las hojas css, por ejemplo:

#reloj {
    width: 20%;
    height: 10%
    border: 1px solid black;
    font: bold 1em europa, arial;
    text-align: center;
    margin: auto;
    background-color: yellow;
    border-radius: 10px; 
}
    PASO 2: Juego Terminado. 

   Vamos ahora a implementar una función que nos permita saber si hemos completado correctamente el rompecabezas.

function JuegoTerminado(){
  var list = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,"blanco"];
  var listaactual = [];
  index = 0;
  for (i=1; i < 5; i++) {
    for (j=1; j < 5; j++) {
      identy = "F" + i.toString() + "C" + j.toString();
      Pieza = document.getElementById(identy).src; 
      Ficheros = Pieza.split('/');
      x = Ficheros.length - 1;
      imagen = Ficheros[x].split('.');
      if (imagen[0] != "blanco"){
        Ficha = parseInt(imagen[0]);
      }else{
        Ficha = imagen[0];
      }
      listaactual.push(Ficha);
      index++;
    }
  }
  iguales = true;
  for (i = 0; i < listaactual.length; i++){
    if (listaactual[i] != list[i]) {
      iguales = false;
    }
  }
  if (iguales != false) {
    alert("ROMPE COMPLETADO");
    StopClock(); 
  }
  }

    Si analizamos el código poco a poco, podemos contemplar la idea principal que es comparar la lista de imágenes actuales, con la lista original. Si el orden de los elementos coinciden entonces habremos completado el ROMPE.

*Nota: Es a continuación del mensaje de alert("ROMPE COMPLETADO"), cuando uniremos conceptos con el PASO 1, añadiendo la función StopClock(), para que nuestro cronometro se pare.

PASO 3: Carrousel.

    He utilizado bootstrap que es el marco más popular para el desarrollo de sitios web sensibles. Con el objetivo de poder poner diferentes imágenes de puzzles. Para ello también he tenido que gestionar bien el sistema de ficheros, donde guarde todas las imágenes troceadas. El código del carrousel lo podrás encontrar en w3school. http://www.w3schools.com/bootstrap/bootstrap_carousel.asp

<div id="myCarousel" class="carousel slide" data-ride="carousel">
      <!-- Indicators -->
      <ol class="carousel-indicators">
        <li data-target="#myCarousel" data-slide-to="0" class="active"></li>
        <li data-target="#myCarousel" data-slide-to="1" class></li>
        <li data-target="#myCarousel" data-slide-to="2" class></li>
        <li data-target="#myCarousel" data-slide-to="3" class></li>
        <li data-target="#myCarousel" data-slide-to="4" class></li>
        <li data-target="#myCarousel" data-slide-to="5" class></li>
      </ol>
      <!-- Wrapper for slides -->
      <div class="carousel-inner" role="listbox">
        <div onClick="CambiarPuzzle(this)" id="ROMPE1" class="item active">
          <img src="media/ROMPE1/rompe1.png">
        </div>
        <div onClick="CambiarPuzzle(this)" id="ROMPE2" class="item" >
          <img src="media/ROMPE2/rompe2.png">
        </div>
        <div onClick="CambiarPuzzle(this)" id="ROMPE3" class="item">
          <img src="media/ROMPE3/rompe3.png" >
        </div>
        <div onClick="CambiarPuzzle(this)" id="ROMPE4" class="item">
          <img src="media/ROMPE4/rompe4.png" >
        </div>
        <div onClick="CambiarPuzzle(this)" id="ROMPE5" class="item">
          <img src="media/ROMPE5/rompe5.png" >
        </div>
        <div onClick="CambiarPuzzle(this)" id="ROMPE6" class="item">
          <img src="media/ROMPE6/rompe6.png" >
        </div>
      </div>
      <!-- Left and right controls -->
      <a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
        <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
        <span class="sr-only">Previous</span>
      </a>
      <a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
        <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
        <span class="sr-only">Next</span>
      </a>
    </div>

A continuación comento, las modificaciones que he hecho en relación al código elegido. Como veremos la estructura del html es una etiqueta div, en el que nos encontramos:

  1. Una lista que nos indicara el estado de actividad de cada imagen del puzzle en cada momento, ya que nuestro carrusel estará en continuo movimiento.
  2. Justo después de la lista tendremos otra estructura div, con muchos div introducidos en el, los cuales irán apareciendo en relación a la actividad que ofrezca el carrusel.
  3. El último contenido de este carrusel, son los controles right y left, que nos servirán para ver que puzzle queremos cambiar.
Si nos fijamos en el contenido html, hay llamadas a la función CambiarPuzzle(). Esta función nos permitirá cambiar de forma ordenada cada una de las imágenes que componen los puzzles. Estas imágenes deben estar colocadas en sus correspondientes carpetas ¡¡MUY IMPORTANTE!!!!


function CambiarPuzzle(entrada) {
  ResetClock();
  var list = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
  index = 0;
  puzzle = entrada;
  for (i=1; i < 5; i++) {
   for (j=1; j < 5; j++) {
      identy = "F" + i.toString() + "C" + j.toString();
      if (identy != "F4C4"){
        document.getElementById(identy).src = "media/"+ puzzle.id +"/" + list[index] + ".png"; 
      }
      index++;
   }
  }
  document.getElementById("F4C4").src = "media/blanco.png"; 
  var white = {id: "F4C4", src: "media/blanco.png"};
}

Nota: Esta función nos tiene que recordar a la función DesordenarFichas() vista en el hito 1 de rompecabezas URJC, salvo con la diferencia de que aquí, tenemos que gestionar las carpetas de los diferentes puzzles, por eso se necesita tener una variable global.

var puzzle = {id: "ROMPE1"};

La inicializo al nombre de la carpeta donde se encuentra mi rompecabezas por defecto.

Bueno, pues ya tendríamos lo necesario para ver nuestro carrusel, no sin antes añadir la magia del bootstrap. Para que todo esto funcione es de obligatorio cumplimiento introducir los siguientes scrip, que contienen documentos javascrip, donde están implementados las funciones de nuestro carrusel.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

Y también recordar, que podremos retocar las dimensiones de nuestras imagenes, con la hoja de estilo css de la siguiente forma.

.carousel-inner > .item > img,
.carousel-inner > .item > a > img {
    margin: auto;
    width: 300px;
    height: 300px;
  }

PASO 4: Cookie

   Este ultimo paso es el más sencillo de todos, ya que únicamente va a consistir en que cuando carguemos la pagina, nos salga un mensaje de alerta pidiendo autentificación, y si nos volvemos a conectar en una hora nos debera de pedir otra vez la autentificación.

  Para utilizar las cookies es muy importante abrir nuestro documento html con firefox, ya que chrome no le las cookie locales.

Para la gestión de las cookies he utilizado tres funciones:

1 - En primer lugar, creamos una función que almacena el nombre del usuario en una variable cookie:

function setCookie(cname,cvalue,exmins) {
    var d = new Date();
    d.setTime(d.getTime() + (exmins*1000));
    var expires = "expires=" + d.toGMTString();
    document.cookie = cname+"="+cvalue+"; "+expires;
}

2 - Luego, creamos una función que devuelve el valor de una cookie especificada:

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1);
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

3 - Por último, creamos la función que comprueba si se crea una cookie, se mostrará un "welcome again".
Si la cookie no se ha creado, se mostrará un cuadro de diálogo, preguntando por el nombre del usuario, y almacena la cookie de nombre de usuario en un plazo de 60 mins, llamando a la función setCookie:

function checkCookie() {
    var user=getCookie("username");
    if (user != "") {
        alert("Welcome again " + user);
    } else {
       user = prompt("Please enter your name:","");
       if (user != "" && user != null) {
           setCookie("username", user, 60);
       }
    }

}

Nota: Para que todo esto de las cookies funcione en nuestra web simplemente llamaremos a la función checkCookie, cuando se cargue la pagina.

<body onload = "checkCookie()" align="center">ROMPE-CABEZAS URJC</body>

   Aquí doy por concluido mi hito 2 del tutorial Rompe-cabezas URJC donde hemos mejorado en mucho lo hecho en el hito 1. Una vez cogida la carrerilla vamos a por django. Os adjunto la apariencia de la pagina.


martes, 3 de febrero de 2015

WEB_P1


Rompecabezas URJC

    Este es mi primer tutorial de como hacer un juego utilizando html, javascrip y css. El ejemplo del tutorial es: Programar un rompecabezas en 4 PASOS.

¿Qué es un rompecabezas y en que consiste?
Tenemos una tabla dividida en una matriz de 4X4 (16 celdas), con una de sus casillas en blanco, la cual nos servirá para poder mover las piezas y así resolver el rompecabezas.


PASO 1.

    Lo primero es el documento html con sus correspondientes etiquetas para crear una tabla de 4x4 y en que cada una de ellas vaya asociada una imagen por defecto que sera la solución del rompecabezas.

<!DOCTYPE html>
<html>
<head>
<title>ROMPE-CABEZAS</title>
</head>
<body>
<table width="320" height="320" border="1">
    <tr>
    <td><img src="1.png" width="80" height="80"id="F1C1"/></td>
    <td><img src="2.png" width="80" height="80" id="F1C2"/></td>
    <td><img src="3.png" width="80" height="80" id="F1C3"/></td>
    <td><img src="4.png" width="80" height="80" id="F1C4"/></td>
    </tr>
    <tr>
    <td><img src="5.png" width="80" height="80" id="F2C1" /></td>
    <td><img src="6.png" width="80" height="80" id="F2C2"/></td>
    <td><img src="7.png" width="80" height="80" id="F2C3"/></td>
    <td><img src="8.png" width="80" height="80" id="F2C4"/></td>
     </tr>
     <tr>
    <td><img src="9.png" width="80" height="80" id="F3C1"/></td>
    <td><img src="10.png" width="80" height="80" id="F3C2"/></td>
    <td><img src="11.png" width="80" height="80" id="F3C3"/></td>
    <td><img src="12.png" width="80" height="80" id="F3C4"/></td>
      </tr>
       <tr>
    <td><img src="13.png" width="80" height="80" id="F4C1"/></td>
    <td><img src="14.png" width="80" height="80"id="F4C2"/></td>
    <td><img src="15.png" width="80" height="80" id="F4C3"/></td>
    <td><img src="blanco.png" width="80" height="80" id="F4C4"/></td>
       </tr>
</table>
</body>
</html>

    En el código, aparte de la tabla, en cada celda va asociado un identificador que corresponde con el numero de columna "Cx" y el numero de fila "Fy" de cada casilla.
Este juego esta pensado para insertarle cualquier imagen para jugar a colocarla en orden. En mi caso he puesto números que también son imagen, para que la resolución del rompecabezas cuando juguemos sea más sencillo.

* Dentro del paso 1 comentamos que para dividir una imagen en 16 piezas iguales, puedes utilizar cualquier herramienta de edición de imagen, recomiendo photoshop, el cual te permite dividir la imagen en piezas iguales de manera muy rápida. Si tenéis algún problema en este punto comentármelo y os contesto, pero en principio no debería dar problemas.

PASO 2

    A continuación y como segundo paso en nuestro Rompecabezas, es desordenar la imagen de forma aleatoria, para ello he pensado crearme un boton en html y asociarle el evento onclick.

<button onClick="DesordenaPiezas">START</button>
    Cuando hagamos click en ese boton, invocaremos al metodo onClick, el cual activara la función DesordenarFicha().


function DesordenaPiezas() {
  var list = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
  list = list.sort(function() {return Math.random() - 0.5});
  index = 0;
  for (i=1; i < 5; i++) {
   for (j=1; j < 5; j++) {
    identity = "F" + i.toString() + "C" + j.toString();
    document.getElementById(identity).src = list[index].toString() + ".png"; 
    index++;
   }
  }
 }

    La idea de la función consiste, en crearse una lista de 15 elementos enumerados del 1 al 15.
En la segunda linea del código de la función desordenamos esa lista de forma aleatoria. Una vez que tenemos una lista de 15 elementos desordenados, nos tenemos que recorrer todos los elementos de la tabla, y la manera de hacerlos es con un bucle anidado de 4X4. En cada iteración de las 16 posibles, lo que haremos sera lo siguiente: Nombrar al elementos en el que estamos, para luego asignarle una imagen aleatoria. Para que todo esto tenga sentido, ni que decir tiene que nuestras imágenes tienen que tener un nombre particular [1.png,2.png....,15.png]. Si tenéis algún problema con esta función DesordenarFicha() comentármelo y os contesto.

PASO 3

    Como tercer paso vamos a realizar una función en java scrip que nos permita hacer click en una pieza y que esa pieza se cambie por la imagen en blanco. 

Por ejemplo la función CambiarFicha se la voy asignar a la celda F1C1 y deberá cambiarse por el blanco.

<td><img onclick="CambiarFicha(this)" src="media/1.png" width="80" height="80" id="F1C1"/></td>

Para esto he pensado asignarle el metodo onClick a cada casilla, con la función CambiarFicha(this). 

La función CambiarFicha(this) es la siguiente:

function CambiarFicha(in) {
 identy = white.id;
 var aux = document.getElementById(identy);
 aux.src = in.src;
 in.src = "media/blanco.png";
 white = in;
 }

Como observamos en el codigo hace falta de una variable empty que es global. 
 var white = {src: "blanco.png", id: "F4C4"};

Analizando un poco las lineas de codigo de la función vemos que el campo identy en nuestro caso "F4C4", que la variable aux="F1C1", a continuación itroducimos la imagen de la pieza en la posición del blanco y la imagen del blanco en la posición de la pieza y por ultimo dejamos actualizada la posición del blanco var white = {src: "blanco.png", id: "F4C4"};


PASO 4

Esta función nos permite cambiar cualquier ficha por la que esta en blanco, pero el juego nos obliga a que sean las abyacentes al blanco. Entonces la solución que se me ocurrio fue llamar a otra función cuando se active el metodo onclick en la casilla seleccionada.

<td><img onclick="CambiarFichaCercana(this)" src="media/1.png" width="80" height="80" id="F1C1"/></td>

La función es la siguiente:

function CambiarFichaCercana(entrada) {
identy1 = white.id;
identy2 = entrada.id;
 i = parseInt(identy1.charAt(1));
 j = parseInt(identy1.charAt(3));
 x = parseInt(identy2.charAt(1));
 y = parseInt(identy2.charAt(3));
 switch (Math.abs(i - x)) {
  case 0:
   if (Math.abs(j - y) == 1) {
    CambiarFicha(entrada);
   }
   break;
  case 1:
   if (j == y) {
    CambiarFicha(entrada);
   }
   break;
 }
}

  Vamos analizando poco a poco el código js implementado. Tenemos dos variables indety1 e identy2 que guardan el nombre del identificador de la pieza seleccionada y del blanco. A continuación buscamos a partir de los identificadores las coordenadas de la pieza. Una vez que tenemos almacenadas las coordenadas de las piezas, aplicamos el concepto de celdas abyacentes que no es otro que si en el eje de las x la diferencia de su modulo es "0", se tiene que cumplir que la diferencia del modulo del eje y tiene que ser = "1". Lo mismo ocurre en caso contrario, si el modulo de la diferencia del eje y es "0", entonces la diferencia del modulo de x debera ser "1".

Ejemplo:

Si vamos analizando poco a poco el codigo, con un caso para ver si lo entendemos mejor. Imaginemos que pinchamos en el id="F4C3" y el blanco esta en "F4C4", debería dejarnos mover la pieza según la norma del juego. 
Lo primero que hace el codigo es inicializar las variables:
identy1 = "F4C4";
identy2 = "F4C3";
i = 4;
j = 4;
x = 4;
y = 3;

Siguiendo el flujo, calculamos el valor absoluto de la resta.
|x-i| = |4-4| = 0
Si da "0" entonces:
 Calculamos el valor absoluto de |y-j|, si da igual a 1 entonces CambiarFicha(Entrada);
 |3-4|=1;
 Si ocurre esto se produce un break, por lo que el programa se para aquí.

CONCLUSIÓN
Bueno y aquí termino con la publicación de mi primer tutorial sobre este rompecabezas, espero que se entienda bien y seguiremos haciendo mejoras. Un saludo.