# 物件導向JS繼承 - 遊戲實作 ### **撰寫程式:HTML | CSS(SASS) | JS(jQuery ∕ 原生JS)** ###### codepen:https://codepen.io/liu_0821/pen/XWYZgRV ![](https://i.imgur.com/AuK70wH.jpg) ## HTML > ###### 原生HTML撰寫 ``` <div class="game"> <!--遊戲主體--> <div class="board b1"></div> <div class="board b2"></div> <div class="ball"></div> <div class="info"> <h2 class="infoText">Start Game</h2> <button class="start" onclick = "newGame.startGame()">開始</button> </div> <div class="grade"></div> </div> ``` **** ## CSS(SASS) > ###### 與原生CSS不同之處,原生CSS使用大括弧{}套用CSS特性,SASS則利用縮排區分HTML之間的層級關係。 ``` * font-family: "微軟正黑體" font-weight: 900 html,body background-color: #222 color: white display: flex justify-content: center align-items: center height: 100% margin: 0 .game width: 500px height: 500px position: relative border: 5px solid white overflow: hidden .board background-color: #ffab2d .ball background-color: white .info width: 100% height: 100% position: absolute left: 0 top: 0 background-color: #222 color: white display: flex justify-content: center align-items: center //垂直排列 flex-direction: column .start width: 80px height: 50px border-radius: 25px border: 1px solid white font-size: 18px background-color: #222 color: white cursor: pointer .grade padding: 10px ``` **** ## JS(jQuery ∕ 原生JS) > ###### 使用原生JS與jQuery撰寫,利用JS物件導向的繼承來作為整體程式開發的主軸。 ###### 遊戲物件與繼承範圍 ``` let gameObject = function(position,size,selector){ this.$el = $(selector); this.position = position; this.size = size ; this.$el.css("position","absolute"); this.updateCss(); // 把初始化的條件更新到螢幕上 }; // 更新遊戲物件 gameObject.prototype.updateCss = function(){ this.$el.css('left',this.position.x); this.$el.css('top',this.position.y); this.$el.css('width',this.size.width); this.$el.css('height',this.size.height); }; // 計算遊戲碰撞 gameObject.prototype.collide = function(otherObject){ // this => 與其他物件 var inRangeX = otherObject.position.x > this.position.x && otherObject.position.x < this.position.x + this.size.width; var inRangeY = otherObject.position.y > this.position.y && otherObject.position.y < this.position.y + this.size.height; // 回傳 是否有同時滿足在他的範圍內 return inRangeX && inRangeY }; ``` ###### 球體物件與更新 ``` // 球球物件 let Ball = function(){ this.size = {width:15,height:15} this.position = {x:250 ,y:250} this.velocity = {x:-3,y:5} // 球體速度 // 繼承三步驟 //1.呼叫初始化函數 gameObject.call(this,this.position,this.size,".ball") } //2.讓ball可以使用gameObject的函數 Ball.prototype = Object.create(gameObject.prototype); //3.將建構函數返回到自己原本建立的函數 Ball.prototype.constructor = Ball.constructor; // 球球速度更新 Ball.prototype.update = function(){ this.position.x += this.velocity.x; this.position.y += this.velocity.y; this.updateCss(); // 更新到母元素 // 計算球球什麼時候反彈 if(this.position.x < 0 || this.position.x > 500){ this.velocity.x = -this.velocity.x } if(this.position.y < 0 || this.position.y > 500){ this.velocity.y = -this.velocity.y } }; // 球球初始化 Ball.prototype.init = function(){ this.position = {x:250 ,y:250} // 球體速度 改成隨機速度 Math.random()原本是0~1的之間亂數 var speed = 8; var angle = Math.random()*Math.PI*2 this.velocity = { x: speed*Math.cos(angle), y: speed*Math.sin(angle) } this.update(); }; // 建立球球 let newBall = new Ball() // setInterval(function(){ // newBall.update() //呼叫球球移動 // },30) ``` ###### 設立板子物件 ``` let Board = function (position,selector){ this.size = {width:100,height:15} // 1.呼叫初始化函數 gameObject.call(this,position,this.size,selector) }; // 2.讓Board可以使用gameObject的函數 Board.prototype = Object.create(gameObject.prototype); // 3.將建構函數返回到自己原本建立的函數 Board.prototype.constructor = Board.constructor; // 檢查board1的板子不超出邊界 Board.prototype.update = function(){ // 計算左邊 if(this.position.x < 0){ this.position.x = 0; } // 計算右邊 if(this.position.x + this.size.width > 500){ this.position.x = 500 - this.size.width; } this.updateCss(); }; // 建立板子 let board1 = new Board( { x : 0 , y : 30},".b1" ); let board2 = new Board( { x : 0 , y : 455},".b2" ); ``` ###### 遊戲開始物件與綁定鍵盤事件 ``` let Game = function(){ this.timer = null; this.grade = 0 ; // 執行鍵盤事件 this.initControl(); this.control = {}; // 新增物件管理鍵盤按的變數 } // 使用者控制 綁定鍵盤事件 Game.prototype.initControl = function(){ let _this = this; $(window).keydown(function(evt){ _this.control[evt.key] = true ; console.log(_this.control) }); $(window).keyup(function(evt){ _this.control[evt.key] = false ; console.log(_this.control) }); } //設定遊戲開始之前的倒數 Game.prototype.startGame = function(){ var _this = this ; var time = 3; this.grade = 0; // 初始分數為0 newBall.init(); //球球初始化 $("button").hide(); var timer = setInterval(function(){ $(".infoText").text(time); time--; if(time<0){ clearInterval(timer) $(".info").hide(); _this.startGameMain() } },1000); }; // 建立遊戲函數 Game.prototype.startGameMain = function(){ let _this = this; //代表game的this // 偵測球體碰撞、輸贏狀態 this.timer = setInterval(function(){ // 判斷板子有無碰撞到球 if(board1.collide(newBall)){ console.log("hit 1") // 打到後回彈 newBall.velocity.y = -newBall.velocity.y; //打到板子後球體速度會變化 newBall.velocity.x *= 1.1; newBall.velocity.y *= 1.1; newBall.velocity.x += 0.5-Math.random(); newBall.velocity.y += 0.5-Math.random(); } if(board2.collide(newBall)){ console.log("hit 2") newBall.velocity.y = -newBall.velocity.y; _this.grade += 10; } // 判斷有無撞到邊界 if(newBall.position.y < 0){ console.log("Board 1 lose") _this.endGame("computer lose") } if(newBall.position.y > 500){ console.log("Board 2 lose") _this.endGame("you lose") } // 判斷鍵盤按鍵 if(_this.control["ArrowLeft"]){ board2.position.x -= 12; } if(_this.control["ArrowRight"]){ board2.position.x += 12; } // 上方板子移動(以中心點來判斷,如果球在右邊向右跑,反之) // 如果滿足條件就+8,反之+0 board1.position.x += newBall.position.x > board1.position.x + board1.size.width/2 ? 12:0 ; board1.position.x += newBall.position.x < board1.position.x + board1.size.width/2 ? -12:0 ; // 呼叫板子更新css board1.update() ; board2.update() ; newBall.update(); //遊戲內更新自己的成績 $(".grade").text(_this.grade) },30) }; // 遊戲結束計算 Game.prototype.endGame = function(res){ clearInterval(this.timer) $(".info").show(); $("button").show(); $(".infoText").html(res + "<br>分數:" + this.grade); }; let newGame = new Game(); //newGame.startGame(); // 呼叫遊戲開始 ``` ##### ヽ(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人(゚∀゚)人( ゚∀)ノヽ(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人( ゚∀)人 ##### 以上 如果註解哪裡有錯誤或有問題,歡迎提出來一起討論~~~~ ---