<file_sep>class Block{
  constructor(row,col,width,height,padding,setTop,setLeft){
    this.row      = row
    this.col      = col
    this.width    = width
    this.height   = height
    this.padding  = padding
    this.setTop   = setTop
    this.setLeft  = setLeft
    this.blocks   = []
    this.BlockSet()
  }

  BlockSet(){
    for (let c = 0; c < this.col; c++) {
        this.blocks[c] = []
      for (let r = 0; r < this.row; r++) {
        this.blocks[c][r] = {x:0,y:0,status:1};
      }
    }
  }

  BlockStatusCheck(bls){
    for (let c = 0; c < this.col; c++) {
      for (let r = 0; r < this.row; r++) {
        if (this.blocks[c][r].status==1) {
          bls.push(true)
        }else{
          bls.push(false)
        }
      }
    }
  }

  draw(ctx){
    for (let c = 0; c < this.col; c++) {
      for (let r = 0; r < this.row; r++) {
        if (this.blocks[c][r].status == 1) {
          let blockX =  (c*(this.width+this.padding))+this.setLeft
          let blockY = (r*(this.height+this.padding))+this.setTop
          this.blocks[c][r].x = blockX
          this.blocks[c][r].y = blockY
          ctx.beginPath()
          ctx.rect(blockX,blockY,this.width,this.height,)
          ctx.fillStyle="#0095DD"
          ctx.fill()
          ctx.closePath()
        }
      }
    }
  }
}

export default Block;

// ctx.fillStyle="red"
          // ctx.fillStyle="#111111"
<file_sep># ブロック崩しゲーム
![breakout](/images/breakout_game1.png)
# Description
複雑なプログラムを組みトレーニングとして、ブロック崩しゲームを作成をしてみました。座標の設定や衝突判定のロジックを組むのは、とても難易度が高かったです。ブログに解説記事がありますので、よろしければご参照してください。
# Demo
<img src="/images/breakout_game2.gif" width="500px" height="300px"><br><br>

- [Demo](https://kazutotakeuchi-32.github.io/breakout_game/)
- [ブログ解説記事](https://taketon-blog.com/kazugramming/%e3%83%96%e3%83%ad%e3%83%83%e3%82%af%e5%b4%a9%e3%81%97%e3%82%b2%e3%83%bc%e3%83%a0/)
# Install
  下記のコマンドを実行してください。<br><br>
  ```
    $ git clone https://github.com/kazutotakeuchi-32/breakout_game.git
  ```
# Requirements
  - HTML
  - CSS
  - JavaScript
  - Live Server
<file_sep>class Game {
    // Math.abs(this.paddle.y-(this.paddle.height/2)- this.ball.y) <= this.ball.rabius
  constructor(node){
    this.intervalID=null
    this.node =document.querySelector(node)
    this.ctx = this.node.getContext('2d')
    this.ball =new window.Ball(this.node.width/2+10,this.node.height-30, -2,-2,10 )
    this.paddle = new window.Paddle(10,75,false,parseInt( (this.node.width-75)/2),parseInt(this.node.height-10))
    this.block = new window.Block(5,5,70,20,5,20,55)
    document.addEventListener("keydown", this.paddle.keyDownHandler.bind(this.paddle), false);
    document.addEventListener("keyup", this.paddle.keyupHandler.bind(this.paddle), false);
  }

  game_start(){
    this.ctx.clearRect(0,0,this.node.width,this.node.height)
    this.ball.draw(this.ctx)
    this.paddle.draw(this.ctx)
    this.paddle.move(this.node)
    this.block.draw(this.ctx)
    this.BallCollisionDetection()
    this.BlockCollisionDetection()
  }

  BallCollisionDetection(){
      if (this.ball.y+this.ball.dy <this.ball.rabius) {
        this.ball.dy = -this.ball.dy
        this.ball.y +=   this.ball.rabius
      }
      if(this.ball.x+this.ball.dx > this.node.width - this.ball.rabius || this.ball.x+this.ball.dx < this.ball.rabius){
        this.ball.dx = -this.ball.dx
      }
      if (Math.abs(this.paddle.y+(this.paddle.height/2)- this.ball.y) <= this.ball.rabius ) {
        if (this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x +1) {
          this.ball.dy = -this.ball.dy
          this.ball.dx = -this.ball.dx
          this.ball.x -= 2
        }
        else if(this.ball.x >= this.paddle.x + this.paddle.width -1 && this.ball.x <= this.paddle.x + this.paddle.width){
          this.ball.dy = -this.ball.dy
          this.ball.dx = -this.ball.dx
          this.ball.x += 2
        }else if (this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width) {
         this.ball.dy = -this.ball.dy
         this.ball.y += this.ball.rabius
        }

      }
      else if (Math.abs(this.paddle.y-(this.paddle.height/2)- this.ball.y) <= this.ball.rabius  ) {
        if (this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x +1) {
          this.ball.dy = -this.ball.dy
          this.ball.dx = -this.ball.dx
          this.ball.y = Math.abs(this.paddle.y-(this.paddle.height/2)) - this.ball.rabius
          this.ball.x -= 2
        }else if(this.ball.x >= this.paddle.x + this.paddle.width -1 && this.ball.x <= this.paddle.x + this.paddle.width){
          this.ball.dy = -this.ball.dy
          this.ball.dx = -this.ball.dx
          this.ball.y = Math.abs(this.paddle.y-(this.paddle.height/2)) - this.ball.rabius
          this.ball.x += 2

        }else if (this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width) {
          this.ball.dy = -this.ball.dy
          this.ball.y = Math.abs(this.paddle.y-(this.paddle.height/2)) - this.ball.rabius
         }
      }
      if ( this.ball.y+this.ball.dy >this.node.height) this.game_over()

      //  this.ball.dy = -this.ball.dy
      // this.ball.y -= this.ball.rabius


    this.ball.x += this.ball.dx;
    this.ball.y += this.ball.dy;
  }

  BlockCollisionDetection(){
    this.game_clear()
    for (let c = 0; c <this.block.col; c++) {
      for (let r = 0; r < this.block.row; r++) {
        let b =this.block.blocks[c][r]
        if (b.status == 1) {
          if (this.ball.x >b.x && this.ball.x< b.x +this.block.width && this.ball.y > b.y && this.ball.y < b.y+this.block.height) {
            this.ball.dy = -this.ball.dy;
            b.status = 0
          }
        }
      }
    }
  }

 game_clear(){
   let blocks_status =[]
   this.block.BlockStatusCheck(blocks_status)
   blocks_status = blocks_status.filter((bl)=>bl == true)
   if (blocks_status.length == []) {
     alert("ゲームクリア")
     clearInterval(this.intervalID)
   }
 }
  game_over(){
    alert("ゲームオーバー")
    clearInterval(this.intervalID)
  }
}

const game = new Game("#myCanvas");
game.intervalID=setInterval(function (params) {
  game.game_start()
},10)

// game.game_start()
// this.ball.y = (Math.abs(this.paddle.y-(this.paddle.height/2)- this.ball.y) <= this.ball.rabius) ?
          //   Math.abs(this.paddle.y-(this.paddle.height/2)) - this.ball.rabius
          //   :
          //   null
// Math.abs(this.paddle.y+(this.paddle.height/2)) - this.ball.rabius

// if (Math.abs(this.paddle.y+(this.paddle.height/2)- this.ball.y) <= this.ball.rabius ) {
          //   this.ball.y -= this.paddle.height
 // }

// this.ball.y = (Math.abs(this.paddle.y-(this.paddle.height/2)- this.ball.y) <= this.ball.rabius) ?
              // Math.abs(this.paddle.y-(this.paddle.height/2)) - this.ball.rabius
              // :
              // Math.abs(this.paddle.y+(this.paddle.height/2)) - this.ball.rabius
          // this.ball.y =  - this.ball.rabius
          // this.ball.dy = -this.ball.dy
          // this.ball.dx = -this.ball.dx
          // this.ball.dx *= -1
          // this.ball.dy *= -1


// if (Math.abs(this.paddle.y+(this.paddle.height/2)- this.ball.y) <= this.ball.rabius ) {
          //   this.ball.y -= this.paddle.height
          // }
          // this.ball.y = (Math.abs(this.paddle.y-(this.paddle.height/2)- this.ball.y) <= this.ball.rabius) ?
          // Math.abs(this.paddle.y-(this.paddle.height/2)) - this.ball.rabius
          // :
          // Math.abs(this.paddle.y+(this.paddle.height/2)) - this.ball.rabius

          // this.ball.x += 1

          // this.ball.y = this.paddle.y - this.ball.rabius
          // this.ball.dy = -this.ball.dy
          // this.ball.dy *= -1






   // console.log);
    // this.game_clear()
      // if (this.ball.y + this.ball.dy >= this.paddle.y - this.paddle.height && this.ball.y+this.ball.dy >= this.paddle.y) {

          // if (this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width ) {
          //   this.ball.dy = -this.ball.dy
          //   this.ball.dx *= 1
          // }
      // }

         // this.ball.dx *= 1
        // if ( Math.abs(this.paddle.x-(this.paddle.width/2)- this.ball.x)< this.ball.x ||  Math.ads()) {
        //   this.ball.dy = -this.ball.dy
        // }

        // if ( this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width ) {
        //   this.ball.dy = -this.ball.dy
        // }




      // }else if (this.ball.y+this.ball.dy > this.paddle.y-this.paddle.height ) {
      // }else if ( this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width && Math.abs(this.paddle.y+(this.paddle.height/2)- this.ball.y) < this.ball.rabius ) {
      //   this.ball.dy = -this.ball.dy
        // }else if(this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width && this.ball.y + this.ball.dy >= this.paddle.y - this.paddle.height && this.ball.y+this.ball.dy >= this.paddle.y){
      //  else if ( this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width && Math.abs(this.paddle.y-(this.paddle.height/2)- this.ball.y) <= this.ball.rabius) {
      //   this.ball.dy = -this.ball.dy
      // }
      // ||Math.abs(this.paddle.y+(this.paddle.height/2)-this.ball.y) == this.ball.rabius
      // }else if ( this.ball.x >= this.paddle.x && this.ball.x <= this.paddle.x + this.paddle.width && this.ball.y+this.ball.dy >= this.paddle.y-this.paddle.height && this.ball.y+this.ball.dy <= this.paddle.y) {
      //   this.ball.dy = -this.ball.dy
      // }
      // }else if(this.ball.x >=this.paddle.x-parseInt((this.paddle.x/2)) && this.ball.x <= this.paddle.x+parseInt((this.paddle/2))){
      //   console.log("tt");
      //   this.ball.dy = -this.ball.dy
      // }


    //   if(this.ball.y+this.ball.dy >  this.paddle.y  ){
    //     }
    // // }
    // if (this.ball.y+this.ball.dy >this.node.height-this.ball.rabius) {
    //   this.ball.dy = -this.ball.dy
    // }

//if (ball.y >= paddle.y - ball.size && ball.y <= paddle.y + ball.size && ball.x >= paddle.x - (paddle.size / 2) && ball.x <= paddle.x + (paddle.size / 2)) {
  // ball.dy *= -1;
  // }
  // 10
  //
// console.log(`ball(x:${this.ball.x},y${this.ball.y}`);
// console.log(`paddle(x:${this.ball.x},y${this.ball.y}`);
<file_sep>// キャンバス
let canvas = document.querySelector('#myCanvas')
let ctx = canvas.getContext('2d')
// パドル
let paddleHeight = 10
let paddleWidth = 75
let paddleX = (canvas.width - paddleWidth)/2

let rightPressed = false
let leftPressed = false

// ボール
let x = canvas.width/2;
let y = canvas.height-30;
let dx = -2;
let dy = -2;

let ballRabius = 10

// ブロック
let brickRowCount = 3;
let brickColumnCount = 5;
let brickWidth = 75;
let brickHeight =20;
let brickPadding = 5;
let brickOffsetTop = 30;
let brickOffsetLeft = 30;

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

function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      let 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 drawBricks() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      if (bricks[c][r].status == 1) {
        let brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
        let 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 keyDownHandler(e) {
  console.log(e.key);
  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 drawBall(){
  ctx.beginPath();
  ctx.arc(x, y, ballRabius, 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 draw() {
  ctx.clearRect(0,0,canvas.width,canvas.height)
  drawBall()
  drawBricks();
  drawPaddle()
  collisionDetection()
  if (rightPressed && paddleX < canvas.width-paddleWidth) {
    paddleX += 7
  }else if (leftPressed && paddleX > 0) {
    paddleX -=7
  }

  if (y+dy < ballRabius ) {
    dy = -dy
  }else if ( y+dy > canvas.height - ballRabius) {
    if (x>paddleX && x<paddleX+paddleWidth) {
      dy = -dy
    }else{
      clearInterval(interval)
      alert("GAME OVER")
    }

  }
  if (x+dx > canvas.width -ballRabius|| x+dx < ballRabius) {
    dx = -dx
  }
  x += dx;
  y += dy;
}

let interval=setInterval(draw,10)
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyupHandler, false);


class Game {
  constructor(){
    // this.ball = Ball()
    // this.paddle = Paddle()
    // this.block = Block()
  }
  start(){
    console.log("dd");
  }

}

const game = new Game();
game.start();

class Ball{
  constructor(){
    // this.ball = Ball()
    // this.paddle = Paddle()
    // this.block = Block()
  }
}
class Paddle{
  constructor(){
    // this.ball = Ball()
    // this.paddle = Paddle()
    // this.block = Block()
  }
}

class Block{
  constructor(){
  }
}
// if (y+dy<0) {
//   dy = -dy
// }
// if (y+dy > canvas.height) {
//   dy = -dy
// }
// ctx.fillStyle ="green"
// ctx.fillRect(10,10,100,100)
// ctx.beginPath();
// ctx.rect(10,0,50,50);
// ctx.fillStyle = "#FF0000";
// ctx.fill();
// ctx.closePath();

// ctx.beginPath();
// ctx.arc(240,160,20,0,Math.PI*2,false);
// ctx.fillStyle = "green";
// ctx.fill();
// ctx.closePath();

// ctx.beginPath();
// ctx.rect(160, 10, 100, 40);
// ctx.strokeStyle = "rgba(0, 0, 255, 0.5)";
// ctx.stroke();
// ctx.closePath()
