您好,登錄后才能下訂單哦!
這篇文章主要介紹了jQuery怎么實現實現貪吃蛇小游戲,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
設計思想
在開始寫代碼前首先讓我們來構思一下整體游戲的實現過程:
需要的對象
首先既然是貪吃蛇,那么游戲中肯定要涉及到兩個對象,一個是蛇的對象,另一個是食物的對象。食物對象肯定要有一個屬性就是食物的坐標點,蛇對象有一個屬性是一個數組,用來存放蛇身體所有的坐標點。
如何移動
另外全局需要有一個定時器來周期性的移動蛇的身體。由于蛇的身體彎彎曲曲有各種不同的形狀,因此我們只處理蛇的頭部和尾部,每次移動都根據移動的方向的不同來添加新的頭部,再把尾部擦去,看起來就像蛇在向前爬行一樣。
方向控制
由于蛇有移動的方向,因此我們也需要在全局定義一個方向對象,對象中有上下左右所代表的值。同時,在蛇對象的屬性中我們也需要定義一個方向屬性,用來表示當前蛇所移動的方向。
碰撞檢測
在蛇向前爬行的過程中,會遇到三種不同的情況,需要進行不同的判斷檢測。第一種情況是吃到了食物,這時候就需要向蛇的數組中添加食物的坐標點;第二種情況是碰到了自己的身體,第三種是碰到了邊界,這兩種情況都導致游戲結束;如果不是上面的三種情況,蛇就可以正常的移動。
開始編程
整體構思有了,下面就開始寫代碼了。
搭建幕布
首先整個游戲需要一個搭建活動的場景,我們通過一個表格布局來作為整個游戲的背景。
<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就是我們的幕布,我們在這個里面用td標簽來畫上一個個的“像素點”。我們用兩種樣式來表現不同的對象,.body表示蛇的身體的樣式,.food表示食物的樣式。
var settings = { // pannel面板的長度 pannelSize: 10, // 貪吃蛇移動的速度 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);
我們定義了一個全局的settings用來存放全局性的變量,比如幕布的大小、蛇移動的速度和工作的線程。然后通過一個函數把幕布畫了出來,最后的效果就是這樣:
方向和定位
既然我們的“舞臺”已經搭建完了,怎么來定義我們“演員”的位置和移動的方向呢。首先定義一個全局的方向變量,對應的數值就是我們的上下左右方向鍵所代表的keyCode。
var Direction = { UP: 38, DOWN: 40, LEFT: 37, RIGHT: 39, };
我們在上面畫幕布的時候通過兩次遍歷畫出了一個類似于中學里學的坐標系,有X軸和Y軸。如果每次都用{x:x,y:y}來表示會很(mei)麻(bi)煩(ge),我們可以定義一個坐標點對象。
function Position(x,y){ // 距離X軸長度,取值范圍0~pannelSize-1 this.X = x || 0; // 距離Y軸長度,取值范圍0~pannelSize-1 this.Y = y || 0; }
副咖–食物
既然定義好了坐標點對象,那么可以先來看一下簡單的對象,就是我們的食物(Food)對象,上面說了,它有一個重要的屬性就是它的坐標點。
function Food(){ this.pos = null; // 隨機產生Food坐標點,避開蛇身 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; } } }; // 畫點 this.handleDot = function(flag, dot, className){ if(flag){ $('.td_'+dot.X+'_'+dot.Y).addClass(className); } else { $('.td_'+dot.X+'_'+dot.Y).removeClass(className); } }; }
既然食物有了坐標點這個屬性,那么我們什么時候給他賦值呢?我們知道Food是隨機產生的,因此我們定義了一個Create函數用來產生Food的坐標點。但是產生的坐標點又不能在蛇的身體上,所以通過一個while循環來產生坐標點,如果坐標點正確了,就終止循環。此外為了方便我們統一處理坐標點的樣式,因此定義了一個handleDot函數。
主咖–蛇
終于到了我們的主咖,蛇。首先定義一下蛇基本的屬性,最重要的肯定是蛇的body屬性,每次移動時,都需要對這個數組進行一些操作。其次是蛇的方向,我們給它一個默認向下的方向。然后是食物,在蛇的構造函數中我們傳入食物對象,在后續移動時需要判斷是否吃到食物。
function Snake(myFood){ // 蛇的身體 this.body = []; // 蛇的方向 this.dir = Direction.DOWN; // 蛇的食物 this.food = myFood; // 創造蛇身 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); } }; }
移動函數處理
下面對蛇移動的過程進行處理,由于我們每次都采用添頭去尾的方式移動,因此我們每次只需要關注蛇的頭和尾。我們約定數組的第一個元素是頭,最后一個元素是尾。
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; } // 數組添頭 this.body.unshift(newHead); // 數組去尾 this.body.pop(); };
檢測函數處理
這樣我們對蛇身數組就處理完了。但是我們還需要對新的頭(newHead)進行一些碰撞檢測,判斷新頭部的位置上是否有其他東西(碰撞檢測)。
// 食物檢測 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; };
重新繪制
因此我們需要對Move函數進行一些擴充:
this.Move = function(){ // ...數組操作 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'); } };
因為在Move函數處理數組的后我們的蛇身還沒有重新繪制,因此我們很巧妙地判斷如果是吃到食物的情況,在數組中就把原來的尾部添加上,這樣就達到了吃食物的效果。同時我們定義一個rePaint函數進行頁面的重繪。
游戲控制器
我們的“幕布”、“演員”和“動作指導”都已經到位,那么,我們現在就需要一個“攝影機”進行拍攝,讓它們都開始“干活”。
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綁定一個keydown事件,當觸發按鍵時改變蛇的移動方向,但是如果和當前蛇移動方向相反時就直接return。最后的效果如下:
感謝你能夠認真閱讀完這篇文章,希望小編分享的“jQuery怎么實現實現貪吃蛇小游戲”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。