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

首頁 > 編程 > JavaScript > 正文

jQuery編寫網頁版2048小游戲

2019-11-19 18:06:15
字體:
來源:轉載
供稿:網友

大致介紹

看了一個實現網頁版2048小游戲的視頻,覺得能做出自己以前喜歡玩的小游戲很有意思便自己動手試了試,真正的驗證了這句話-不要以為你以為的就是你以為的,看視頻時覺得看懂了,會寫了,但是自己實現起來會遇到各種問題。比如,在最后判斷游戲是否結束的時候,我寫的語句語法是對的,但就是不執行。最后通過對視頻源碼的分析對比,發現原作者寫的一個setTimeout定時器有額外的意思,本來我以為它就是簡單的一個延時動畫,其實他是在等待另外一個函數執行完畢。-_-||。最后還是很高興能寫出來,也改進了一些源代碼的不足。

這篇博客并不是詳細的講解,只是大致介紹函數的作用,其中實現的細節注釋中有解釋,網上的這個源碼有點亂,如果想看比較整齊的源碼或者視頻的可以QQ聯系我(免費)(找共同學習的伙伴)

思路

這個小游戲可以抽象化分為3層(我覺得這樣能更好理解)

◆最底下的一層是基本的樣式(可見的)

◆中間的層是最主要的,是一個4x4的二維數組,游戲中我們都是對這個二維數組進行操作(不可見的)

◆最上面的一層也是一個4x4的二維數組,它只是根據第二層數組的每個數顯示樣式(可見的)

我們通過最底下的一層顯示最基本的16個小方格,通過鍵盤的按鍵或者手指在屏幕的滑動來操作中間層的數組,最后在通過最上面的一層顯示出數字

基本結構與樣式

基本的結構和樣式都挺簡單,直接看代碼

結構:

<div id="test2048"> <div id="header">  <h1>2048</h1>  <a href="javascript:newgame()" >開始新的游戲</a>  <p>分數:<span id="score">0</span></p> </div> <div id="container">  <div class="cell" id="cell-0-0"></div>  <div class="cell" id="cell-0-1"></div>  <div class="cell" id="cell-0-2"></div>  <div class="cell" id="cell-0-3"></div>  <div class="cell" id="cell-1-0"></div>  <div class="cell" id="cell-1-1"></div>  <div class="cell" id="cell-1-2"></div>  <div class="cell" id="cell-1-3"></div>  <div class="cell" id="cell-2-0"></div>  <div class="cell" id="cell-2-1"></div>  <div class="cell" id="cell-2-2"></div>  <div class="cell" id="cell-2-3"></div>  <div class="cell" id="cell-3-0"></div>  <div class="cell" id="cell-3-1"></div>  <div class="cell" id="cell-3-2"></div>  <div class="cell" id="cell-3-3"></div> </div> </div>

樣式:

*{ margin: 0; padding: 0;}#test2048{ font-family: Arial; margin: 0 auto; text-align: center;}#header{ margin: 20px;}#header a{ font-family: Arial; text-decoration: none; display: block; color: white; margin: 20px auto; width: 125px; height: 35px; text-align: center; line-height: 40px; background-color: #8f7a66; border-radius: 10px; font-size: 15px;}#header p{ font-family: Arial; font-size: 20px;}#container{ width: 460px; height: 460px; background-color: #bbada0; margin: 0 auto; border-radius: 10px; position: relative; padding: 20px;}.cell{ width: 100px; height: 100px; border-radius: 6px; background-color: #ccc0b3; position: absolute;}

從CSS樣式可以看出,我們并沒有對每個格子的位置進行設置,因為如果用CSS給每個格子設置樣式代碼量太大,而且他們的位置有一定的規律,所以我們可以用js循環來完成每個格子樣式的設置

代碼:

// 初始化棋盤格function initialize(){ for(var i=0;i<4;i++){  for(var j=0;j<4;j++){   // 設置棋盤格的位置   var everyCell = $('#cell-'+ i +'-'+ j);   everyCell.css({top:getPos(i),left:getPos(j)});  } }}
// 獲取位置function getPos(num){ return 20 + num*120;}

這樣我們的第一層就好了

效果:

 

現在構造第二層,即構建一個4x4的值全部為0的數組,由于在構造第二層時,有兩層循環,所以我們可以在構造第一層時也能構造第二層

第三層是用js生成16個格子,它和第一層的16個格子一一對應

代碼:

// 數字格function numFormat(){ for(var i=0;i<4;i++){  for(var j=0;j<4;j++){   $('#container').append('<div class="number" id="number-'+ i +'-'+ j +'"></div>')   // 設置數字格的位置,樣式   var everyNumber = $('#number-'+ i +'-'+ j);   if(checkerboard[i][j] == 0){    everyNumber.css({     width:'0px',     height:'opx',     top:getPos(i) + 50,     left:getPos(j) + 50    })   }else{    everyNumber.css({     width:'100px',     height:'100px',     top:getPos(i),     left:getPos(j),backgroundColor:getBackgroundColor(checkerboard[i][j]),     color:getColor(checkerboard[i][j])    });    everyNumber.text(checkerboard[i][j]);   }  } }}
// 獲取相應數字的背景顏色function getBackgroundColor(number){ switch (number) {  case 2:return "#eee4da";break;  case 4:return "#ede0c8";break;  case 8:return "#f2b179";break;  case 16:return "#f59563";break;  case 32:return "#f67c5f";break;  case 64:return "#f65e3b";break;  case 128:return "#edcf72";break;  case 256:return "#edcc61";break;  case 512:return "#9c0";break;  case 1024:return "#33b5e5";break;  case 2048:return "#09c";break;  case 4096:return "#a6c";break;  case 8192:return "#93c";break; }}
// 設置相應數字的文字顏色function getColor(number){ if (number <= 4) {  return "#776e65" } return "white";}

初始化

在每次游戲重新開始時,都會在隨機的位置出現兩個隨機的數字,我們寫一個在隨機位置出現一個隨機數的函數,只要調用兩次就可以實現了

代碼:

// 隨機的在一個位置上產生一個數字function randomNum(){ // 隨機產生一個坐標值 var randomX = Math.floor(Math.random() * 4); var randomY = Math.floor(Math.random() * 4); // 隨機產生一個數字(2或4) var randomValue = Math.random() > 0.5 ? 2 : 4; // 在數字格不為0的地方生成一個隨機數字 while(true){  if(checkerboard[randomX][randomY] == 0){   break;  }else{   var randomX = Math.floor(Math.random() * 4);   var randomY = Math.floor(Math.random() * 4);  } } // 將隨機產生的數字顯示在隨機的位置上 checkerboard[randomX][randomY] = randomValue; // 動畫 randomNumAnimate(randomX,randomY,randomValue);}
// 隨機產生數字的動畫function randomNumAnimate(randomX,randomY,randomValue){ var randomnum = $('#number-'+ randomX +'-'+ randomY); randomnum.css({  backgroundColor:getBackgroundColor(randomValue),  color:getColor(randomValue), })    .text(randomValue)    .animate({     width:'100px',     height:'100px',     top:getPos(randomX),     left:getPos(randomY)    },50);}

基本操作

我們通過switch循環,來根據用戶不同的輸入進行不同的操作

代碼:

// 獲取鍵盤事件,檢測不同的按鍵進行不同的操作$(document).keydown(function(event){ switch(event.keyCode){  case 37://左   if(canMoveLeft(checkerboard)){    // 如果可以向左移動    MoveLeft();    // 向左移動    setTimeout(function(){     randomNum();    },200);    // 隨機產生一個數字   }   break;  case 38://上   if(canMoveUp(checkerboard)){    // 如果可以向上移動    MoveUp();    // 向上移動    setTimeout(function(){     randomNum();    },200);    // 隨機產生一個數字   }   break;  case 39://右   if(canMoveRight(checkerboard)){    // 如果可以向右移動    MoveRight();    // 向右移動    setTimeout(function(){     randomNum();    },200);    // 隨機產生一個數字   }   break;  case 40://下   if(canMoveDown(checkerboard)){    // 如果可以向下移動    MoveDown();    // 向下移動    setTimeout(function(){     randomNum();    },200);    // 隨機產生一個數字   }   break;  default:   break; }});

由于數字格的移動只有左、上、右、下四種方式,并且他們都是大同小異的,所以就拿向左移動為例,

向左移動,我們首先需要判斷它是否能向左移動,能向左移動有兩種情況

第一種:當前格子的左邊的格子是空的即值為0

第二種:當前格子的值和左邊格子的值相同

由于向左移動,所以第一列的格子不可能向左移動,所以不需要判斷

代碼:

// 判斷是否可以向左移動function canMoveLeft(checkerboard){ for(var i=0;i<4;i++){  for(var j=1;j<4;j++){   if(checkerboard[i][j] != 0){    // 如果這個數字格它左邊的數字格為空或者左邊的數字格和它相等,則可以向左移動    if(checkerboard[i][j-1] == 0 || checkerboard[i][j] == checkerboard[i][j-1]){     return true;    }   }  } } return false;}

判斷能否向左移動后,我們就要對可以移動的格子進行移動,這里需要特別注意,向哪個方向移動就要先從哪個方向開始判斷

代碼:

// 向左移動function MoveLeft(){ for(var i=0;i<4;i++){  for(var j=1;j<4;j++){   if(checkerboard[i][j] != 0){    for(var k=0;k<j;k++){     if(checkerboard[i][k] == 0 && noMiddleNumRow(i,k,j,checkerboard)){      moveAnimation(i,j,i,k);      checkerboard[i][k] = checkerboard[i][j];      checkerboard[i][j] = 0;     }else if(checkerboard[i][k] == checkerboard[i][j] && noMiddleNumRow(i,k,j,checkerboard) && !hasConflicted[i][k]){      moveAnimation(i,j,i,k);      checkerboard[i][k] += checkerboard[i][j];      checkerboard[i][j] = 0;     }    }   }  } } // 設置刷新的時間是為了讓運動的動畫走完在進行更新數字格,否則數字格運動的動畫將會被打斷 setTimeout(function(){  numFormat(); },200);}
// 判斷中間的數字格是否為0(行)function noMiddleNumRow(row,col1,col2,checkerboard){ for(var i=col1+1;i<col2;i++){  if(checkerboard[row][i] != 0){   return false;  } } return true;}

將上、右、下四個方向寫完以后,游戲基本的操作就已經完成了。

游戲分數和判斷游戲結束

游戲的分數是每個相加的數的和,所以我們在每個數相加的時候更新分數就可以了

代碼:

// 更新分數score += checkerboard[k][j];updateScore(score);
 // 設置分數function updateScore(num){ $('#score').text(num);}

判斷游戲是否結束很簡單,用我們之前定義的方法就可以實現

代碼:

// 判斷游戲是否結束function wheGameOver(checkerboard){ if(!canMoveLeft(checkerboard) && !canMoveUp(checkerboard) && !canMoveRight(checkerboard) && !canMoveDown(checkerboard) ){  showGameOver(); }}
// 顯示游戲結束function showGameOver(){ $('#container').append("<div id='gameover'><p>最終得分</p><span>"+ score +"</span><a href='javascript:resert();'>重新開始游戲</a></div> ")}// 重新開始游戲function resert(){ $('#gameover').remove(); newgame();}

最后優化

1、游戲中會出現一次移動,一個數會被累加很多次

在原游戲中,每個數在每次操作中只能累加一次,所以我們在定義一個4x4的值為false的數組,與中間層的數組一一對應,專門用來防止一個數的多次累加,如果是false則可以累加,并將值改為false,否則不可以累加

2、結束死循環

由于在設置隨機數的時候用到了一個死循環,但是在游戲結束后,該循環還在,所以我們在死循環中在添加一個條件,如果游戲結束就跳出循環

3、最后的結束游戲提示不執行

case 37://左   if(canMoveLeft(checkerboard)){    // 如果可以向左移動    MoveLeft();    // 向左移動    setTimeout(function(){     wheGameOver(checkerboard)    },300);    // 判斷游戲是否結束,這里設置延時是因為要等到隨機產生數字后再進行判斷,如果不加    // 延時,則最后一次的判斷因為canMoveLeft(checkerboard)為false就不會再執行了    setTimeout(function(){     randomNum();    },200);    // 隨機產生一個數字   }   break;

從代碼中可以看出,判斷游戲是否結束是在隨機產生一個數字前執行的,所以在判斷游戲結束時,總是有一個空的格子,所以代碼執行后認為游戲沒有結束,但是當這個隨機數字產生后,所有的格子不能移動,當我們按鍵時,if條件不通過,判斷游戲是否結束的函數不能執行。所以我們要給判斷游戲結束的函數設置定時器,讓他在隨機產生一個數字后再進行判斷

4、在移動端可以執行

由于原作者沒有寫有關移動端的操作,所以我在網上找的判斷移動端觸屏手機滑動位置的代碼,加入了游戲的事件就可以執行了

//返回角度    function GetSlideAngle(dx, dy) {     return Math.atan2(dy, dx) * 180 / Math.PI;    }    //根據起點和終點返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑動    function GetSlideDirection(startX, startY, endX, endY) {     var dy = startY - endY;     var dx = endX - startX;     varresult = 0;     //如果滑動距離太短     if(Math.abs(dx) < 2 && Math.abs(dy) < 2) {      returnresult;     }     var angle = GetSlideAngle(dx, dy);     if(angle >= -45 && angle < 45) {      result = 4;     }else if (angle >= 45 && angle < 135) {      result = 1;     }else if (angle >= -135 && angle < -45) {      result = 2;     }     else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {      result = 3;     }     return result;    }    //滑動處理    var startX, startY;    document.addEventListener('touchstart',function (ev) {     startX = ev.touches[0].pageX;     startY = ev.touches[0].pageY;    }, false);    document.addEventListener('touchend',function (ev) {     var endX, endY;     endX = ev.changedTouches[0].pageX;     endY = ev.changedTouches[0].pageY;     var direction = GetSlideDirection(startX, startY, endX, endY);     switch(direction) {      case 0:       //沒滑動       break;      case 1:       if(canMoveUp(checkerboard)){      // 如果可以向上移動      MoveUp();      // 向上移動      setTimeout(function(){       wheGameOver(checkerboard)      },300);      // 判斷游戲是否結束      setTimeout(function(){       randomNum();      },200);      // 隨機產生一個數字      }       break;      case 2:       if(canMoveDown(checkerboard)){      // 如果可以向下移動      MoveDown();      // 向下移動      setTimeout(function(){       wheGameOver(checkerboard)      },300);      // 判斷游戲是否結束      setTimeout(function(){       randomNum();      },200);      // 隨機產生一個數字      }       break;      case 3:       if(canMoveLeft(checkerboard)){      // 如果可以向左移動      MoveLeft();      // 向左移動      setTimeout(function(){       wheGameOver(checkerboard)      },300);      // 判斷游戲是否結束,這里設置延時是因為要等到隨機產生數字后再進行判斷,如果不加      // 延時,則最后一次的判斷因為canMoveLeft(checkerboard)為false就不會再執行了      setTimeout(function(){       randomNum();      },200);      // 隨機產生一個數字      }       break;      case 4:       if(canMoveRight(checkerboard)){      // 如果可以向右移動      MoveRight();      // 向右移動      setTimeout(function(){       wheGameOver(checkerboard)      },300);      // 判斷游戲是否結束      setTimeout(function(){       randomNum();      },200);      // 隨機產生一個數字      }       break;      default:        }    }, false);

總結

總體來說這個游戲實現起來并不是太難,就是許多小的操作集合起來

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持武林網!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永和县| 马龙县| 昌乐县| 罗城| 承德市| 巴林左旗| 博爱县| 谢通门县| 林周县| 塘沽区| 无棣县| 灵台县| 巩留县| 榆社县| 沙雅县| 屏边| 丹凤县| 永州市| 林甸县| 金塔县| 苗栗市| 漳浦县| 乐山市| 新晃| 星子县| 灵川县| 南陵县| 天全县| 琼中| 甘洛县| 增城市| 广宁县| 德阳市| 望江县| 自贡市| 正阳县| 山阴县| 虞城县| 岗巴县| 玛多县| 江华|