見出し画像

ゲームを作ろ!-MDN web docs(ブロック崩し)-7

ここで復習です。

function drawBall() {
   ctx.beginPath();
   ctx.arc(x, y, 10, 0, Math.PI*2);
   ctx.fillStyle = "#0095DD";
   ctx.fill();
   ctx.closePath();
}

ボールを表示させるコードです。大事なことは

ctx.arc(x, y, 10, 0, Math.PI*2);

です。ボールの中心の座標が"x"と"y"です。ここを再認識して衝突検知するコードを考えていきます。

ブロックに衝突、ぶつかったら跳ね返るようにします。

function collisionDetection() {
   for(var c=0; c<brickColumnCount; c++) {
       for(var 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;
           }
       }
   }
}
もしボールの中央がブロックの1つの座標の内部だったらボールの向きを変えます。ボールの中央がブロックの内部にあるためには次の4つの命題が全て真でなければなりません。
ボールのx座標がブロックのx座標より大きい
ボールのx座標がブロックのx座標とその幅の和より小さい
ボールのy座標がブロックのy座標より大きい
ボールのy座標がブロックのy座標とその高さの和より小さい

そして跳ね返ったら、ブロックに当たれば、そのブロックを消します。その方法ですが、まず、衝突、ぶつかったかどうか判定する目印をつけます。

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

衝突すると"status: 0"となるように設定します。 status: 1はまだ衝突はしていません。

これを、drawBricks()に適応させます。

function drawBricks() {
   for(var c=0; c<brickColumnCount; c++) {
       for(var 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();
           }
       }
   }
}

そして衝突した時のためのコードです。"b.status = 0;"を加えています。

跳ね返った時に、statusを"0"にします。

function collisionDetection() {
   for(var c=0; c<brickColumnCount; c++) {
       for(var 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;
               }
           }
       }
   }
}

drawBricks() を変更して、collisionDetection()を追加して、

function draw() {

}

の中で実行させます。これで、ボールが上方向へ移動して、ブロックに当たればブロックが消えます。最低限度の仕組みができました。

全コードです。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 10;
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;
var bricks = [];
for (var c = 0; c < brickColumnCount; c++) {
   bricks[c] = [];
   for (var r = 0; r < brickRowCount; r++) {
       bricks[c][r] = { x: 0, y: 0, status: 1 };
   }
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
   if (e.key == "Right" || e.key == "ArrowRight") {
       rightPressed = true;
   }
   else if (e.key == "Left" || e.key == "ArrowLeft") {
       leftPressed = true;
   }
}
function keyUpHandler(e) {
   if (e.key == "Right" || e.key == "ArrowRight") {
       rightPressed = false;
   }
   else if (e.key == "Left" || e.key == "ArrowLeft") {
       leftPressed = false;
   }
}
function collisionDetection() {
   for (var c = 0; c < brickColumnCount; c++) {
       for (var 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 drawBall() {
   ctx.beginPath();
   ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
   ctx.fillStyle = "#0095DD";
   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 (var c = 0; c < brickColumnCount; c++) {
       for (var 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 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();
           clearInterval(interval); // Needed for Chrome to end game
       }
   }
   if (rightPressed && paddleX < canvas.width - paddleWidth) {
       paddleX += 7;
   }
   else if (leftPressed && paddleX > 0) {
       paddleX -= 7;
   }
   x += dx;
   y += dy;
}
var interval = setInterval(draw, 10);

この記事が気に入ったらサポートをしてみませんか?