Java Scriptによるブロック崩し

〜
[index.html]
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>ブロック崩し</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!--canvasにはゲームを描画-->
  <!--幅480px,高さ320px-->
  <canvas id="myCanvas" width="480" height="320">
  </canvas>
  <!--ゲームを制御するJSを書く-->
  <script src="main.js"></script>
</body>
</html>
[main.js]
//変数の宣言
//<canvas>要素への参照をcanvasに保存
let canvas=document.getElementById("myCanvas");
//2D描画コンテキストを保存するためにctx変数を作成
let ctx=canvas.getContext("2d");

//円の中心のx座標を定義
let x=canvas.width/2;
//円の中心のy
let y=canvas.height-30;

//xを描画した後に小さな値を加え、ボールが動いているように見せるための変数。
let dx=2;
//yを描画した後に小さな値を加え、ボールが動いているように見せるための変数
let dy=-2;

//計算を簡単にするために、描画される円の半径をもつballRadiusという変数を定義
let ballRadius=10;

//パドルの高さ
let paddleHeight=10;

//パドルの幅
let paddleWidth=75;

//パドルのx軸上の開始地点
//(キャンバスの右端の座標ーパドルの横幅)/2
let paddleX=(canvas.width-paddleWidth)/2;

//右側のボタンが押された
//最初、制御ボタンが押されていないため、デフォルトの値はfalseで初期化しておく。
let rightPressed=false;

//左側のボタンが押された
//最初、制御ボタンが押されていないため、デフォルトの値はfalseで初期化しておく。
let leftPressed=false;

//ブロックを定義
//ブロックの行の数
let brickRowCount=5;
//ブロックの列の数
let brickColumnCount=5;
//ブロックの幅
let brickWidth=75;
//ブロックの高さ
let brickHeight=20;
//
let brickPadding=10;
//キャンバスの上端からのブロック相対位置
let brickOffsetTop=30;
//キャンバスの左端からのブロックの相対位置
let brickOffsetLeft=30;

//1次元目の配列を宣言
let bricks=[];


//宣言終了

//変数の宣言終了
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//ボールを定義する関数
function drawBall(){
  //ボールを描画
  //draw()関数の中に下記のコードを追記する。
  //描画コードの始め
  ctx.beginPath();
  //円の描画
  //(円の中心のx座標、円の中心のy座標、円の半径、開始角度と終了角度、πの二乗)
  //arc()メソッド内で変数xと変数yを使うようにdraw()関数を書き換える。
  //ballRadius=描画される円の半径
  ctx.arc(x,y,ballRadius,0,Math.PI*2);
  //ctx.fillstyleに色を記憶。
  ctx.fillStyle="#0095DD";
  //fill()メソッドは、配列中の開始インデックスから終了インデックスまでの要素を固定値で設定する。
  ctx.fill();
  //描画コードの終わり
  ctx.closePath();

}
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//壁に当たったかどうかの判定
function judge(){
  //左右の壁の当たり判定
  //左の壁 (x+dx<0)
  //(今いるx座標+移動するx方向の変化量)<(キャンバスの左端の座標+ボールの半径)
  if(x+dx<ballRadius){
    dx=-dx;
  }
  //右の壁(x+dx>canvas.width)
  //(今いるx座標+移動するx方向の変化量)>(キャンバスの右端の座標-ボールの半径)
  else if(x+dx>canvas.width-ballRadius){
    dx=-dx;
  }

  //上下の壁の当たり判定
  //上の壁(y+dy<0)
  //(今いるy座標+移動するy方向の変化量)<(キャンバスの上端のy座標+ボールの半径)
  if( y+dy<ballRadius){
    dy=-dy;
  }
  //下の壁(y+dy>canvas.height-ballRadius)
  //(今いるy座標+移動するy方向の変化量>(キャンバスの高さ-ボールの半径)
  else if(y+dy>canvas.height-ballRadius){
    //ボールがパドルの左端と右端の間にあるか確認する
    //ボールのx座標 > パドルの左端のx座標 であり、ボールのx座標 < パドルの左端のx座標+パドルの横幅
    if(x>paddleX&&x<paddleX+paddleWidth){
      dy=-dy;
    }
    else{
      //アラート表示
      alert("GAME OVER");
      //再度読み込む(更新、リロード同じ)
      document.location.reload();
    }
  }
}
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//パドルを描画する関数
function drawPaddle(){
  //命令の始まり
  ctx.beginPath();
  //四角形の定義(パドルのx軸上の開始地点、キャンバスの下端ーパドルの高さ、パドルの横幅、パドルの高さ)
  ctx.rect(paddleX,canvas.height-paddleHeight,paddleWidth,paddleHeight);
  //ctx.fillStyleに四角形の色を記録
  ctx.fillStyle="#0095DD";
  //fill()メソッドは、配列中の開始インデックスから終了インデックスまでの要素を固定値で設定
  ctx.fill();
  //命令の終わり
  ctx.closePath();
}
//キーボードのキーのどれかに対してkeydownイベントが発生したとき(どれかが押されたとき)、keyDownHandler()関数が実行
document.addEventListener("keydown",keyDownHandler,false);
//キーボードのキーのどれかに対して、keyUpイベントが発生したとき(どれかが押された状態から離されたとき)、keyUpHandler()関数が実行される
document.addEventListener("keyup",keyUpHandler,false);

//---------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//ボタンが押されたときの処理
function keyDownHandler(e){
  //どちらの関数も変数eで表されるイベントをパラメータとしてとる。
  //keyCodeは押されたキーについての情報を持っている。(右カーソルキー=39)
  if(e.keyCode==39){
    //キーが押されたとき、その情報は変数に保存される。
    //キーが押されたときは、変数rightPressesの値がtrueに書き換わる。
    rightPressed=true;
  }
  //どちらの関数も変数eで表されるイベントをパラメータとしてとる。(e:event:これにより有用な情報が手に入る。)
  else if(e.keyCode==37){
    //キーが押されたとき、その情報は変数に保存される。
    //キーが押されたときは、変数rightPressesの値がfalseに書き換わる。
    leftPressed=true;
  }
}

//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//あらゆるボタンが押されている状態から離されたときの処理
function keyUpHandler(e){
  debugger;
  //どちらの関数も変数eで表されるイベントをパラメータとしてとる。
  //keyCodeは押されたキーについての情報を持っている。(右カーソルキー=39)
  if(e.keyCode==39){
    //キーが押された状態から離されたとき、その情報は変数に保存される。
    //キーが押された状態から離されたとき、変数rightPressedの値がtrueからfalseに書き換わる。
    rightPressed=false;
  }

  //keyCodeは押されたキーについての情報を持っています。
  else if(e.keyCode==37){
    //キーが押された状態から離されたとき、その情報は変数に保存される。
    //キーが押された状態から離されたとき、変数rightPressedの値がtrueからfalseに書き換わる。
    leftPressed=false;
  }
}
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//パドルを動かす処理
function movepaddle(){
  //パドルが縁から出てしまった時の処理
  //canvasの境界内でのみ動くようにする
  //右カーソルが押されている+パドルの左端のx座標<キャンバスの右端ーパドルの幅
  if(rightPressed&&paddleX<canvas.width-paddleWidth){
    paddleX+=7;
  }
  else if( leftPressed && paddleX>0){
    paddleX-=7;
  }
}
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//無限に続く setInterval の性質のため、draw()は10ミリ秒おきにずっと、あるいは私達が止めるまで呼ばれ続ける。
setInterval(draw,10);
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//1つの2次元配列で、すべてのブロックを記録する。
//2次元配列はブロックの列(c:Column)を含んでいる。
//また、列は行(r:Row)を含み、行はそれぞれのブロックが描画される画面上のx座標とy座標を持つオブジェクトを含んでいる。
//ブロックを描画する関数
function drawBricks(){
  //1次元目のループ
  //brickColumnCount=5より、5列のブロック
  for(let c=0;c<brickColumnCount;c++){
    //入れ子(2次元目の配列を加える)
    bricks[c]=[];
    //brickRowCount=3より、3行のブロック
    for(let r=0;r<brickRowCount;r++){
      //bricks[c][r]のx座標に0を紐づける
      //bricks[c][r]のy座標に0を紐づける
      //x座標とy座標の初期化
      //statusプロパティを追加
      bricks[c][r] = { x: 0, y: 0, status:1};
      //当たったブロックは消えるようにする
      if(bricks[c][r].status==1){
        //列の数*(ブロックの幅+余裕スペース)+左端からの相対位置
        let brickX=(c*(brickWidth+brickPadding))+brickOffsetLeft;
        //行の数*(ブロックの高さ+余裕スペース)+上端からの相対位置
        let brickY=(r*(brickHeight+brickPadding))+brickOffsetTop;
        //ブロックのx座標を代入
        bricks[c][r].x=brickX;
        //ブロックのy座標を代入
        bricks[c][r].y=brickY;

        //命令の始まり
        ctx.beginPath();
        //四角形の定義
        ctx.rect(brickX,brickY,brickWidth,brickHeight);
        //ctx.fillStyleに四角形の色を記録
        ctx.fillstyle="#0095DD"
        //fill() メソッドは、配列中の開始位置から終了位置までの要素を固定値で設定する。
        ctx.fill();
        //命令の終わり
        ctx.closePath();
      }
    }
  }
}

//衝突検出関数
function collisionDetection(){
  for(let c=0;c<brickColumnCount;c++){
    for(let r=0;r<brickRowCount;r++){
      //変数bはブロックオブジェクトを保存する
      //新たな変数bを宣言し、その中にbricks[c][r]を代入していく。
      let b=bricks[c][r];
      if(b.status==1){
        //色々な計算
        //ボールのx座標がブロックのx座標より大きい
        //ボールのx座標がブロックのx座標とその幅の和より小さい
        //ボールのy座標がブロックのy座標より大きい
        //ボールのy座標がブロックのy座標とその高さの和より小さい
        if(x>b.x&&x<b.x+brickWidth&&y>b.y&&y<b.y+brickHeight){
          dy=-dy;
          b.status=0;
        }
      }
    }
  }
}

//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
//ボールを描画する関数
function draw(){

  //削除コード
  //このメソッドは4つのパラメータをとる。
  //四角形の左上端のx,y座標と四角形の右下端のx,y座標。
  //この四角形で囲われた領域にある内容全てが消去される。
  ctx.clearRect(0,0,canvas.width,canvas.height);

  //ブロックを描画
  drawBricks();

  //衝突検出を有効に
  collisionDetection();

  //ボールを定義する関数
  drawBall();

  //パドルの動きを定義
  movepaddle();

  //パドルを描画する
  drawPaddle();

  //パドルの動きを定義
  movepaddle();

  //壁に当たったかどうかを判定する関数
  judge();

  //xの値を+2して更新する
  x=x+dx;
  //yの値を-2して更新
  y=y+dy;
}
[style.css]
*{
  padding:0;
  margin:0;
}

canvas{
  background:#eee;
  display:block;
  margin:0 auto;
}