js 學習四 對象應用 吃貨遊戲

遊戲來源於 Mdn學習網站canvas

該例子用於對象的理解很是有效(建議看完上面網站的內容在開始練習)數組

彈球

body {

        margin: 0;
        
        overflow: hidden;
        
        font-family: "PingFangSC-Regular", "微軟雅黑", sans-serif;
        
        height: 100%;

}

  

h1 {
        
        font-size: 2rem;
        
        letter-spacing: \-1px;
        
        position: absolute;
        
        margin: 0;
        
        top: \-4px;
        
        right: 5px;
        
          
        
        color: transparent;
        
        text-shadow: 0  0  4px  white;
        
}

p {

        position: absolute;
        
        margin: 0;
        
        top: 35px;
        
        right: 5px;
        
        color: #aaa;
        
}

  

彈球

  

//彈球的個數

const  BALLS\_COUNT  \=  25;

//彈球的半徑範圍

const  BALL\_SIZE\_MIN  \=  10;

const  BALL\_SIZE\_MAX  \=  20;

// 彈球的速度

const  BALL\_SPEED\_MAX  \=  7;

// 設定畫布

var  canvas  \=  document.querySelector("canvas");

var  pcount  \=  document.querySelector("p");

var  ctx  \=  canvas.getContext("2d");

//獲取屏幕的寬高 並設置爲畫布的寬高

var  width  \=  (canvas.width  \=  window.innerWidth);

var  height  \=  (canvas.height  \=  window.innerHeight);

  

// 生成隨機數的函數

function  random(min,  max)  {

        return  Math.floor(Math.random()  \*  (max  \-  min))  +  min;
        
}

  

// 生成隨機顏色的函數

function  randomColor()  {

    return  (
    "rgb("  + random(0,  255)  + ", "  + random(0,  255)  + ", "  +random(0,  255)  + ")"); 
}

  

//定義形狀

function  Shape(x,  y,  velX,  velY,  exists)  {

        this.x  \=  x;
        
        this.y  \=  y;
        
        this.velX  \=  velX;
        
        this.velY  \=  velY;
        
        this.exists  \=  exists;

}

  

// 建立彈球對象

function  Ball(x,  y,  velX,  velY,  color,  size,  exists)  {

        Shape.call(this,  x,  y,  velX,  velY,  exists);
        
        this.color  \=  color;
        
        this.size  \=  size;

}

Ball.prototype  \=  Object.create(Shape.prototype);

Ball.prototype.constructor  \=  Ball;

// 定義繪製球的函數

Ball.prototype.draw  \=  function()  {

        ctx.beginPath();
        
        ctx.fillStyle  \=  this.color;
        
        ctx.arc(this.x,  this.y,  this.size,  0,  2  \*  Math.PI);
        
        ctx.fill();
        
};

//更新跳球的位置

Ball.prototype.update  \=  function()  {

            //到達右邊,反彈
            
            if  (this.x  +  this.size  \>=  width)  {
            
            this.velX  \=  \-this.velX;
            
            }
            
            //到達左邊,反彈
            
            if  (this.x  \-  this.size  <=  0)  {
            
            this.velX  \=  \-this.velX;
            
            }
            
            //到達底部,反彈
            
            if  (this.y  +  this.size  \>=  height)  {
            
            this.velY  \=  \-this.velY;
            
            }
            
            //到達頂部 反彈
            
            if  (this.y  \-  this.size  <=  0)  {
            
            this.velY  \=  \-this.velY;
            
            }
            
              
            
            this.x  +=  this.velX;
            
            this.y  +=  this.velY;
            
            };
            
            //彈球的碰撞處理
            
            Ball.prototype.collisionDetect  \=  function()  {
            
            for  (var  j  \=  0;  j  <  balls.length;  j++)  {
            
            //是否是彈球自己
            
            if  (balls\[j\]  \===  this)  continue;
            
              
            
            var  dx  \=  this.x  \-  balls\[j\].x;
            
            var  dy  \=  this.y  \-  balls\[j\].y;
            
            var  distance  \=  Math.sqrt(dx  \*  dx  +  dy  \*  dy);
            
            //碰撞改變兩個球的顏色
            
            if  (distance  <  this.size  +  balls\[j\].size)  {
            
            this.color  \=  balls\[j\].color  \=  randomColor();
            
            }
            
            }
            
};

//定義一個小吃貨

function  EvilCircle(x,  y,  exists)  {

Shape.call(this,  x,  y,  20,  20,  exists);

this.color  \=  "white";

this.size  \=  10;

}

EvilCircle.prototype  \=  Object.create(Shape.prototype);

EvilCircle.prototype.constructor  \=  EvilCircle;

// 定義繪製小吃貨的函數

EvilCircle.prototype.draw  \=  function()  {

        ctx.beginPath();
        
        ctx.strokeStyle  \=  this.color;
        
        ctx.arc(this.x,  this.y,  this.size,  0,  2  \*  Math.PI);
        
        ctx.stroke();

};

// 檢查小吃貨是否碰壁

EvilCircle.prototype.checkBounds  \=  function()  {

            if  (this.x  +  this.size  \>=  width)  {
            
            this.velX  \=  \-this.velX;
            
            }
            
              
            
            if  (this.x  \-  this.size  <=  0)  {
            
            this.x  \=  this.size;
            
            }
            
              
            
            if  (this.y  +  this.size  \>=  height)  {
            
            this.y  \=  height  \-  this.size;
            
            }
            
              
            
            if  (this.y  \-  this.size  <=  0)  {
            
            this.y  \=  this.size;
            
            }
            
};

// 定義小吃貨移動函數

EvilCircle.prototype.setControls  \=  function()  {

            window.onkeydown  \=  e  \=>  {
            
            if  (e.key  \===  "a")  {
            
            this.x  \-=  this.velX;
            
            }  else  if  (e.key  \===  "d")  {
            
            this.x  +=  this.velX;
            
            }  else  if  (e.key  \===  "w")  {
            
            this.y  \-=  this.velY;
            
            }  else  if  (e.key  \===  "s")  {
            
            this.y  +=  this.velY;
            
            }
            
            //上下左右移動
            
            if  (e.key  \===  "ArrowLeft")  {
            
            this.x  \-=  this.velX;
            
            }  else  if  (e.key  \===  "ArrowRight")  {
            
            this.x  +=  this.velX;
            
            }  else  if  (e.key  \===  "ArrowUp")  {
            
            this.y  \-=  this.velY;
            
            }  else  if  (e.key  \===  "ArrowDown")  {
            
            this.y  +=  this.velY;
            
            }
            
};

};

//小吃貨碰撞到了彈球

EvilCircle.prototype.collisionDetect  \=  function()  {

            for  (var  j  \=  0;  j  <  balls.length;  j++)  {
            
            //彈球沒被吃
            
            if  (balls\[j\].exists)  {
            
            var  dx  \=  this.x  \-  balls\[j\].x;
            
            var  dy  \=  this.y  \-  balls\[j\].y;
            
            var  distance  \=  Math.sqrt(dx  \*  dx  +  dy  \*  dy);
            
              
            
            if  (distance  <  this.size  +  balls\[j\].size)  {
            
            //標記彈球被吃
            
            balls\[j\].exists  \=  false;
            
            }
            
            }
            
            }

};

//激活小吃貨

EvilCircle.prototype.run  \=  function()  {

            this.draw();
            
            this.checkBounds();
            
            this.collisionDetect();

};

  

//建立吃貨

var  evilCircle  \=  new  EvilCircle(20,  20,  true);

evilCircle.setControls();

// 定義一個數組來保存全部的球

var  balls  \=  \[\];

  

pcount.textContent  \=  "還剩"  +  BALLS\_COUNT  +  "個球";

  

for  (let  i  \=  0;  i  <  BALLS\_COUNT;  i++)  {

            var  size  \=  random(BALL\_SIZE\_MIN,  BALL\_SIZE\_MAX);
            
            var  ball  \=  new  Ball(
            
            // 爲避免繪製錯誤,球至少離畫布邊緣球自己一倍寬度的距離
            
            random(0  +  size,  width  \-  size),
            
            random(0  +  size,  height  \-  size),
            
            random(\-BALL\_SPEED\_MAX,  BALL\_SPEED\_MAX),
            
            random(\-BALL\_SPEED\_MAX,  BALL\_SPEED\_MAX),
            
            randomColor(),
            
            size,
            
            true
            
            );
            
            balls.push(ball);

}

// 定義一個循環來不停地播放

function  loop()  {
                
                background("rgb(0, 0, 0)");
                
                for  (var  i  \=  0;  i  <  balls.length;  i++)  {
                
                if  (!balls\[i\].exists)  {
                
                continue;
                
                }
                
                balls\[i\].draw();
                
                balls\[i\].update();
                
                balls\[i\].collisionDetect();
                
                }
                
                  
                
                evilCircle.run();
                
                var  newballs  \=  balls.filter(balls  \=>  balls.exists);
                
                pcount.textContent  \=  "還剩"  +  newballs.length  +  "個球";
                
                  
                
                requestAnimationFrame(loop);

}

  

function  background(color)  {

            ctx.fillStyle  \=  color;
            
            ctx.fillRect(0,  0,  width,  height);
            
            ctx.beginPath();
            
}

  

loop();
相關文章
相關標籤/搜索