Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

[TUTORIAL] Juego de la serpiente

Iniciado por Jose134, Septiembre 01, 2016, 11:37:27 AM

Tema anterior - Siguiente tema
Septiembre 01, 2016, 11:37:27 AM Ultima modificación: Septiembre 01, 2016, 10:23:16 PM por Jose134
Hola gente! Hace poco implemente el juego de la serpiente en javascript y se me ocurrio que podria hacer un tutorial explicando como funciona para aquellos que no tengan mucha experiencia programando juegos.
 
He de decir que no voy a explicar como programarlo, solo explicare como funciona este juego en especifico, para que asi luego lo podais implementar donde querais.
 
 
 
1 - Movernos por la "cuadricula"
 
Primero tenemos que entender como vamos a calcular las posiciones para que parezca que todo esta dentro de una cuadricula.
 
Vamos a asignar un tamaño a cada cuadrado, en mi caso van a ser de 20x20 pixeles. Esto quiere decir que si mi pantalla tiene "width" pixeles de ancho y "height" de alto va a haber (width / 20) cuadrados de ancho y (height / 20) de alto. Si queremos saber la posicion del cuadrado (5, 0) en pixeles tendriamos que hacer pos = (5 * 20, 0 * 20). Una vez entendido esto podemos empezar a hacer el juego
 
 
 
2 - Comida
 
Vamos a empezar por generar la comida que posteriormente la serpiente tendra que comer. En mi caso la comida (y la serpiente y practicamente todo) era un vector, y despues dibujaba un cuadrado en la posicion que ese vector indicara. Para generar la posicion de la comida vamos a hacer lo siguiente: pos = (random(0, width / 20 - 1) * 20, random(0, height / 20 - 1) * 20). Probablemente os estareis preguntando por que ese -1, la razon es porque la width / 20 esta fuera de la pantalla, ya que consideramos que la posicion es la esquina superior izquierda del cuadrado.
 

 
 
 
3 - Estructura de la serpiente
 
Rapida explicacion, nuestra serpiente va a constar de:
 
x - posicion de la cabeza en el eje X
 
y - posicion de la cabeza en el eje Y
 
dir - vector el cual indica la direccion en la que esta yendo la serpiente
 
tail - array de vectores la cual contiene las posiciones del cuerpo de la serpiente
 
Esta parte la escribo es solo para que no os perdais en la siguiente.
 
 
 
4 - Moviendo la serpiente
 
Lo primero va a ser asignar la direccion, cuando pulsemos las teclas W A S o D vamos a modificar dir para que apunte en la direccion que queramos, por ejemplo, if (W is down) { dir = new Vector(0, 1); }
 
Ahora vamos a modificar la posicion de la cabeza en funcion de dir:
 
x += dir.x * 20;
 
y += dir.y * 20;
 
Hasta aqui todo sencillo, el problema es como movemos el resto de la serpiente. Podriamos ir asignando la posicion a cada cuadradito de la serpiente uno a uno pero tenemos un truco mejor. Vamos a guardar la posicion de la cabeza antes de guardarla, movemos la cabeza y despues creamos un nuevo cuadrado en la posicion guardada anteriormente, finalmente borramos el ultimo cuadrado del cuerpo. Suena complejo pero no lo es, vamos a verlo graficamente
 

 
 
 
5 - Ampliando la serpiente
 
Ahora ya tenemos a nuestra serpiente moviendose pero... Es solo la cabeza, asi que vamos a hacer que si llegamos a la comida nos hagamos mas grandes.
 
Lo primero sera detectar si estamos en la posicion donde se encuentra la comida, comparar dos posiciones:
 
if (x == food.x && y == food.y) { COMER(); }
 
facil, no? Ahora vamos a crear un cuadrado nuevo, pero, donde lo creamos? para esto vamos a tener que hacer una pequeña modificacion en el punto anterior, eso solo lo haremos cuando NO nos comamos nada, en caso de que en ese frame hayamos comido haremos esto, no os olvideis de cambiar la posicion de la comida tambien.
 

 
Por lo que ahora todo nuestro codigo de movimiento se vera algo asi:
 

lastHeadPos = new Vector(this.x, this.y);
x += dir.x * 20;
y += dir.y * 20;
if (x == food.x && y == food.y) {
  tail.unshift(lastHeadPos);
  setNewFoodPos();
}
else {
  tail.unshift(tail.length - 1);
  tail.pop();
}

 
No iba a poner codigo pero asi es mas legible y no es muy dificil de entender, la funcion unshift añade un elemento al principio de la array y la funcion pop elimina el ultimo elemento de la array, sabiendo eso no deberiais tener problemas para entenderlo.
 
 
 
6 - Morir
 
Llegados a este punto no nos queda mucho que hacer, asi que vamos a hacer lo mas importante que nos queda para tener algo jugable, perder.
 
Para esto, tras movernos, vamos a comparar nuestra posicion con la de todo nuestro cuerpo. Si alguna coincide es que nos estamos comiendo a nosotros mismos y por tanto morimos (muy logico todo :P). Usaremos un ciclo for para recorrer la array tail e ir comparando la posicion uno a uno
 

for (var i = ; i < tail.length; i++) {
  if (x == tail[i].x && y == tail[i].y) {
    tail = [];
  }
}

 
En mi caso he hecho que se borre la array del cuerpo, asi que perdemos todo lo que llevamos, pero vosotros podeis hacer una bonita pantalla de GameOver.
 
 
 
7 - Bordes
 
Vale, el juego funciona, pero... Nos podemos salir de la pantalla y obviamente eso no es algo bueno. Para arreglarlo, dependiendo de que version mireis al salir de la pantalla o perdeis o apareceis por el otro lado. Yo voy a hacer que aparezcas por el otro lado. Es bastante sencillo de hacer: si estamos fuera de la pantalla, nuestra posicion = el otro lado de la pantalla
 

 
 
 
8 - Solucionando problemillas
 
No se si os habreis fijado pero podemos darnos media vuelta, es decir, si vamos hacia la derecha y pulsamos la A iremos hacia la izquierda comiendonos a nosotros mismos al instante. Para arreglar esto solo tenemos que añadir un poco de logica extra a los if que recogen la input:
 
if (W is down && dir.y == 0) { dir = new Vector(0, -1); }
 
if (A is down && dir.x == 0) { dir = new Vector(-1, 0); }
 
...
 
 
 
Otra cosa que tal vez os haya pasado es que la comida puede aparecer dentro de la serpiente, al principio esto no es un gran problema (a pesar de que no deberia ocurrir) pero cuando la serpiente es bastante grande si que nos puede hacer sufrir un poco. Para arreglarlo la funcion setFoodPosition se va a llamar a si misma hasta que la posicion de la comida no interfiera con nada, es decir:
 

function setFoodPosition () {
  food = new Vector(random(, width / 20 - 1) * 20, random(, height / 20 - 1) * 20);
 
  if (snake.x == food.x && snake.y == food.y) {
    setFoodPosition();
  }
 
  for (var i = ; i < snake.tail.length; i++) {
    if (food.x == snake.tail[i].x && food.y == snake.tail[i].y) {
      setFoodPosition();
    }
  }
}

 
 
 
9 - Jugar!
 
Nada que explicar en este punto, hemos terminado el juego! Ahora toca jugarlo!
 
Por si a alguien le interesa aqui les dejo mi version hecha en javascript, aunque advierto de que el codigo no esta comentado xD
 
https://mega.nz/#!z1BxyLpS!MacQeYh4OW63vnmEcwANuwR2wqqHqgbKpshrRW9y5Q4

Etiquetas: