您好,登錄后才能下訂單哦!
本文實例講述了JS實現的貪吃蛇游戲。分享給大家供大家參考,具體如下:
github項目地址:https://github.com/LEERTRT/Snake
在<script></script>中,文檔加載完畢后調用:
$(function () { var game = new Game("canvas"); game.init(); });
其中構造函數Game()接收canvas的id作為參數,實例化對象以后,調用init()函數,init()函數里面有三個函數,接下來會一個一個說明。
/** * 初始化函數,生成構造函數實例后調用此函數 */ this.init = function () { /** * 初始化畫布和果實 */ this.initData(); /** * 1.清空畫布;2.畫背景格子;3.畫蛇;4.畫果實 */ this.draw(); /** * 綁定事件:方向和速度控制 */ this.bindEvents(); };
第一個,initData():在initData()函數里面,聲明畫布,果實,畫布大小,格子數量,方向,速度,蛇等:
var canvas = document.getElementById(id); if (canvas && canvas.getContext) { this.ctx = canvas.getContext('2d'); } this.foodNode = null;//果實 this.size = canvas.width || $(canvas).width();//畫布大小 this.columns = 50;//畫布行列數 this.direction = 0;//方向 this.speed = 10;//速度 this.bodyNodes = [];//蛇體
然后隨機生成蛇的位置:
var rdx = Math.round(Math.random() * (this.columns - 1)); var rdy = Math.round(Math.random() * (this.columns - 1));
把隨機生成的rdx, rdy放進記錄蛇體的數組中:
this.bodyNodes.push({ x: rdx, y: rdy });
到此,initData()完成。
第二個,draw():draw()函數包含四步:1.清空畫布;2.畫背景;3.畫蛇;4.畫果實:
this.draw = function () { /** * 清空畫布 */ this.clear(); /** * 畫畫布 */ this.drawBG(); /** * 畫蛇體 */ this.drawBody(); /** *畫果實 */ this.drawFood(); };
1.清空畫布
使用clearRect(0,0,size,size)即可:
this.ctx.clearRect(0, 0, this.size, this.size);
2.畫背景
每個格子大小 = 畫布尺寸/格子數量,然后一行一行畫就行了,和畫棋盤一樣:
var _this = this; var x = 0, y = 0, size = _this.size / _this.columns; _this.ctx.strokeStyle = "rgba(124,124,124,0.1)"; //一行一行畫畫布 for (var i = 0; i < _this.columns; i++) { y = i * size; for (var j = 0; j < _this.columns; j++) { x = j * size; _this.ctx.strokeRect(x, y, size, size); } }
3.畫蛇
前面在initData()里面,把隨機生成的蛇的位置放進了bodyNodes數組里面,
這里把bodyNodes里面的元素用each()取出來畫即可。因為后面當蛇吃了果實后,bodyNodes里面的
元素會增加,所以用each取出所有元素繪畫,現在是在初始化階段,bodyNodes里面只有在initData()
的一個隨機生成的元素。
var nodes = _this.bodyNodes; $.each(nodes, function (i, node) { _this.ctx.fillRect(node.x * size, node.y * size, size, size); });
4.畫果實
畫果實的時候,先判斷foodNode是否存在,存在的話就直接畫,不存在隨機生成位置,
注意,這時候要判斷隨機生成的果實位置有沒有和蛇重合,重合了要重新畫:
//如果果實重新出現的位置和蛇體重合,重畫果實 if (_this.Utils.contains(_this.bodyNodes, {x: rdx, y: rdy})) { _this.drawFood(); } else { _this.ctx.strokeRect(rdx * size, rdy * size, size, size); _this.foodNode = {x: rdx, y: rdy}; }
到此,初始化畫布和果實數據;繪畫已經完成,這一塊屬于靜態,接下來是動態的綁定事件。
這里主要描述貪吃蛇動態內容,比如前進,吃果實后變大,越界,速度控制等。
在前面,init()函數已經 完成了initData()和draw(),接下來是最后一個函數,bindEvents()。
在bindEvents()函數里面,有2個函數:①方向控制;②時間控制。
①方向控制directionContoller
document.body.onkeydown捕獲按鍵,對ketCode進行判斷,左(37),上(38),右(39),下(40),再將direction根據keyCode置為自己設置的標志即可。這里需要注意一點:如果這時候的方向為x,而按下的方向為-x,那么按鍵無效。比如現在方向是向左,而按下右是無效轉彎的。
case 37: // 左, 1表示右,即當蛇向右行時,按左鍵不能改變方向,下面同理 if (_this.direction == 1) return; _this.direction = -1; break;
設置好方向后,調用move()函數,這里控制蛇的移動,就是說到底就是在蛇體數組里面新增頭元素,去掉尾元素,這里還要進行2個判斷:1)蛇有沒有咬到自己;2)有沒有出界。
調用food()方法判斷蛇是否吃到果實,在蛇數組里面設置好元素后,draw()重繪,以此完成了蛇的移動和吃果實。
this.food = function () { var _this = this; var headNode = _this.bodyNodes[0]; //吃到果實 if (_this.Utils.equals(headNode, _this.foodNode)) { _this.bodyNodes.push(_this.foodNode);//push()方法可向數組的末尾添加一個或多個元素,并返回新的長度。 _this.foodNode = null; var score = _this.bodyNodes.length - 1; $('#score').text(score); if (score % 10 == 0) {//加速提高難度 _this.speed += 10; _this.timerController(); } } };
②timerController
時間控制,
利用setInterval()
函數定時調用move()方法,時間為6000/speed。
this.timerController = function () { var _this = this; if (_this.timer) { clearInterval(_this.timer); } _this.timer = setInterval(function () { _this.move(); }, 6000 / _this.speed); $('#speed').text(_this.speed); };
最后是工具類方法contains()和equesl()。contains用來判斷新生成隨機果實的位置和蛇重合時重新生成隨機果實,以及蛇自己碰到自己時算游戲結束。
equals用來判斷蛇到果實沒有。他們的區別就是,contains要用each比較,因為蛇體數組有多個,所以需要循環一個一個比較。而equals()只比較蛇頭和果實重合,所以不用循環。
this.Utils = { contains: function (arr, o) { var _this = this; if (!arr || !o) return false; var flag = false; $.each(arr, function () { if (!this) return true; if (_this.equals(this, o)) { flag = true; return false; } }); return flag; }, equals: function (o1, o2) { if (o1 == o2) return true; if (!o1 || !o2) return false; return o1.x == o2.x && o1.y == o2.y; } };
更多關于JavaScript相關內容感興趣的讀者可查看本站專題:《JavaScript數學運算用法總結》、《JavaScript數據結構與算法技巧總結》、《JavaScript數組操作技巧總結》、《JavaScript排序算法總結》、《JavaScript遍歷算法與技巧總結》、《JavaScript查找算法技巧總結》及《JavaScript錯誤與調試技巧總結》
希望本文所述對大家JavaScript程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。