遊戲來源於 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();