🕹️Brick Breaker en javascript (2D)

Detección de colisiones

 

Una función para detectar colisiones

Para lograr nuestro objetivo vamos a definir una función que, con un bucle, recorrerá todos los ladrillos y comparará la posición de cada uno con la posición de la bola, cada vez que se dibuje un fotograma. Para que el código sea más legible definiremos la variable «b» que almacenará el objeto ladrillo en cada vuelta de bucle:

function collisionDetection() {
  for (c = 0; c < brickColumnCount; c++) {
    for (r = 0; r < brickRowCount; r++) {
      var b = bricks[c][r];
      // calculations
    }
  }
}

Si el centro de la bola está dentro de las coordenadas de uno de nuestros ladrillos, cambiaremos la dirección de la bola. Se cumplirá que el centro de la bola está dentro de ladrillo si se cumplen al mismo tiempo estas cuatro condiciones:

  • La posición «x» de la bola es mayor que la posición «x» del ladrillo
  • La posición «x» de la bola es menor que la posición del ladrillo más el ancho del ladrillo
  • La posición «y» de la bola es mayor que la posición «y» del ladrillo.
  • La posición «y» de la bola es menor que la posición del ladrillo más su altura.

Traducimos esto a JavaScript:

function collisionDetection() {
  for (c = 0; c < brickColumnCount; c++) {
    for (r = 0; r < brickRowCount; r++) {
      var b = bricks[c][r];
      if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
        dy = -dy;
      }
    }
  }
}

Hacer que los ladrillos desaparezcan cuando reciben un golpe

El código anterior funcionará correctamente y la bola cambiará de dirección. El problema es que los ladrillos siguen donde están. Tenemos que imaginar una forma de ocuparnos de los que ya hemos golpeado con la bola. Podemos hacerlo añadiendo un parámetro extra para indicar si queremos pintar cada ladrillo en la pantalla o no. En la parte del código donde inicializamos los ladrillos, añadiremos una propiedad status a cada ladrillo. Cambia tu código fijándote en la línea que está resaltada:

var bricks = [];
for (c = 0; c < brickColumnCount; c++) {
  bricks[c] = [];
  for (r = 0; r < brickRowCount; r++) {
    bricks[c][r] = { x: 0, y: 0, status: 1 };
  }
}

A continuación consultaremos el «status» de cada ladrillo para saber si lo tenemos que dibujar o no. Si «status» vale 1, lo dibujaremos. Si vale 0, no lo dibujaremos porque habrá sido golpeado por la bola. Actualiza tu función drawBricks() para que quede así:

function drawBricks() {
  for (c = 0; c < brickColumnCount; c++) {
    for (r = 0; r < brickRowCount; r++) {
      if (bricks[c][r].status == 1) {
        var brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
        var brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
        bricks[c][r].x = brickX;
        bricks[c][r].y = brickY;
        ctx.beginPath();
        ctx.rect(brickX, brickY, brickWidth, brickHeight);
        ctx.fillStyle = "#0095DD";
        ctx.fill();
        ctx.closePath();
      }
    }
  }
}

Actualizar el «status» en la función de detección de colisiones

Ahora tenemos que ocuparnos del valor de «status» en la función collisionDetection(): si el ladrillo está activo (status 1) comprobaremos si hay colisión. Si hay colisión, pondremos el «status» de ese ladrillo a 0 para no volver a pintarlo. Actualiza collisionDetection() así:

function collisionDetection() {
  for (c = 0; c < brickColumnCount; c++) {
    for (r = 0; r < brickRowCount; r++) {
      var b = bricks[c][r];
      if (b.status == 1) {
        if (
          x > b.x &&
          x < b.x + brickWidth &&
          y > b.y &&
          y < b.y + brickHeight
        ) {
          dy = -dy;
          b.status = 0;
        }
      }
    }
  }
}

Ya sólo falta llamar a la función collisionDetection() desde la función draw(). Añade la línea siguiente dentro de draw() function, justo después de la llamada a drawPaddle():

collisionDetection();

Compara tu código

var canvas=document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius=10;
//to move

var x=canvas.width/2;
var y=canvas.height-30;
var dx=2;
var dy=-2;
var paddleHeight=10;
var paddleWidth=75;
var paddleX=(canvas.width-paddleWidth)/2;
var rightPressed= false;
var leftPressed=false;
var brickRowCount = 3;
var brickColumnCount = 5;
var brickWidth = 75;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
document.addEventListener("keydown",keyDownHandler,false);
document.addEventListener("keyup",keyUpHandler,false);

var bricks = [];
for(c=0; c<brickColumnCount; c++) {
    bricks[c] = [];
    for(r=0; r<brickRowCount; r++) {
         bricks[c][r] = { x: 0, y: 0, status: 1 };
    }
}

function keyDownHandler(e){
    if(e.keyCode==39){
        
        rightPressed=true;
        
        }
        else if(e.keyCode==37){
        
        leftPressed=true;
        
        }
        
    }
    
function keyUpHandler(e){
    
    if(e.keyCode==39){
        
        rightPressed=false;
    }
    else if(e.keyCode==37){
        
        leftPressed=false;
        
        }
    }

function drawBall(){
    ctx.beginPath();
    ctx.arc(x,y,ballRadius,0,2*Math.PI);
    ctx.fillstyle="#0033FF";
    ctx.fillStroke="#0033FF";
    ctx.Stroke="10"
    ctx.fill();
    ctx.closePath();
    }

function drawPaddle(){
    ctx.beginPath();
    ctx.rect(paddleX,canvas.height-paddleHeight,paddleWidth,paddleHeight);
    ctx.fillstyle="#0095DD";
    ctx.fill();
    ctx.closePath();
    }
function drawBricks() {
    for(c=0; c<brickColumnCount; c++) {
        for(r=0; r<brickRowCount; r++) {
            if(bricks[c][r].status == 1) {
                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
                bricks[c][r].x = brickX;
                bricks[c][r].y = brickY;
                ctx.beginPath();
                ctx.rect(brickX, brickY, brickWidth, brickHeight);
                ctx.fillStyle = "#0095DD";
                ctx.fill();
                ctx.closePath();
            }
        }
    }
}

function collisionDetection() {
    for(c=0; c<brickColumnCount; c++) {
        for(r=0; r<brickRowCount; r++) {
            var b = bricks[c][r];
            if(b.status == 1) {
                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
                    dy = -dy;
                    b.status = 0;
                }
            }
        }
    }
}


function draw(){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    drawBricks();
    drawBall();
    drawPaddle();
    collisionDetection();
 if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
        dx = -dx;
    }
    if(y + dy < ballRadius) {
        dy = -dy;
    }
    else if(y + dy > canvas.height-ballRadius) {
        if(x > paddleX && x < paddleX + paddleWidth) {
             if(y= y-paddleHeight){
            dy = -dy  ;
             }
        }
        else {
            alert("GAME OVER");
            document.location.reload();
        }
    }
    if(rightPressed && paddleX<canvas.width-paddleWidth){
        
        paddleX+=7;
        }
     else if(leftPressed && paddleX>0 ){
         paddleX-=7;
         
         }
         
         x=x+dx;
         y=y+dy;
    }

setInterval(draw,10);

¿Te ha resultado útil??

1 / 0

Deja una respuesta 0

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.