jairogarcíarincón

La detección de colisiones


8.85K

La colisión con los bordes

La primera detección que debemos llevar a cabo es la colisión con los bordes del juego. En este caso tan simple, lo único que debemos hacer es comprobar si la x o la y valen 0 o 570, según el movimiento, y en ese caso no mover la nave.

Para conseguirlo, modifica el método moverNave para que incluya, en cada dirección, las siguientes líneas (al principio de cada case, antes de borrar la nave) que comprueban si hemos llegado a un borde. Además y para prepara la detección con los asteroides y la base, añade al final de cada case (antes del break) una llamada a la función detectarColision():


//Muevo la nave
function moverNave(evento){

//Detecto la tecla que estoy pulsando
switch(evento.keyCode){

//Izquierda: 37 o 65 (flecha izquierda o letra A)
case 37:
case 65:
//Compruebo si se va a salir por la izquierda
if (naveX == 0){
break;
}
//Borro la nave (pintando fondoNave encima)
ctx.putImageData(fondoNave, naveX, naveY);
//Actualizo la x
naveX = naveX - 30;
//Capturo el fondo que voy a tapar
fondoNave = ctx.getImageData(naveX, naveY, 30, 30);
//Muevo la nave
ctx.putImageData(nave, naveX, naveY);
//Compruebo colisión
detectarColision();
break;
//Derecha: 39 o 68 (flecha derecha o letra D)
case 39:
case 68:
//Compruebo si se va a salir por la derecha
if (naveX == 570){
break;
}
//Borro la nave (pintando fondoNave encima)
ctx.putImageData(fondoNave, naveX, naveY);
//Actualizo la x
naveX = naveX + 30;
//Capturo el fondo que voy a tapar
fondoNave = ctx.getImageData(naveX, naveY, 30, 30);
//Muevo la nave
ctx.putImageData(nave, naveX, naveY);
//Compruebo colisión
detectarColision();
break;
//Arriba: 38 o 87 (flecha arriba o letra W)
case 38:
case 87:
//Compruebo si se va a salir por arriba
if (naveY == 0){
break;
}
//Borro la nave (pintando fondoNave encima)
ctx.putImageData(fondoNave, naveX, naveY);
//Actualizo la y
naveY = naveY - 30;
//Capturo el fondo que voy a tapar
fondoNave = ctx.getImageData(naveX, naveY, 30, 30);
//Muevo la nave
ctx.putImageData(nave, naveX, naveY);
//Compruebo colisión
detectarColision();
break;
//Abajo: 40 o 83 (fle3cha abajo o letra S)
case 40:
case 83:
//Compruebo si se va a salir por abajo
if (naveY == 570){
break;
}
//Borro la nave (pintando fondoNave encima)
ctx.putImageData(fondoNave, naveX, naveY);
//Actualizo la y
naveY = naveY + 30;
//Capturo el fondo que voy a tapar
fondoNave = ctx.getImageData(naveX, naveY, 30, 30);
//Muevo la nave
ctx.putImageData(nave, naveX, naveY);
//Compruebo colisión
detectarColision();
break;
}

}


La colisión con los asteroides y la base

La otra detección que debemos hacer es comprobar si he chocado con un asteroide (he perdido) o con la base (he ganado). Para eso hemos llamado al método detectarColision() después de cada movimiento. Añade el siguiente código a detectarColision(), que comprobará de una forma bastante rudimentaria pero efectiva si me he chocado analizando pixel a pixel el cuadro al que me voy a mover, de modo que si encuentra algún pixel rojo corresponderá a un asteroide y se encuentra alguno azul a la base.

Además, desde esta función se llama a las funciones finalizar(), que mostrarán por pantalla el mensaje adecuado en cada momento y bloquearán los movimientos del teclado y reiniciar(), que permitirá reiniciar el juego al hacer clic en el mensaje. Añade también el código correspondiente a dichos métodos:


//Detecto colisiones con la base o los asteroides
function detectarColision(){

var pixels = 900; //Porque la imagen es de 30x30 pixels
var elementos = 900*4; //Porque cada pixel tiene 4 bytes (RGBA)

//Recorro en busca del rojo (asteroide) o del azul (base)
for (var i = 0; i < elementos; i += 4){

//Asteroide (255, 0, 0)
if (fondoNave.data[i] == 255 && fondoNave.data[i+1] == 0 && fondoNave.data[i+2] == 0){
var mensaje = "¡Lo siento! Has chocado con un asteroide.
Pincha AQUÍ para volver a intentarlo.";
finalizar(mensaje);
break;
}

//Base (0, 0, 255)
if (fondoNave.data[i] == 0 && fondoNave.data[i+1] == 0 && fondoNave.data[i+2] == 255){
var mensaje = "¡Enhorabuena! Has llegado a la base.
Pincha AQUÍ para volver a jugar.";
finalizar(mensaje);
break;
}

}

}

//Finalizo el juego
function finalizar(mensaje){

//Capturo el elemento en el que voy a escribir
var spanMensaje = document.getElementById("mensaje");
//Escribo el mensaje en ese elemento
spanMensaje.innerHTML = mensaje;
//Bloqueo el movimiento del teclado
window.removeEventListener("keydown", moverNave, true);

}

//Reinicio el juego
function reiniciar(){

window.location.reload();

}


En este punto, la aplicación ya es perfectamente jugable, si bien faltarían dos detalles:

Actualizar el contador para que vaya decrementándose en cada movimiento, cambiando de color si me estoy quedando sin movimientos, y finalizando el juego si llego a 0.
Añadir un temporizador que establezca un límite de 30 segundos para realizar el recorrido completo.

Ambas las veremos en las siguientes clases.


Publicado el 23 de Noviembre de 2024

javascripthtml5space starscanvas