Tutorial Javascript español - Crear un Snake Game en tu navegador

  • Autor Autor mundoblackhat
  • Fecha de inicio Fecha de inicio
M

mundoblackhat

Alfa
Programador
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Voy a empezar una serie para desarrollar el famoso Snake Game en Javascript que todos teníamos (y algunos aún tienen) en sus móviles del año de la pera. Va a ser totalmente funcional (colisiones, alimentos aparecen aleatoriamente, vidas y puntuación incluidas) y podemos ejecutarlo en nuestro navegador, supongo que en unos 5 o 6 posts quedará terminado ya que intentaré desgranar las funciones de Javascript que lo forman.

OJO: He marcado en negrita los scripts que llaman a Javascript en el código por una razón, los foros normalmente no dejan introducir scripts para evitar ser hackeados, así que lo único que tenéis que hacer es añadir el tag correspondiente a script, abrir con "<" y cerrar con ">" y "<" "/script" ">".

PARTE 1

Link original

snake-game.png


Voy a empezar una serie para desarrollar el famoso Snake Game en Javascript que todos teníamos (y algunos aún tienen) en sus móviles del año de la pera. Va a ser totalmente funcional (colisiones, alimentos aparecen aleatoriamente, vidas y puntuación incluidas) y podemos ejecutarlo en nuestro navegador, supongo que en unos 5 o 6 posts quedará terminado ya que intentaré desgranar las funciones de Javascript que lo forman.

El juego va a estar formado por tres archivos:

Insertar CODE, HTML o PHP:
index.html
index.html será la página principal de nuestro juego, el front-end, la página web que cargaremos para poder jugar.

Insertar CODE, HTML o PHP:
snake-game-script.js
snake-game-script.js serán todas las funciones que harán que nuestro juego funcione.

Insertar CODE, HTML o PHP:
snake-game-style.css
snake-game-style.css serán los estilos y como ponerlo todo bonito.

En esta primera parte voy a construir la mayoría de index.html, crear algunas reglas de estilo en snake-game-style.css y no voy a tocar para nada el Javascript hasta el siguiente capítulo. Empezamos con index.html:

Insertar CODE, HTML o PHP:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Snake Game en Javascript</title>
	<meta name="description" content="Snake Game en Javascript para http://aprendejs.es">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<link rel="stylesheet" href="snake-game-style.css" type="text/css">
</head>
<body>
	<div class="container">
		<h1>Snake Game en Javascript!</h1>
	
		<canvas id="canvas" width="600" height="450">

		</canvas>

		<div class="footer">
			<p><a href="http://aprendejs.es" target="_blank">AprendeJS</a></p>
		</div>

	</div>

	[B]script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js" type="text/javascript"
	script src="snake-game-script.js" type="text/javascript"[/B]
</body>

</html>

Como podéis ver no tiene nada raro, cargamos snake-game-style.css en el header (aún estará vacío de estilos), creamos un canvas en el body de la página de 600x450 y añadimos dos scripts al final del body, la librería jQuery, que la cargo a través de un CDN (cómo explicaba en el post anterior, aunque podeis cargar una copia local sin problemas) y nuestro javascript local, snake-game-script.js, que también estará vacío por ahora.

Para finiquitar el primer post añadiré unos cuantos estilos en snake-game-style.css para que se vea un poco decente antes de empezar a programar el juego:
Insertar CODE, HTML o PHP:
body {
	background: #000000;
	font-family: arial;
}

h1, h3 {
	color: #ffffff;
	text-align: center;
}

a {
	color: #ffffff;
	text-decoration: none;
}

canvas {
	background-color: #000000;
	border: 1px #cccccc solid;
}

.container {
	margin:30px auto 0 auto;
	width: 600px;
	position: relative;
}

snake-game-javascript-1024x589.png

Si tenéis alguna duda ya sabéis 😉
 
PARTE 2

Link original

En ésta segunda parte empezaré el archivo Javascript y a integrar todas las funcionalidades que tendrá nuestro juego, pero primero vamos a construir lo básico:

Insertar CODE, HTML o PHP:
'use strict';

window.jQuery(document).ready(function(){
});
Voy a usar el modo estricto de Javascript (del que aún no he hablado en el blog pero que caerá tarde o temprano en posteriores actualizaciones, básicamente nos ayudará a no cometer errores que la propia flexibilidad de Javascript nos permite). Por otra parte lo que quiero es que el juego cargue nada más lo haga la página, por lo que utilizaré el método .ready() de jQuery, que lo que hace es llamar al parámetro que pasamos dentro de la función automáticamente una vez que el DOM está cargado y listo, si como parámetro pasamos una función, podemos meter todo el código dentro y se ejecutará nada más el DOM esté cargado.

Canvas:

Mediante jQuery vamos a coger la id="canvas" de nuestro archivo HTML y le vamos a signar una variable en javascript, acto seguido llamaremos al método HTMLCanvasElement.getContext() y le pasaremos el parámetro '2d' para darle a entender al programa que vamos a renderizar en 2d mediante CanvasRenderingContext2D

Insertar CODE, HTML o PHP:
'use strict';

window.jQuery(document).ready(function(){
    	var canvas = window.jQuery('#canvas');
	var ctx = canvas.getContext('2d');
        var cellWidth = 20;
});
Si usamos el método HTMLCanvasElement.getContext() tal como nos dice la documentación nos dará error:

Insertar CODE, HTML o PHP:
TypeError: canvas.getContext is not a function
Parece ser que da error ya que no es un elemento puro del Canvas, sino que es un objeto jQuery, según un amigo de StackOverflow se soluciona devolviendo el elemento real y no el objeto, tal que:

Insertar CODE, HTML o PHP:
var canvas = window.jQuery('#canvas')[0];
La variable cellWidth no será más que un valor arbitrario por ahora que marcará el tamaño de las casillas que conforman tanto la serpiente, como la comida como los movimientos, he puesto 20 pero podréis jugar más adelante con ello, reduciéndolo o aumentándolo a vuestro gusto.

Funciones init() y createSnake():

Lo que buscamos con estas dos funciones es que se genere un bucle (Game Loop) que pinte continuamente la serpiente, como en una película compuesta de n fotogramas por segundo hace que genere movimiento a la vista humana, vamos a hacer lo mismo aquí. Mientras que createSnake() re-dibujará la serpiente cada vez que la función es llamada, mediante init() crearemos un bucle que hará que llamemos a createSnake() continuamente.

Insertar CODE, HTML o PHP:
function init(){
    createSnake();
    /* GAME LOOP */
}
init();

function createSnake(){

}
El efecto que buscamos es algo como esto cuando añadamos unas cuantas cosas más al código:

Y con esto es todo por hoy, en el siguiente post completaremos las funciones para generar la serpiente en movimiento tal como la veis en las imágenes, pero como quedan aun unas cuantas funciones y cosas que meter por en medio no quiero complicar cada post demasiado, por ahora irle echando un ojo a la documentación de las funciones que hemos ido usando para crear el canvas, ya que serán la base de cualquier juego que queramos hacer en el navegador.
 
PARTE 3

Link original

Y aquí tenemos la tercera parte de cómo crear un Snake Game en Javascript, si te has perdido los post anteriores aquí tienes los links:

Crear un Snake Game en Javascript – Parte 1
Crear un Snake Game en Javascript – Parte 2

En esta tercera parte vamos a poner la serpiente en movimiento, partimos desde nuestra función principal window.jQuery.ready(function(){}); donde añadimos las variables para movimiento (anchura, altura, dirección, color y velocidad) así como el array que conformará la serpiente, ya que queremos que esté compuesta por x partes e irá creciendo en función de las frutas que vaya comiendo por el camino.

window.jQuery(document).ready(function(){
var canvas = window.jQuery('#canvas')[0];
var ctx = canvas.getContext('2d');
var cellWidth = 20;

/* anadimos variables para movimiento y velocidad */
var w = canvas.width;
var h = canvas.height;
var d = 'right';
var color = 'green';
var speed = 100; // milisegundos

/* creamos el array que contendra la serpiente */
var snakeArray = [];
El siguiente paso será editar la función que conforma el LOOP principal del juego mediante setInterval(function, n) donde el primer parámetro es la función que se ejecutará en bucle cada vez que pase n tiempo y en el parámetro speed pasaremos el tiempo de intervalo en que queremos que la función se ejecute una y otra vez, en vez de añadir un valor numérico directamente como parámetro lo que haré será pasar la variable speed que hemos definido al principio así será más fácil de localizar y cambiar y tener el código organizado.

function init(){
createSnake();

/* anadimos el LOOP principal del juego mediante setInterval() */
var game_loop = setInterval(paint, speed);
}
init();
Creamos una nueva función llamada createSnake() que será la encargada de "crear" la serpiente, aunque en realidad lo único que hace es darle un largo por defecto (5 casillas por ejemplo) y mediante el método push sobre snakeArray nos irá añadiendo elementos al final del array y retornando el nuevo valor, lo que básicamente hará que cada vez que llamemos la función la serpiente será más larga, 5 casillas, 6, 7, 8, 9,... no es exactamente lo que buscamos pero partiremos de aquí para crear la serpiente y hacer que parezca que está en movimiento.

function createSnake(){
var length = 5;
snakeArray.push({x:0, y:0});
}
Creamos una nueva función llamada paint() que contendrá dos variables que nos servirán más adelante para jugar con la dirección de la serpiente, X e Y ya que el juego es 2d y sólo serán necesarias estás dos direcciones.

function paint(){
var directionX = snakeArray[0].x;
var directionY = snakeArray[0].y;
}
Una vez creado todo lo anterior, si abrimos el archivo HTML en nuestro navegador podemos ver como se crea la serpiente pero ésta nunca pasa de una casilla y se queda inmóvil en el primer cuadrante, así que tocará arreglarlo.

snake game javascript punto unico

Para ello tendremos que editar la función paint() que hemos creado antes y añadirle la clave, básicamente lo que tenemos que conseguir es que si la dirección por defecto es correcta (en este caso hemos elegido "right") añadiremos una casilla al array que conforma la serpiente, a su vez usaremos el método unshift, que nos añadirá el elemento al principio del array y retornará el nuevo array (fijaos que la diferencia entre push y unshift es sutil pero importante, push añade elementos al final y unshift lo hace al principio), y con unshift podemos jugar pasándole como parámetro una variable a la que llamaremos tail, lo que hará será añadir dicha casilla en la dirección X si esa es la dirección tomada o en la dirección Y si esta es la elegida, por lo que aquí ya podemos ver como poco a poco la serpiente irá creciendo en la dirección que le marquemos.

A su vez llamaremos a una nueva función que aún no existe pero que crearemos a continuación, la función nos pintará las casillas en una dirección o la otra continuamente.

function paint(){
var directionX = snakeArray[0].x;
var directionY = snakeArray[0].y;

if(d == 'right') directionX++;
var tail = {x: directionX, y: directionY};
snakeArray.unshift(tail);

for(var i = 0; i < snakeArray.length; i++){
paintCell(snakeArray.x, snakeArray.y);
}
}
Creamos la nueva función llamada paintCell(); que contendrá las variables referentes al canvas y que se conformarán mediante los métodos fillStyle, fillRect, strokeStyle y strokeRect, por ejemplo para determinar el color sería algo así (en el link y la documentación podemos ver todos los métodos disponibles):

canvas.getContext('2d').fillStyle = "#FF0000";
Para hacerlo más sencillo habíamos creado un par de variables iniciales al principio del código que nos ayudarán a tenerlo todo más organizado, por ejemplo lo anterior se transforma fácilmente en:

ctx.fillStyle = color;
Y la función al completo queda tal que:

function paintCell(x,y){
ctx.fillStyle = color;
ctx.fillRect(x*cellWidth, y*cellWidth, cellWidth, cellWidth);
ctx.strokeStyle = '#ffffff';
ctx.strokeRect(x*cellWidth, y*cellWidth, cellWidth, cellWidth);
}
Y si ahora abrimos nuestro archivo HTML por fin tenemos la serpiente en movimiento!

snake game javascript move 1

snake game javascript move 2

snake game javascript move 3

Ahora tocará recortarla por el final para que mantenga la misma longitud continuamente, añadir el resto de variables de movimiento, la aparición de la fruta, la puntuación, etc, ... pero lo más complicado ya está hecho y lo dejamos atrás.

Hasta la siguiente entrada!
 
Atrás
Arriba