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:
- Cronometro: Realizar un cronometro con html, css y javascrip, en cuanto demos al botón "START".
- Juego Terminado: Realización de una función javascrip que nos permita saber si hemos completado el puzzle.
- Carrusel: Tener un listado de puzzles para poder cambiar dinámicamente. lo explico mas detalladamente en el PASO 3.
- 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:
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"};
#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:
- 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.
- 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.
- 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.