最终代码,还有很多优化空间。
然后下面有每一步的思考空间。
这个代码目前就只实现了主要功能,但是封装的相对比较好,可以自行把一些交互加上,比如计分、自定义棋盘大小、自定义难度(移动速度)。还有结束的逻辑也没写,这些都交给有兴趣的读者自行完成了,如果感觉有难度或者疑问,欢迎在评论区留言讨论。
上次写的贪吃蛇小游戏还没完工,时隔很久了,可以先看一下上面那个链接回顾一下。
下面我们继续。
以下是接着上一篇文章的创作思路。
4 给棋牌填上颜色
线条布局已经搞定了,接下来我们需要给蛇和食物填上颜色。
canvas的对应API为 fillrect(x,y,w,h);
5 把代码重新整理一下如下:
这时候的页面效果如图,已经有了棋盘、蛇、食物。
接下来是要让蛇动起来啦。
6 让蛇动起来
按照游戏规则,在按下方向键时会动,然后不按的话,会按照之前的方向继续向前。
我们先实现按键移动吧。按键的监听功能我们挂到map对象上了,在今天这次调整中,可以看到很多方法我们都移动到了map对象,这个是我思考了一下这个游戏中各个对象应有的职责而修改的,游戏和我们生活中的场景不太一样,生活场景对象化很简单,每个人拥有自己的功能方法就可以了,但是游戏不一样,它的规则其实不属于任何一个对象,非要细分的话,引入一个上帝或者法官会比较合适,但是为了简单点,我们把这个交给了我们的棋盘对象了。
同样动起来这个也交给了map对象。首先snaker对象是有个move方法的,在上面我们已经写好了,下面只需要监听按键,然后调用对应snaker的move方法即可,这里同时稍微改造了一下对应move方法的实现。
到这里实现了移动,吃食物,判断是否碰撞到边界或者自己的身体。
自动移动先缓一下,我们先实现一下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); }
關鍵字: 小游戏 event.keyCode this.width