JS实现的贪吃蛇游戏案例详解
本文实例讲述了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程序设计有所帮助。