龙空技术网

js实现贪吃蛇小游戏 2

儛2018 92

前言:

如今兄弟们对“jquery怎么监听play”可能比较关注,看官们都想要剖析一些“jquery怎么监听play”的相关文章。那么小编在网摘上搜集了一些有关“jquery怎么监听play””的相关知识,希望同学们能喜欢,看官们一起来了解一下吧!

最终代码,还有很多优化空间。

然后下面有每一步的思考空间。

这个代码目前就只实现了主要功能,但是封装的相对比较好,可以自行把一些交互加上,比如计分、自定义棋盘大小、自定义难度(移动速度)。还有结束的逻辑也没写,这些都交给有兴趣的读者自行完成了,如果感觉有难度或者疑问,欢迎在评论区留言讨论。

<!DOCTYPE html><html><head> <script src="" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script> // 常量 var D_UP = 1, D_DOWN = 2, D_RIGHT = 3, D_LEFT = 4; var Direction_Map = { '37' : D_LEFT, '38' : D_UP, '39' : D_RIGHT, '40' : D_DOWN }; // 简单点,我们的地图是长方形的(有兴趣的可以考虑其他形状,最经典的应该还是长方形) var Map = function (width, height) { this.width = width; this.height = height; } Map.prototype.init = function(){ this.snaker = new Snaker(2, D_DOWN); this.food = this.createFood(); $(document).keydown(function(event){ if(Direction_Map[event.keyCode]){ this.move(Direction_Map[event.keyCode]); }   }.bind(this)); this.draw(); } Map.prototype.setMoveTimeout = function(){ if(this.clock){ clearTimeout(this.clock); } this.clock = setTimeout(function(){ this.move(); }.bind(this), 1000); }  Map.prototype.createFood = function(){ var min = 0; var max = this.width * this.height - 1; var a = {}; var randArr = []; for(var i in this.snaker.body){ var p = this.snaker.body[i]; var k = p[1] * this.width + p[0]; a[k] = 1; } for(var i = min; i <= max; i++ ){ if(!a[i]){ randArr.push(i); } } if(randArr.length === 0){ return false; } var random = randArr[Math.floor(Math.random()*randArr.length)]; return new Food(random % this.width, Math.floor(random / this.width)); } Map.prototype.move = function(direction){ var result = this.snaker.move(this.food, direction); if(result){ this.food = this.createFood(); } if(this.isCollided()){ alert("dead"); return this.init(); } this.draw(); this.setMoveTimeout(); return result; } Map.prototype.isCollided = function () { if(!this.snaker){ return true; } let body = this.snaker.body; let first = body[0]; console.log(first) if (first[0] < 0 || first[0] >= this.width || first[1] < 0 || first[1] >= this.height) { return true; } for (var i = 1; i < body.length; i++) { if (body[i][0] === first[0] && body[i][1] === first[1]) { return true; } } return false; } Map.prototype.draw = function() { var chess = document.getElementById("mycanvas"); var context = chess.getContext('2d'); var width = this.width, height = this.height, blockWidth = 30; chess.width = width * blockWidth ; chess.height = height * blockWidth ; for (let i = 0; i < width + 1; i++) { context.strokeStyle = "#D6D1D1"; context.moveTo(i * blockWidth, 0); context.lineTo(i * blockWidth, blockWidth * height); context.stroke(); } for (let i = 0; i < height + 1; i++) { context.strokeStyle = "#D6D1D1"; context.moveTo(0, i * blockWidth); context.lineTo(blockWidth * width, i * blockWidth); context.stroke(); } //改变填充的颜色 context.fillStyle="#ffff00"; //画一个实体方块---fillrect(x,y,w,h); context.fillRect(this.food.position[0] * blockWidth, this.food.position[1] * blockWidth, blockWidth, blockWidth);  for(let i in this.snaker.body){ let position = this.snaker.body[i]; //改变填充的颜色 context.fillStyle="blue"; //画一个实体方块---fillrect(x,y,w,h); context.fillRect(position[0] * blockWidth, position[1] * blockWidth, blockWidth, blockWidth); }  } // 蛇有个初始长度,一个初始的移动方向,一个初始的身体,一个头,然后会拥有运动的能力 var Snaker = function (height, direction) { this.direction = direction; // 初始身体是由长度生成的,我们假设从第二行第二列开始,横着放 this.body = []; for (var i = 1; i < height + 1; i++) { this.body.push([i, 1]); } } Snaker.prototype.move = function (food, direction) { if(direction){ // 如果方向相反,那么则无效 if(direction + this.direction == D_DOWN + D_UP || direction + this.direction == D_LEFT + D_RIGHT){ return false; } this.direction = direction; } let first = this.body[0]; if (this.direction === D_UP) { first = [first[0], first[1] - 1]; } else if (this.direction === D_DOWN) { first = [first[0], first[1] + 1]; } else if (this.direction === D_RIGHT) { first = [first[0] + 1, first[1]]; } else { first = [first[0] - 1, first[1]]; } this.body.unshift(first); if (food && (food.position[0] == first[0] && food.position[1] == first[1])) { return true; } this.body.pop(); return false; }  // 食物先简单点,就一个位置 var Food = function (x, y) { this.position = [x, y]; } </script></head><body> <canvas id="mycanvas" ></canvas></body><script> var m = new Map(12, 10); m.init();</script></html>

js实现贪吃蛇小游戏 1

上次写的贪吃蛇小游戏还没完工,时隔很久了,可以先看一下上面那个链接回顾一下。

下面我们继续。

以下是接着上一篇文章的创作思路。

4 给棋牌填上颜色

线条布局已经搞定了,接下来我们需要给蛇和食物填上颜色。

canvas的对应API为 fillrect(x,y,w,h);

5 把代码重新整理一下如下:

<!DOCTYPE html><html><head> <script src="" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script> // 简单点,我们的地图是长方形的(有兴趣的可以考虑其他形状,最经典的应该还是长方形) var Map = function (width, height) { this.width = width; this.height = height; this.init(); } Map.prototype.init = function(){ this.snaker = new Snaker(2); this.food = new Food(3,5); } Map.prototype.isCollided = function () { if(!this.snaker){ return true; } let body = this.snaker.body; let first = body[0]; if (first[0] < 0 || first[0] >= this.height - 1 || first[1] < 0 || first[1] >= this.width - 1) { return true; } for (var i = 1; i < body.length; i++) { if (body[i][0] === first[0] && body[i][1] === first[1]) { return true; } } return false; } Map.prototype.draw = function() { var chess = document.getElementById("mycanvas"); var context = chess.getContext('2d'); var width = this.width, height = this.height, blockWidth = 30; chess.width = width * blockWidth ; chess.height = height * blockWidth ; for (let i = 0; i < width + 1; i++) { context.strokeStyle = "#D6D1D1"; context.moveTo(i * blockWidth, 0); context.lineTo(i * blockWidth, blockWidth * height); context.stroke(); } for (let i = 0; i < height + 1; i++) { context.strokeStyle = "#D6D1D1"; context.moveTo(0, i * blockWidth); context.lineTo(blockWidth * width, i * blockWidth); context.stroke(); } //改变填充的颜色 context.fillStyle="#ffff00"; //画一个实体方块---fillrect(x,y,w,h); context.fillRect(this.food.position[0] * blockWidth, this.food.position[1] * blockWidth, blockWidth, blockWidth);  for(let i in this.snaker.body){ let position = this.snaker.body[i]; //改变填充的颜色 context.fillStyle="blue"; //画一个实体方块---fillrect(x,y,w,h); context.fillRect(position[0] * blockWidth, position[1] * blockWidth, blockWidth, blockWidth); }  } // 蛇有个初始长度,一个初始的移动方向,一个初始的身体,一个头,然后会拥有运动的能力 var D_UP = 1, D_DOWN = 2, D_RIGHT = 3, D_LEFT = 4; var Snaker = function (height, direction) { this.direction = direction; // 初始身体是由长度生成的,我们假设从第二行第二列开始,横着放 this.body = []; for (var i = 1; i < height + 1; i++) { this.body.push([i, 1]); } } Snaker.prototype.move = function (food) { let first = this.body[0]; if (direction === D_UP) { first = [first[0] - 1, first[1]]; } else if (direction === D_DOWN) { first = [first[0] + 1, first[1]]; } else if (direction === D_RIGHT) { first = [first[0], first[1] + 1]; } else { first = [first[0], first[1] - 1]; } this.body.unshift(first); if (!food) { this.body.pop(); } }  // 食物先简单点,就一个位置 var Food = function (x, y) { this.position = [x, y]; } </script></head><body> <canvas id="mycanvas" ></canvas></body><script> var m = new Map(25, 10); m.draw();</script></html>

这时候的页面效果如图,已经有了棋盘、蛇、食物。

接下来是要让蛇动起来啦。

6 让蛇动起来

按照游戏规则,在按下方向键时会动,然后不按的话,会按照之前的方向继续向前。

我们先实现按键移动吧。按键的监听功能我们挂到map对象上了,在今天这次调整中,可以看到很多方法我们都移动到了map对象,这个是我思考了一下这个游戏中各个对象应有的职责而修改的,游戏和我们生活中的场景不太一样,生活场景对象化很简单,每个人拥有自己的功能方法就可以了,但是游戏不一样,它的规则其实不属于任何一个对象,非要细分的话,引入一个上帝或者法官会比较合适,但是为了简单点,我们把这个交给了我们的棋盘对象了。

同样动起来这个也交给了map对象。首先snaker对象是有个move方法的,在上面我们已经写好了,下面只需要监听按键,然后调用对应snaker的move方法即可,这里同时稍微改造了一下对应move方法的实现。

<!DOCTYPE html><html><head> <script src="" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script> // 常量 var D_UP = 1, D_DOWN = 2, D_RIGHT = 3, D_LEFT = 4; var Direction_Map = { '37' : D_LEFT, '38' : D_UP, '39' : D_RIGHT, '40' : D_DOWN }; // 简单点,我们的地图是长方形的(有兴趣的可以考虑其他形状,最经典的应该还是长方形) var Map = function (width, height) { this.width = width; this.height = height; this.init(); } Map.prototype.init = function(){ this.snaker = new Snaker(2, D_DOWN); this.food = new Food(3,5); $(document).keydown(function(event){ console.log(event.keyCode) if(Direction_Map[event.keyCode]){ this.move(Direction_Map[event.keyCode]); }   }.bind(this)); } Map.prototype.move = function(direction){ this.snaker.move(this.food, direction); if(this.isCollided()){ alert("dead"); } this.draw(); } Map.prototype.isCollided = function () { if(!this.snaker){ return true; } let body = this.snaker.body; let first = body[0]; if (first[0] < 0 || first[0] >= this.width - 1 || first[1] < 0 || first[1] >= this.height - 1) { return true; } for (var i = 1; i < body.length; i++) { if (body[i][0] === first[0] && body[i][1] === first[1]) { return true; } } return false; } Map.prototype.draw = function() { var chess = document.getElementById("mycanvas"); var context = chess.getContext('2d'); var width = this.width, height = this.height, blockWidth = 30; chess.width = width * blockWidth ; chess.height = height * blockWidth ; for (let i = 0; i < width + 1; i++) { context.strokeStyle = "#D6D1D1"; context.moveTo(i * blockWidth, 0); context.lineTo(i * blockWidth, blockWidth * height); context.stroke(); } for (let i = 0; i < height + 1; i++) { context.strokeStyle = "#D6D1D1"; context.moveTo(0, i * blockWidth); context.lineTo(blockWidth * width, i * blockWidth); context.stroke(); } //改变填充的颜色 context.fillStyle="#ffff00"; //画一个实体方块---fillrect(x,y,w,h); context.fillRect(this.food.position[0] * blockWidth, this.food.position[1] * blockWidth, blockWidth, blockWidth);  console.log(this.snaker.body) for(let i in this.snaker.body){ let position = this.snaker.body[i]; //改变填充的颜色 context.fillStyle="blue"; //画一个实体方块---fillrect(x,y,w,h); context.fillRect(position[0] * blockWidth, position[1] * blockWidth, blockWidth, blockWidth); }  } // 蛇有个初始长度,一个初始的移动方向,一个初始的身体,一个头,然后会拥有运动的能力 var Snaker = function (height, direction) { this.direction = direction; // 初始身体是由长度生成的,我们假设从第二行第二列开始,横着放 this.body = []; for (var i = 1; i < height + 1; i++) { this.body.push([i, 1]); } } Snaker.prototype.move = function (food, direction) { if(direction){ // 如果方向相反,那么则无效 if(direction + this.direction == D_DOWN + D_UP || direction + this.direction == D_LEFT + D_RIGHT){ return false; } this.direction = direction; } let first = this.body[0]; if (this.direction === D_UP) { first = [first[0], first[1] - 1]; } else if (this.direction === D_DOWN) { first = [first[0], first[1] + 1]; } else if (this.direction === D_RIGHT) { first = [first[0] + 1, first[1]]; } else { first = [first[0] - 1, first[1]]; } this.body.unshift(first); if (food && (food.position[0] == first[0] && food.position[1] == first[1])) { return true; } this.body.pop(); return false; }  // 食物先简单点,就一个位置 var Food = function (x, y) { this.position = [x, y]; } </script></head><body> <canvas id="mycanvas" ></canvas></body><script> var m = new Map(10, 10); m.draw();</script></html>

到这里实现了移动,吃食物,判断是否碰撞到边界或者自己的身体。

自动移动先缓一下,我们先实现一下food的消失和产生。

7 产生新食物的方法

食物要出现在棋盘里,同时不能出现在蛇的身体上。

Map.prototype.createFood = function(){ var min = 0; var max = this.width * this.height - 1; var a = {}; var randArr = []; for(var i in this.snaker.body){ var p = this.snaker.body[i]; var k = p[1] * this.width + p[0]; a[k] = 1; } for(var i = min; i <= max; i++ ){ if(!a[i]){ randArr.push(i); } } if(randArr.length === 0){ return false; } var random = randArr[Math.floor(Math.random()*randArr.length)]; return new Food(random % this.width, Math.floor(random / this.width)); }

实现了一个创造食物的方法,篇幅所限,这边不列出此时的完整代码了。

8 实现自动移动

使用setInterval或者setTimeout,比较之后,要实现手动移动之后重置延迟,于是setTimeout会更适合。

Map.prototype.setMoveTimeout = function(){ if(this.clock){ clearTimeout(this.clock); } this.clock = setTimeout(function(){ this.move(); }.bind(this), 1000); }

条纹图案可爱绿蛇

标签: #jquery怎么监听play #jquery下一步 #jquery根据行和列 #jquery制作小游戏 #jquery监听键盘