国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript貪吃蛇小組件實(shí)例代碼

2019-11-19 15:44:10
字體:
供稿:網(wǎng)友

1 寫在前面

看來《JavsScript高級(jí)編程》,想做一個(gè)小demo練練自己的手,選擇了貪吃蛇游戲。由于以前都是用c#寫的,將貪吃蛇寫到一個(gè)類里面,然后一個(gè)一個(gè)小方法的拆分,只向外提供需要提供的方法。這樣就可以將貪吃蛇作為一個(gè)模塊,任何地方都可以復(fù)用的。然而,用js進(jìn)行編寫的時(shí)候,由于不能很好的利用js語言的特性進(jìn)行模塊化編程,所以第一版的實(shí)現(xiàn)完全采用面向過程的方式,將函數(shù)中所需要的變量全部聲明為全局變量。雖然這樣也能夠?qū)崿F(xiàn)功能,但是做不到復(fù)用,而且定義非常多的最頂層變量,污染了全局變量。寫完之后,總想將自己寫的重新封裝一次,達(dá)到只向外提供必須要提供的變量、或者功能函數(shù)接口。查了一些許多資料,對(duì)于js的封裝可以采用閉包的方式來進(jìn)行實(shí)現(xiàn)。通過在函數(shù)內(nèi)部聲明局部變量和閉包函數(shù)來當(dāng)做類型的私有變量和函數(shù),然后通過this給對(duì)象向外提供需要開發(fā)的接口。

2 貪吃蛇組件的使用

2.1 初級(jí)示例

示例代碼1如下:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>貪吃蛇組件</title></head><body> <canvas width="600" height="600" id="gameScense"></canvas></body><script src="SnakeGame.js"></script><script> var snakeGame = new SnakeGame("gameScense",{ }); snakeGame.startGame();</script></html>

首先引入SnakeGame.js組件,然后通過實(shí)例化 SnakeGame對(duì)象,并向SnakeGame構(gòu)造函數(shù)傳入兩個(gè)參數(shù)。第一參數(shù)是canvas的id,第二個(gè)參數(shù)游戲配置的對(duì)象,如果為空的話,那么采用默認(rèn)的配置。最后,調(diào)用對(duì)象的startGame()方法,即可實(shí)現(xiàn)貪吃蛇的邏輯。默認(rèn)的方向控制鍵為上下左右按鍵、暫停為空格,效果如下:

我們可以通過更改實(shí)例化時(shí)傳入的配置對(duì)象來實(shí)現(xiàn)對(duì)游戲的更多控制。

 示例代碼2:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>貪吃蛇組件</title></head><body> <canvas width="600" height="600" id="gameScense"></canvas></body><script src="SnakeGame.js"></script><script> var snakeGame = new SnakeGame("gameScense",{  snakeColor:"red",  foodColor:"green",  scenseColor:"blue",  directionKey:[68,83,65,87], }); snakeGame.startGame();</script></html>

通過參數(shù)的名字可以知道,配置蛇、食物、游戲背景的顏色,以及控制游戲的方向鍵。配置方向順序?yàn)椤咀螅拢遥稀俊PЧ缦拢?/p>

當(dāng)然還有更加多的配置。還能夠定義分?jǐn)?shù)改變的回調(diào)的函數(shù),以及游戲結(jié)束時(shí)的回調(diào)函數(shù)等。下面介紹一下配置參數(shù),以及SnakeGame對(duì)象共有的方法。

2.2 公有方法

•startGame() : 開始游戲。在該方法內(nèi),會(huì)初始化各種設(shè)置。如,重置分?jǐn)?shù),蛇身,速度等。

•changeGameStatus():改變游戲狀態(tài),即暫停和開始,SnakeGame對(duì)象里面有一個(gè)私有變量,作為游戲的狀態(tài)變量。

2.3 配置游戲參數(shù)的對(duì)象gameConfigObj屬性、

gameConfigObj 對(duì)象一共該有10個(gè)屬性,3個(gè)回調(diào)函數(shù)

屬性

•size : 蛇塊和食物的大小,默認(rèn)20
•rowCount : 行,默認(rèn)30行
•colCount : 列,默認(rèn)30列
•snakeColor : 蛇身顏色,默認(rèn)green
•foodColor : 食物顏色,默認(rèn)yellow
•scenseColor : 游戲場(chǎng)景背景色, 默black
•directionKey : 方向鍵, 默認(rèn)[39, 40, 37, 38] 上下左右
•pasueKey : 暫停鍵, 默認(rèn)32,空格鍵
•levelCount : 速度等級(jí)控制,默認(rèn)10.
•curSpeed : 初始速度,默認(rèn)200毫秒

回調(diào)函數(shù)

•onCountChange : 事件,每一個(gè)食物,分?jǐn)?shù)改變,并調(diào)用該方法,帶有一個(gè)參數(shù)(count)

•onGamePause : 事件,游戲狀態(tài)改變時(shí),調(diào)用該方法,帶有一個(gè)參數(shù) 1,代表暫停,0 ,代表游戲在進(jìn)行。

•onGameOver : 事件,游戲結(jié)束時(shí),調(diào)用該方法。

2.4使用進(jìn)階

通過上面的屬性我們可以設(shè)計(jì)一個(gè)交互性更加強(qiáng)的程序。代碼如下。

 示例3

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>貪吃蛇組件</title> <style type="text/css">  *{   margin:0px;   padding:0px;  }  #gamebd{   width:850px;   margin:50px auto;  }  #gameScense{   background-color:green;   float:left;  }  #gameSet{   margin-left:10px;   float:left;  }  .gameBoxStyle{   margin-bottom:7px;   padding:5px 10px;  }  .gameBoxStyle h3{   margin-bottom:7px;  }  .gameBoxStyle p{   line-height: 1.7em;  }  .gameBoxStyle input{   margin-top:7px;   background-color: white;   border:1px gray solid;   padding:3px 9px;   margin-right:9px;  }  .gameBoxStyle input[type=text]{   width:90px;  }  .gameBoxStyle input:hover{   background-color: #e2fff2;  }  .gameBoxStyle #txtValue{   color:red;  } </style></head><body><div id="gamebd"> <canvas id="gameScense" width="600" height="600"> </canvas> <div id="gameSet">  <div id="gameControl" class="gameBoxStyle">   <h3>游戲控制</h3>   <p>方向鍵:上,下,左,右</p>   <p>開始/暫停:空格</p>  </div>  <div id="gameStatus" class="gameBoxStyle">   <h3>游戲狀態(tài)</h3>   <p>用戶名:<input type="text" placeholder="輸入用戶名:" id="txtUserName" value="游客123"/> </p>   <p>當(dāng)前用戶1得分:<span id="txtValue">0</span></p>   <input type="button" value="開始游戲" id="btnStart"/>   <input type="button" value="暫停" id="btnPause"/>  </div>  <div id="game" class="gameBoxStyle">   <h3>游戲記錄</h3>   <a href="#" rel="external nofollow" rel="external nofollow" >查看歷史記錄</a>  </div> </div></div><script src="js/SnakeGame.js"></script></body><script src="SnakeGame.js"></script><script> var btnStart=document.getElementById("btnStart"); var btnPasue=document.getElementById("btnPause"); var gameSnake = new SnakeGame("gameScense",{  snakeColor:"red",  onCountChange:function(count){   var txtScore=document.getElementById("txtValue");   txtScore.innerText=count.toString( );   txtScore=null;  },  onGamePause:function(status){   if(status){    btnPasue.value = "開始";   }else {    btnPasue.value = "暫停"   }  },  onGameOver:function (status) {   alert("游戲結(jié)束");  } }); btnStart.onclick=function(event){  if(checkUserName()){   gameSnake.startGame();   btnStart.blur();  } } btnPasue.onclick=function(event) {  gameSnake.changeGameStatus();  btnStart.blur(); } function checkUserName(){  var txtUserName = document.getElementById("txtUserName");  if(txtUserName.value.length==0){   alert("用戶名不能為空");   return false;  }else {   return true;  } }</script></html>

上面的代碼通過設(shè)置OnChangeCount、onGamePause、onGameOver,三個(gè)回調(diào)函數(shù),實(shí)現(xiàn)界面與組件的交互。效果如下:

在《JavaScript高級(jí)編程》這本書中說道一個(gè)模塊模式,但是這種模式是單例模式,也就是閉包最后返回一個(gè)字面量的對(duì)象。但是我需要在一個(gè)頁面中能夠同時(shí)開啟兩個(gè)貪吃蛇的窗口,兩個(gè)游戲通過設(shè)置配置不同的方向鍵和按鈕操作,實(shí)現(xiàn)兩個(gè)人同時(shí)一起玩。所以,在實(shí)現(xiàn)SnakeGame組件時(shí),沒有采用道格拉斯所說的模塊模式。下面演示一下,如何在一個(gè)頁面中,讓兩個(gè)人同時(shí)一起玩游戲。代碼如下: 

示例4

首先建立一個(gè)html文件

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Jaume's貪吃蛇</title> <link rel="stylesheet" href="css/gameStyle.css" rel="external nofollow" ></head><body><div id="gamebd"> <canvas id="gameScense" width="600" height="600"> </canvas> <canvas id="gameScense1" width="600" height="600" style="background-color: black"> </canvas> <div id="gameSet">  <div id="gameControl" class="gameBoxStyle">   <h3>游戲控制</h3>   <p>方向鍵:上,下,左,右</p>   <p>開始/暫停:空格</p>  </div>  <div id="gameStatus" class="gameBoxStyle">   <h3>游戲狀態(tài)</h3>   <p>當(dāng)前用戶1得分:<span id="txtValue">0</span></p>   <p>當(dāng)前用戶2得分:<span id="txtValue1">0</span></p>   <input type="button" value="開始游戲" id="btnStart"/>  </div>  <div id="game" class="gameBoxStyle">   <h3>游戲記錄</h3>   <a href="#" rel="external nofollow" rel="external nofollow" >查看歷史記錄</a>  </div> </div></div><script src="js/SnakeGame.js"></script><script src="js/UIScript.js"></script></body></html>

樣式文件如下:

*{ margin:0px; padding:0px;}#gamebd{ /*width:850px;*/ /*margin:50px auto;*/ width:100%;}#gameScense{ background-color:green; float:left;}#gameSet{ margin-left:10px; float:left;}.gameBoxStyle{ margin-bottom:7px; padding:5px 10px;}.gameBoxStyle h3{ margin-bottom:7px;}.gameBoxStyle p{ line-height: 1.7em;}.gameBoxStyle input{ margin-top:7px; background-color: white; border:1px gray solid; padding:3px 9px; margin-right:9px;}.gameBoxStyle input[type=text]{ width:90px;}.gameBoxStyle input:hover{ background-color: #e2fff2;}.gameBoxStyle #txtValue{ color:red;}

在html中拖入了兩個(gè)文件,一個(gè)是貪吃蛇組件,另一個(gè)是UIScript.js,其中的代碼如下:

/** * Created by tjm on 8/16/2017. */var btnStart=document.getElementById("btnStart");var gameSnake = new SnakeGame("gameScense",{ snakeColor:"red", directionKey:[68,83,65,87], pauseKey:81, onCountChange:function(count){  var txtScore=document.getElementById("txtValue");  txtScore.innerText=count.toString( );  txtScore=null; }, onGameOver:function (status) {  alert("游戲結(jié)束"); }});var gameSnake1 = new SnakeGame("gameScense1",{ snakeColor:"green", size:20, onCountChange:function(count){  var txtScore=document.getElementById("txtValue1");  txtScore.innerText=count.toString();  txtScore=null; }, onGameOver:function (status) {  alert("游戲結(jié)束"); }});btnStart.onclick=function(event){  gameSnake.startGame();  gameSnake1.startGame();  btnStart.blur();}

實(shí)例化兩個(gè)SnakeGame對(duì)象,一個(gè)對(duì)象使用默認(rèn)的上下左右鍵和空格鍵作為方向鍵和暫停鍵,而另一個(gè)使用了,W、A、S、D 以及 Q 作為方向鍵和暫停鍵。效果如下:

嗯哼,沒錯(cuò),完美實(shí)現(xiàn)了。使用SnakeGame這個(gè)組件,創(chuàng)建貪吃蛇游戲就是如此的簡單。下面簡單介紹一下,組件的實(shí)現(xiàn)方式。

3貪吃蛇組件實(shí)現(xiàn)方式

在上一節(jié)中就提到過,沒有采用過道哥拉斯的設(shè)計(jì)模式,下面給出貪吃蛇設(shè)計(jì)結(jié)構(gòu)。具體的源代碼,可以在后面的鏈接中進(jìn)行下載。代碼如下:

/** * Created by tjm on 8/18/2017. */var SnakeGame = function () { /*蛇塊和食物組件類*/ function SnakeBlock(row,col){  this.row=row;  this.col=col; } SnakeBlock.prototype.draw = function(graphic,color,size){  graphic.fillStyle=color;  graphic.fillRect(size*this.col,size*this.row,size-2,size-2); } SnakeBlock.prototype.clearDraw = function(graphic,color,size){  graphic.fillStyle=color;  graphic.fillRect(size*this.col,size*this.row,size,size); } SnakeBlock.prototype.equal = function(snakeBlock){  if(snakeBlock.row==this.row && snakeBlock.col==this.col){   return true;  }else{   return false;  } } /*貪吃蛇組件類*/ function SnakeGame(gameScenseId, gameConfigObj) {  // 私有屬性  var gameScense = document.getElementById(gameScenseId);  var graphic = gameScense.getContext("2d");  var count = 0;  var snake;  var curFood;  var runId;  var isMoved = false;//方向改變后,如果沒有移動(dòng)則方向鍵暫時(shí)失效。  var gameStatus = false;  var curDirection = 1;  var size = gameConfigObj.size || 20;  var rowCount = gameConfigObj.rowCount || 30;  var colCount = gameConfigObj.colCount || 30;  var snakeColor = gameConfigObj.snakeColor || "green";  var foodColor = gameConfigObj.foodColor || "yellow";  var scenseColor = gameConfigObj.scenseColor || "black";  var directionKey = gameConfigObj.directionKey || [39, 40, 37, 38];  var pauseKey = gameConfigObj.pauseKey || 32;  var levelCount = gameConfigObj.levelCount || 10;  var curSpeed = gameConfigObj.curSpeed || 200;  //公開事件  var onCountChange = gameConfigObj.onCountChange || null; //帶有一個(gè)參數(shù)  var onGamePause = gameConfigObj.onGamePause || null; //帶有一個(gè)參數(shù)  var onGameOver = gameConfigObj.onGameOver || null;  //判斷  if(gameScense.width != size*rowCount || gameScense.height != size*colCount){   throw "場(chǎng)景大小不等于行列大小*蛇塊大小";  }  //特權(quán)方法  this.startGame = startGame;  this.changeGameStatus = changeGameStatus;  //注冊(cè) dom 鍵盤事件  var preFunc = document.onkeydown;  document.onkeydown = function (e) {   var key = (e || event).keyCode;   handleKeyInput(key);   if (typeof preFunc == "function") {    preFunc(e);   }  }  //私有方法  /*初始化蛇身*/  function initSnake(){   ???  }  /*繪制場(chǎng)景背景色*/  function initScense(){   ???  }  /*產(chǎn)生食物*/  function genFood(){   ???  }  /*吃食物*/  function eatFood(snakeHead){   ???  }  /*判斷游戲是否結(jié)束*/  function gameOver(){   ???  }  /*蛇移動(dòng)*/  function snakeMove(){   ???  }  function changeSpeed(){   ???  }  function handleKeyInput(key){   ???  }  function initGame(){   ???  }  function triggerEvent(callback,argument){   ???  }  function runGame(){   ???  }  function pauseGame() {   ???  }  function changeGameStatus(){   ???  }  function startGame(){   ???  } } return SnakeGame; //最后返回一個(gè)組件構(gòu)造函數(shù)}();

上面有一個(gè)很重要的地方,就是鍵盤注冊(cè)的代碼,單獨(dú)列出來分析一下。

var preFunc = document.onkeydown;  document.onkeydown = function (e) {   var key = (e || event).keyCode;   handleKeyInput(key);   if (typeof preFunc == "function") {    preFunc(e);   }  }

該段代碼的邏輯是,首先判斷在 document 上是否注冊(cè)了onkeydown 事件,如果注冊(cè)了該事件,則保存所引用的事件處理程序,然后重置onkeydown事件程序,然后在新的事件處理程序中,調(diào)用先前的事件處理程序,這樣就實(shí)現(xiàn)了事件觸發(fā)后,調(diào)用所有監(jiān)聽該事件處理程序,而不是直接覆蓋。

另外關(guān)于貪吃蛇的設(shè)計(jì)邏輯,可以參看我另外一篇文章,個(gè)人覺得講的非常詳細(xì)了,文章:基于控制臺(tái)實(shí)現(xiàn)貪吃蛇游戲

3 小結(jié)

通過這次貪吃蛇組件的設(shè)計(jì),對(duì) js 的模塊化設(shè)計(jì)稍微了解了一下,但是,我也不知道上文所實(shí)現(xiàn)的貪吃蛇模塊有哪些缺陷,希望有大神看到這篇文章,能給一些指導(dǎo)。當(dāng)然了,該組件還可以進(jìn)行進(jìn)一步的擴(kuò)展,比如將游戲的方塊,替換成圖片。有興趣的可以從下面的鏈接進(jìn)行下載,更改后別忘了分享哦。

源碼下載鏈接:https://github.com/StartAction/SnakeGame

以上所述是小編給大家介紹的JavaScript貪吃蛇小組件實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 嘉善县| 通州区| 大石桥市| 宜君县| 临安市| 大宁县| 金乡县| 文水县| 合川市| 阜南县| 焦作市| 萨迦县| 海晏县| 淮南市| 抚州市| 普定县| 郴州市| 怀宁县| 玉龙| 治多县| 方正县| 白朗县| 吴忠市| 福建省| 泸水县| 平湖市| 明光市| 信丰县| 湘乡市| 临沭县| 古丈县| 德昌县| 夏邑县| 宁波市| 报价| 桃园市| 闽侯县| 三台县| 邳州市| 澄城县| 历史|