欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

jQuery實(shí)現(xiàn)貪吃蛇小游戲(附源碼下載)

 更新時(shí)間:2017年03月04日 15:33:54   作者:Corner  
網(wǎng)上關(guān)于JS實(shí)現(xiàn)貪吃蛇的文章有很多,最近閑來無事,想著利用jQury來實(shí)現(xiàn)貪吃蛇小游戲,下面實(shí)現(xiàn)這篇文章主要介紹了利用jQuery實(shí)現(xiàn)貪吃蛇小游戲的方法,文中給出的是吸納思路和示例代碼,需要的朋友可以參考下。

前言

相信貪吃蛇的游戲大家都玩過。在那個(gè)水果機(jī)還沒有流行,人手一部諾基亞的時(shí)代,貪吃蛇是手機(jī)中的必備游戲。筆者閑的無聊的時(shí)候就拿出手機(jī)來玩上幾局,挑戰(zhàn)一下自己的記錄。

后來上大學(xué)了,用c語言做過貪吃蛇的游戲,不過主要是通過函數(shù)來控制(PS:現(xiàn)在讓我看代碼都看不懂(⊙﹏⊙))?,F(xiàn)在學(xué)習(xí)前端框架之后,通過jQuery來實(shí)現(xiàn)一個(gè)貪吃蛇的游戲效果,雖然游戲界面比(bu)較(ren)簡(zhi)陋(shi),但是主要學(xué)習(xí)一下游戲中面向?qū)ο蠛陀删植康秸w的思想。

設(shè)計(jì)思想

在開始寫代碼前首先讓我們來構(gòu)思一下整體游戲的實(shí)現(xiàn)過程:

需要的對(duì)象

首先既然是貪吃蛇,那么游戲中肯定要涉及到兩個(gè)對(duì)象,一個(gè)是蛇的對(duì)象,另一個(gè)是食物的對(duì)象。食物對(duì)象肯定要有一個(gè)屬性就是食物的坐標(biāo)點(diǎn),蛇對(duì)象有一個(gè)屬性是一個(gè)數(shù)組,用來存放蛇身體所有的坐標(biāo)點(diǎn)。

如何移動(dòng)

另外全局需要有一個(gè)定時(shí)器來周期性的移動(dòng)蛇的身體。由于蛇的身體彎彎曲曲有各種不同的形狀,因此我們只處理蛇的頭部和尾部,每次移動(dòng)都根據(jù)移動(dòng)的方向的不同來添加新的頭部,再把尾部擦去,看起來就像蛇在向前爬行一樣。

方向控制

由于蛇有移動(dòng)的方向,因此我們也需要在全局定義一個(gè)方向?qū)ο?,?duì)象中有上下左右所代表的值。同時(shí),在蛇對(duì)象的屬性中我們也需要定義一個(gè)方向?qū)傩?,用來表示?dāng)前蛇所移動(dòng)的方向。

碰撞檢測

在蛇向前爬行的過程中,會(huì)遇到三種不同的情況,需要進(jìn)行不同的判斷檢測。第一種情況是吃到了食物,這時(shí)候就需要向蛇的數(shù)組中添加食物的坐標(biāo)點(diǎn);第二種情況是碰到了自己的身體,第三種是碰到了邊界,這兩種情況都導(dǎo)致游戲結(jié)束;如果不是上面的三種情況,蛇就可以正常的移動(dòng)。

開始編程

整體構(gòu)思有了,下面就開始寫代碼了。

搭建幕布

首先整個(gè)游戲需要一個(gè)搭建活動(dòng)的場景,我們通過一個(gè)表格布局來作為整個(gè)游戲的背景。

<style type="text/css">
#pannel table{
 border-collapse:collapse;
}
#pannel td{
 width: 10px;
 height: 10px;
 border: 1px solid #000;
}
#pannel td.food{
 background: green;
}
#pannel td.body{
 background: #f60;
}
</style>
<div id="pannel">
</div>
<select name="" id="palSize">
 <option value="10">10*10</option>
 <option value="20">20*20</option>
 <option value="40">30*30</option>
</select>
<select name="" id="palSpeed">
 <option value="500">速度-慢</option>
 <option value="250">速度-正常</option>
 <option value="100">速度-快</option>
</select>
<button id="startBtn">開始</button>

pannel就是我們的幕布,我們?cè)谶@個(gè)里面用td標(biāo)簽來畫上一個(gè)個(gè)的“像素點(diǎn)”。我們用兩種樣式來表現(xiàn)不同的對(duì)象,.body表示蛇的身體的樣式,.food表示食物的樣式。

var settings = {
 // pannel面板的長度
 pannelSize: 10,
 // 貪吃蛇移動(dòng)的速度
 speed: 500,
 // 貪吃蛇工作線程
 workThread: null,
};
function setPannel(size){
 var content = [];
 content.push('<table>');
 for(let i=0;i<size;i++){
 content.push('<tr>');
 for(let j=0;j<size;j++){
 content.push('<td class="td_'+i+'_'+j+'"></td>');
 }
 content.push('</tr>');
 }
 content.push('</table>');
 $('#pannel').html(content.join(''));
}
setPannel(settings.pannelSize);

我們定義了一個(gè)全局的settings用來存放全局性的變量,比如幕布的大小、蛇移動(dòng)的速度和工作的線程。然后通過一個(gè)函數(shù)把幕布畫了出來,最后的效果就是這樣:

方向和定位

既然我們的“舞臺(tái)”已經(jīng)搭建完了,怎么來定義我們“演員”的位置和移動(dòng)的方向呢。首先定義一個(gè)全局的方向變量,對(duì)應(yīng)的數(shù)值就是我們的上下左右方向鍵所代表的keyCode。

var Direction = {
 UP: 38,
 DOWN: 40,
 LEFT: 37,
 RIGHT: 39,
};

我們?cè)谏厦娈嬆徊嫉臅r(shí)候通過兩次遍歷畫出了一個(gè)類似于中學(xué)里學(xué)的坐標(biāo)系,有X軸和Y軸。如果每次都用{x:x,y:y}來表示會(huì)很(mei)麻(bi)煩(ge),我們可以定義一個(gè)坐標(biāo)點(diǎn)對(duì)象。

function Position(x,y){
 // 距離X軸長度,取值范圍0~pannelSize-1
 this.X = x || 0;
 // 距離Y軸長度,取值范圍0~pannelSize-1
 this.Y = y || 0;
}

副咖–食物

既然定義好了坐標(biāo)點(diǎn)對(duì)象,那么可以先來看一下簡單的對(duì)象,就是我們的食物(Food)對(duì)象,上面說了,它有一個(gè)重要的屬性就是它的坐標(biāo)點(diǎn)。

function Food(){
 this.pos = null;
 // 隨機(jī)產(chǎn)生Food坐標(biāo)點(diǎn),避開蛇身
 this.Create = function(){
 if(this.pos){
 this.handleDot(false, this.pos, 'food');
 }
 let isOk = true;
 while(isOk){
 let x = parseInt(Math.random()*settings.pannelSize),
 y = parseInt(Math.random()*settings.pannelSize);
 if(!$('.td_'+x+'_'+y).hasClass('body')){
 isOk = false;
 let pos = new Position(x, y);
 this.handleDot(true, pos, 'food');
 this.pos = pos;
 }
 }
 };
 // 畫點(diǎn)
 this.handleDot = function(flag, dot, className){
 if(flag){
 $('.td_'+dot.X+'_'+dot.Y).addClass(className);
 } else {
 $('.td_'+dot.X+'_'+dot.Y).removeClass(className);
 }
 };
}

既然食物有了坐標(biāo)點(diǎn)這個(gè)屬性,那么我們什么時(shí)候給他賦值呢?我們知道Food是隨機(jī)產(chǎn)生的,因此我們定義了一個(gè)Create函數(shù)用來產(chǎn)生Food的坐標(biāo)點(diǎn)。但是產(chǎn)生的坐標(biāo)點(diǎn)又不能在蛇的身體上,所以通過一個(gè)while循環(huán)來產(chǎn)生坐標(biāo)點(diǎn),如果坐標(biāo)點(diǎn)正確了,就終止循環(huán)。此外為了方便我們統(tǒng)一處理坐標(biāo)點(diǎn)的樣式,因此定義了一個(gè)handleDot函數(shù)。

主咖–蛇

終于到了我們的主咖,蛇。首先定義一下蛇基本的屬性,最重要的肯定是蛇的body屬性,每次移動(dòng)時(shí),都需要對(duì)這個(gè)數(shù)組進(jìn)行一些操作。其次是蛇的方向,我們給它一個(gè)默認(rèn)向下的方向。然后是食物,在蛇的構(gòu)造函數(shù)中我們傳入食物對(duì)象,在后續(xù)移動(dòng)時(shí)需要判斷是否吃到食物。

function Snake(myFood){
 // 蛇的身體
 this.body = [];
 // 蛇的方向
 this.dir = Direction.DOWN;
 // 蛇的食物
 this.food = myFood;
 // 創(chuàng)造蛇身
 this.Create = function(){
 let isOk = true;
 while(isOk){
 let x = parseInt(Math.random()*(settings.pannelSize-2))+1,
 y = parseInt(Math.random()*(settings.pannelSize-2))+1;
 console.log(x,y)
 if(!$('.td_'+x+'_'+y).hasClass('food')){
 isOk = false;
 let pos = new Position(x, y);
 this.handleDot(true, pos, 'body')
 this.body.push(pos);
 }
 }
 };
 this.handleDot = function(flag, dot, className){
 if(flag){
 $('.td_'+dot.X+'_'+dot.Y).addClass(className);
 } else {
 $('.td_'+dot.X+'_'+dot.Y).removeClass(className);
 }
 };
}

移動(dòng)函數(shù)處理

下面對(duì)蛇移動(dòng)的過程進(jìn)行處理,由于我們每次都采用添頭去尾的方式移動(dòng),因此我們每次只需要關(guān)注蛇的頭和尾。我們約定數(shù)組的第一個(gè)元素是頭,最后一個(gè)元素是尾。

this.Move = function(){
 let oldHead = Object.assign(new Position(), this.body[0]),
 oldTail = Object.assign(new Position(), this.body[this.body.length - 1]),
 newHead = Object.assign(new Position(), oldHead);
 switch(this.dir){
 case Direction.UP:
 newHead.X = newHead.X - 1;
 break;
 case Direction.DOWN:
 newHead.X = newHead.X + 1;
 break;
 case Direction.LEFT:
 newHead.Y = newHead.Y - 1;
 break;
 case Direction.RIGHT:
 newHead.Y = newHead.Y + 1;
 break;
 default:
 break;
 }
 // 數(shù)組添頭
 this.body.unshift(newHead);
 // 數(shù)組去尾
 this.body.pop();
};

檢測函數(shù)處理

這樣我們對(duì)蛇身數(shù)組就處理完了。但是我們還需要對(duì)新的頭(newHead)進(jìn)行一些碰撞檢測,判斷新頭部的位置上是否有其他東西(碰撞檢測)。

// 食物檢測
this.eatFood = function(){
 let newHead = this.body[0];
 if(newHead.X == this.food.pos.X&&newHead.Y == this.food.pos.Y){
 return true;
 } else {
 return false;
 }
};
// 邊界檢測
this.konckWall = function(){
 let newHead = this.body[0];
 if(newHead.X == -1 || 
 newHead.Y == -1 || 
 newHead.X == settings.pannelSize || 
 newHead.Y == settings.pannelSize ){
 return true;
 } else {
 return false;
 }
};
// 蛇身檢測
this.konckBody = function(){
 let newHead = this.body[0],
 flag = false;
 this.body.map(function(elem, index){
 if(index == 0)
 return;
 if(elem.X == newHead.X && elem.Y == newHead.Y){
 flag = true;
 }
 });
 return flag;
};

重新繪制

因此我們需要對(duì)Move函數(shù)進(jìn)行一些擴(kuò)充:

this.Move = function(){
 // ...數(shù)組操作
 if(this.eatFood()){
 this.body.push(oldTail);
 this.food.Create();
 this.rePaint(true, newHead, oldTail);
 } else if(this.konckWall() || this.konckBody()) {
 this.Over();
 } else {
 this.rePaint(false, newHead, oldTail);
 }
};
this.Over = function(){
 clearInterval(settings.workThread);
 console.log('Game Over');
};
this.rePaint = function(isEatFood, newHead, oldTail){
 if(isEatFood){
 // 加頭
 this.handleDot(true, newHead, 'body');
 } else {
 // 加頭
 this.handleDot(true, newHead, 'body');
 // 去尾
 this.handleDot(false, oldTail, 'body');
 }
};

因?yàn)樵贛ove函數(shù)處理數(shù)組的后我們的蛇身還沒有重新繪制,因此我們很巧妙地判斷如果是吃到食物的情況,在數(shù)組中就把原來的尾部添加上,這樣就達(dá)到了吃食物的效果。同時(shí)我們定義一個(gè)rePaint函數(shù)進(jìn)行頁面的重繪。

游戲控制器

我們的“幕布”、“演員”和“動(dòng)作指導(dǎo)”都已經(jīng)到位,那么,我們現(xiàn)在就需要一個(gè)“攝影機(jī)”進(jìn)行拍攝,讓它們都開始“干活”。

function Control(){
 this.snake = null;
 // 按鈕的事件綁定
 this.bindClick = function(){
 var that = this;
 $(document).on('keydown', function(e){
 if(!that.snake)
 return;
 var canChangrDir = true;
 switch(e.keyCode){
 case Direction.DOWN:
 if(that.snake.dir == Direction.UP){
 canChangrDir = false;
 }
 break;
 case Direction.UP:
 if(that.snake.dir == Direction.DOWN){
 canChangrDir = false;
 }
 break;
 case Direction.LEFT:
 if(that.snake.dir == Direction.RIGHT){
 canChangrDir = false;
 }
 break;
 case Direction.RIGHT:
 if(that.snake.dir == Direction.LEFT){
 canChangrDir = false;
 }
 break;
 default:
 canChangrDir = false;
 break;
 }
 if(canChangrDir){
 that.snake.dir = e.keyCode;
 }
 });
 $('#palSize').on('change',function(){
 settings.pannelSize = $(this).val();
 setPannel(settings.pannelSize);
 });
 $('#palSpeed').on('change',function(){
 settings.speed = $(this).val();
 });
 $('#startBtn').on('click',function(){
 $('.food').removeClass('food');
 $('.body').removeClass('body');
 that.startGame();
 });
 };
 // 初始化
 this.init = function(){
 this.bindClick();
 setPannel(settings.pannelSize);
 };
 // 開始游戲
 this.startGame = function(){
 var food = new Food();
 food.Create();
 var snake = new Snake(food);
 snake.Create();
 this.snake =snake;
 settings.workThread = setInterval(function(){
 snake.Move();
 },settings.speed);
 }
 this.init();
}

我們給document綁定一個(gè)keydown事件,當(dāng)觸發(fā)按鍵時(shí)改變蛇的移動(dòng)方向,但是如果和當(dāng)前蛇移動(dòng)方向相反時(shí)就直接return。最后的效果如下:


可以戳這里查看實(shí)現(xiàn)效果

點(diǎn)擊這里下載源碼

總結(jié)

實(shí)現(xiàn)了貪吃蛇的一些基本功能,比如移動(dòng)、吃點(diǎn)、控制速度等,頁面也比較的簡單,就一個(gè)table、select和button。后期可以添加一些其他的功能,比如有計(jì)分、關(guān)卡等,也可以添加多個(gè)點(diǎn),有的點(diǎn)吃完直接GameOver等等。

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • jquery取消事件冒泡的三種方法(推薦)

    jquery取消事件冒泡的三種方法(推薦)

    下面小編就為大家?guī)硪黄猨query取消事件冒泡的三種方法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-05-05
  • jquery 列表雙向選擇器之改進(jìn)版

    jquery 列表雙向選擇器之改進(jìn)版

    自己以前做的列表雙向選擇器,感覺有點(diǎn)挫,昨天閑著沒事改進(jìn)了一下,把元素改成了select option這樣就支持shift多選,感覺好多了
    2013-08-08
  • 教你一步步用jQyery實(shí)現(xiàn)輪播器

    教你一步步用jQyery實(shí)現(xiàn)輪播器

    相信大家應(yīng)該都會(huì)看到在各大網(wǎng)站上都有一個(gè)輪播器的效果,于是自己不禁也想做一個(gè),查了資料,看了輪播器的原理,慢慢的試著做了做,最終效果勉勉強(qiáng)強(qiáng),但還是想總結(jié)出來,或許對(duì)有需要的朋友們帶來一定的幫助,下面來一起看看吧。
    2016-12-12
  • Jquery on方法綁定事件后執(zhí)行多次的解決方法

    Jquery on方法綁定事件后執(zhí)行多次的解決方法

    下面小編就為大家?guī)硪黄狫query on方法綁定事件后執(zhí)行多次的解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06
  • jQuery 1.5.1 發(fā)布,全面支持IE9 修復(fù)大量bug

    jQuery 1.5.1 發(fā)布,全面支持IE9 修復(fù)大量bug

    jQuery 1.5.1發(fā)布了!這是自jQuery1.5發(fā)布以來第一個(gè)小版本更新,并且解決了很多BUG。
    2011-02-02
  • jQuery 相關(guān)控件的事件操作分解

    jQuery 相關(guān)控件的事件操作分解

    JQuery是非常棒的JS類庫,有豐富的UI庫和插件,不過我鐘愛他的是他的選擇器,感覺其他功能有時(shí)跟后臺(tái)人員距離很遠(yuǎn),所以一般我也只使用一下他的選擇器。
    2009-08-08
  • JQuery中的html()、text()、val()區(qū)別示例介紹

    JQuery中的html()、text()、val()區(qū)別示例介紹

    這篇文章主要介紹了JQuery中的html()、text()、val()的區(qū)別,需要的朋友可以參考下
    2014-09-09
  • Jquery實(shí)現(xiàn)搜索框提示功能示例代碼

    Jquery實(shí)現(xiàn)搜索框提示功能示例代碼

    數(shù)據(jù)量很大的情況下使用Ajax去實(shí)現(xiàn)真的不合適,于是想采用Jquery來實(shí)現(xiàn)方法,具體的示例代碼如下,有需求的朋友可以參考下希望對(duì)大家有所幫助
    2013-08-08
  • jQuery實(shí)現(xiàn)獲取隱藏div高度的方法示例

    jQuery實(shí)現(xiàn)獲取隱藏div高度的方法示例

    這篇文章主要介紹了jQuery實(shí)現(xiàn)獲取隱藏div高度的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了jQuery針對(duì)頁面元素屬性操作的相關(guān)技巧,需要的朋友可以參考下
    2017-02-02
  • jQuery表單域?qū)傩赃^濾器用法分析

    jQuery表單域?qū)傩赃^濾器用法分析

    這篇文章主要介紹了jQuery表單域?qū)傩赃^濾器用法,實(shí)例分析了:checked、:enabled、:disabled:、selected等常用表單域?qū)傩赃^濾器使用技巧,需要的朋友可以參考下
    2015-02-02

最新評(píng)論