トップへ(mam-mam.net/)

JavaScriptでブロック崩しゲーム作成|HTML5&Canvasで簡単実装

JavaScriptでブロック崩しゲーム作成|HTML5&Canvasで簡単実装

JavaScriptでブラウザ上で遊べるブロック崩しゲームを作成しました!
マウスやタッチ操作でバーを移動し、クリックまたはタップでゲームを開始できます。
コピペOKのソースコード付きなので、すぐに実装可能!
ぜひ、ブロック崩しの爽快感をブラウザで体験してみてください!

ソースコード

ソースコードは以下です。

<div id="blockmain"></div>

<script>
class TBlock{
  init(){
    this.racket={x:this.wh/2-30, y:this.wh-60, w:60, h:20};
    //ボールは中心
    this.ball={
      x:this.racket.x + this.racket.w/2, 
      y:this.racket.y-6, 
      r:6,
      rx:+(Math.random()*0.1-0.05), ry:-4,
      speed:4,
      stopping:true,
    };
  }
  stageinit(){
    for(let i=0;i<this.stages[this.stageno].length;i++){
      this.stage[i]=[];
      this.stage[i].x = this.stages[this.stageno][i].x;
      this.stage[i].y = this.stages[this.stageno][i].y;
      this.stage[i].w = this.stages[this.stageno][i].w;
      this.stage[i].h = this.stages[this.stageno][i].h;
      this.stage[i].hp= this.stages[this.stageno][i].hp;
    }
    this.stagehp=this.stageshp[this.stageno];
  }
  constructor(elm){
    this.wh=600;
    this.div=elm;
    this.div.style.cssText="margin:0 auto;padding:0;max-width:100%;width:600px;height:600px;box-sizing:border-box;border:1px solid #000;";
    this.can=document.createElement("canvas");
    this.can.style.cssText="margin:0;padding:0;width:100%;height:100%;";
    this.can.setAttribute("width" , this.wh+"px");
    this.can.setAttribute("height", this.wh+"px");
    this.ctx=this.can.getContext("2d",{willReadFrequently:true});
    this.div.appendChild(this.can);
    this.blockcolor=["none","blue", "green", "red", "orange", "yellow"];
    this.init();
    /*
      横 5 50 10 ・・・ 50 10 50 5
      縦 20 20 20 20 20 20 20 20
    */
    this.stageno=0;
    this.stageshp=[];
    this.stage=[];
    this.stages=[];
    let ct;
    ct=0;
    this.stageshp[0]=0;
    this.stages[0]=[];
    for(let y=0;y<8;y++){
      for(let x=0;x<8;x++){
        this.stages[0][ct]=[];
        this.stages[0][ct].x =  0+x*75;
        this.stages[0][ct].y = 40+y*40;
        this.stages[0][ct].w = 70;
        this.stages[0][ct].h = 40;
        this.stages[0][ct].hp = 1+Math.floor(Math.random()*3);
        this.stageshp[0]+=this.stages[0][ct].hp;
        ct++;
      }
    }
    ct=0;
    this.stageshp[1]=0;
    this.stages[1]=[];
    for(let y=0;y<9;y++){
      for(let x=0;x<8;x++){
        this.stages[1][ct]=[];
        this.stages[1][ct].x =  0+x*75;
        this.stages[1][ct].y = 40+y*40;
        this.stages[1][ct].w = 70;
        this.stages[1][ct].h = 40;
        this.stages[1][ct].hp = 2+Math.floor(Math.random()*2);
        this.stageshp[1]+=this.stages[1][ct].hp;
        ct++;
      }
    }
    ct=0;
    this.stageshp[2]=0;
    this.stages[2]=[];
    for(let y=0;y<10;y++){
      for(let x=0;x<8;x++){
        this.stages[2][ct]=[];
        this.stages[2][ct].x =  0+x*75;
        this.stages[2][ct].y = 40+y*40;
        this.stages[2][ct].w = 70;
        this.stages[2][ct].h = 40;
        this.stages[2][ct].hp = 2+Math.floor(Math.random()*2);
        this.stageshp[2]+=this.stages[2][ct].hp;
        ct++;
      }
    }
    ct=0;
    this.stageshp[3]=0;
    this.stages[3]=[];
    for(let y=0;y<10;y++){
      for(let x=0;x<8;x++){
        this.stages[3][ct]=[];
        this.stages[3][ct].x =  0+x*75;
        this.stages[3][ct].y = 40+y*40;
        this.stages[3][ct].w = 70;
        this.stages[3][ct].h = 40;
        this.stages[3][ct].hp = 3+Math.floor(Math.random()*3);
        this.stageshp[3]+=this.stages[3][ct].hp;
        ct++;
      }
    }
    ct=0;
    this.stageshp[4]=0;
    this.stages[4]=[];
    for(let y=0;y<11;y++){
      for(let x=0;x<8;x++){
        this.stages[4][ct]=[];
        this.stages[4][ct].x =  0+x*75;
        this.stages[4][ct].y = 40+y*40;
        this.stages[4][ct].w = 70;
        this.stages[4][ct].h = 40;
        this.stages[4][ct].hp = 4+Math.floor(Math.random()*2);
        this.stageshp[4]+=this.stages[4][ct].hp;
        ct++;
      }
    }
    this.stageinit();
    document.documentElement.addEventListener("mousemove",function(){
      let newx=(event.clientX-this.can.getBoundingClientRect().left)*this.wh/this.styleWidth;
      if(newx<0){newx=0;}
      if(newx>(this.wh-this.racket.w)){newx=this.wh-this.racket.w;}
      if(this.ball.stopping){
        let subx=newx-this.racket.x;
        this.ball.x+=subx;
      }
      this.racket.x=newx;
      //console.log(newx);
    }.bind(this));
    document.documentElement.addEventListener("mousedown",function(){
      this.ball.stopping=false;
    }.bind(this));
    document.documentElement.addEventListener("touchmove",function(){
      let newx=(event.touches[0].pageX-this.can.getBoundingClientRect().left)*this.wh/this.styleWidth;
      if(newx<0){newx=0;}
      if(newx>(this.wh-this.racket.w)){newx=this.wh-this.racket.w;}
      if(this.ball.stopping){
        let subx=newx-this.racket.x;
        this.ball.x+=subx;
      }
      this.racket.x=newx;
      //console.log(newx);
    }.bind(this));
    
    //ウィンドウ リサイズ時
    window.addEventListener('resize',function(){
      this.resize();
    }.bind(this));
    this.resize();
    setInterval(this.interval.bind(this),16);
  }
  interval(){
    if(!this.ball.stopping){
      let nx=this.ball.x+this.ball.rx;
      let ny=this.ball.y+this.ball.ry;
      if(nx<this.ball.r||nx>(this.wh-this.ball.r)){
        this.ball.rx=-this.ball.rx;
      }else if(ny<this.ball.r){
        this.ball.ry=-this.ball.ry;
      }else if(ny>this.wh){
        this.init();
      }else if(
               (nx>=this.racket.x)&&(nx<=(this.racket.x+this.racket.w))&&
               (ny>=this.racket.y)&&(ny<=(this.racket.y+this.racket.h))&&
               (this.ball.ry>0)
               ){
        let subx=(nx-this.racket.x-this.racket.w/2+this.ball.rx)/this.racket.w *2/3 +(Math.random()*0.06-0.03);
        this.ball.rx=-Math.cos((subx+0.5)*Math.PI)*this.ball.speed;
        this.ball.ry=-Math.sin((subx+0.5)*Math.PI)*this.ball.speed;
      }else{
        let collision=false;
        for(let i=0;i<this.stage.length;i++){
          if( (this.stage[i].hp>0)&&
              (this.stage[i].x<=nx)&&
              ((this.stage[i].x+this.stage[i].w)>=nx)&&
              (this.stage[i].y<=ny)&&
              ((this.stage[i].y+this.stage[i].h)>=ny)
            ){
            collision=true;
            this.stage[i].hp--;
            this.ball.speed+=0.01;
            if(Math.abs(this.ball.rx)<0.001){
              this.ball.ry=-this.ball.ry;
            }else if( (this.stage[i].x>=this.ball.x)&&((this.stage[i].x+this.stage[i].w)<=this.ball.x) ){
              this.ball.ry=-this.ball.ry;
            }else{
              let y=0;
              //y=(y2-y1)(x-x1)/(x2-x1)+y1
              if(this.ball.rx>0){
                y=(ny-this.ball.y)*(this.stage[i].x-this.ball.x)/(nx-this.ball.x)+this.ball.y;
              }else{
                y=(ny-this.ball.y)*((this.stage[i].x+this.stage[i].w)-this.ball.x)/(nx-this.ball.x)+this.ball.y;
              }
              if( (y<=this.stage[i].y) || (y>=(this.stage[i].y+this.stage[i].h)) ){
                this.ball.ry=-this.ball.ry;
              }else{
                this.ball.rx=-this.ball.rx;
              }
            }
            break;
          }
        }
        if(collision){
          this.stagehp--;
          if(this.stagehp==0){
            this.stageno++;
            if(this.stageno==this.stages.length){this.stageno=0;}
            this.init();
            this.stageinit();
          }
        }else{
          this.ball.x+=this.ball.rx;
          this.ball.y+=this.ball.ry;
        }
      }
    }
    this.draw();
  }
  draw(){
    //キャンバスのクリア
    this.ctx.clearRect(0,0,this.wh,this.wh);
    this.ctx.fillStyle="rgb(220,220,220)";
    this.ctx.fillRect(0,0,this.wh,this.wh);
    for(let i=0;i<this.stage.length;i++){
      if(this.stage[i].hp>0){
        this.ctx.fillStyle=this.blockcolor[this.stage[i].hp];
        this.ctx.fillRect(
          this.stage[i].x,
          this.stage[i].y,
          this.stage[i].w,
          this.stage[i].h
        );
        this.ctx.lineWidth=2;
        this.ctx.strokeStyle="black";
        this.ctx.strokeRect(
          this.stage[i].x,
          this.stage[i].y,
          this.stage[i].w,
          this.stage[i].h
        );
      }
    }
    this.ctx.fillStyle="black";
    this.ctx.fillRect(this.racket.x,this.racket.y,this.racket.w,this.racket.h);
    this.ctx.fillStyle="black";
    this.ctx.beginPath();
    this.ctx.arc(this.ball.x, this.ball.y, this.ball.r, 0,Math.PI*2);
    this.ctx.fill();
  }
  
  resize(){
    let style=window.getComputedStyle(this.div);
    this.div.style.height=style.width;
    this.styleWidth=parseFloat(style.width);
  }
}
window.addEventListener("load",function(){
  block=new TBlock(document.querySelector("#blockmain"));
});
</script>