用canvas写贪吃蛇
来源:互联网 发布:南威软件林志强 编辑:程序博客网 时间:2024/05/19 02:26
最近参加了baidu_ife_2017,里面有个任务是用canvas写贪吃蛇游戏,游戏有三种玩法,不过现在我也只是完成了前两种(普通模式和过关模式),想记录一下遇到的几个问题和解决方法,各位走过路过也可以给些建议。可以到此试玩一下:Snake Online
1.如何让蛇动起来
用canvas来写游戏,无非就是设置个定时器,不断清空画布然后重绘。而让蛇动起来,让其身体每一截都往前移动,这显然是非常麻烦的一件事,比如蛇身现在弯弯曲曲,而其每一截都要向爬行方向移动一格,还需要给每一截重新计算下一步的位置。在我看来是十分麻烦的一件事,于是思索一番,发现蛇每次只是移动一格,那么如果我只改变最后一截,让其位置变为爬行方向的下一格不就解决了吗。想到这,我用一个数组来维护每一截的位置对象:
function Snake(args) { this.bodyArr = []; // 每次移动蛇头x,y值改变量 this.dx = 0; this.dy = 0; //...}Snake.prototype.setBodyArr = function () { var newX = this.bodyArr[0].x + this.dx; var newY = this.bodyArr[0].y + this.dy; // 移除最后一截 var temp = this.bodyArr.pop(); // 将下一次要移动的位置插入到位置数组中 this.bodyArr.unshift({ x: newX, y: newY }); // ...};
2.食物的随机位置如何设置
或许大家觉得这个很简单,不就是产生个随机数,然后避开蛇身的位置就完事了么。我也是这么想的,但是想动手时却犯难了,我觉得应该是可以优化的。毕竟每产生一次随机数,就要和蛇身每一截去比较一次,重叠了又要重新产生随机数再全部比较一次… 虽然废不了多少时间,但总觉得可以优化,于是在github上找别人的解决方案,发现很多人都是使用一个二维数组来维护地图上每个位置的状态的,觉得不错于是将其用上了:
function Snake(args) { // position[x][y] = 0 为空, // position[x][y] = 1 为蛇身, // position[x][y] = 2 为食物 this.position = creat2dArr(width, height); //...}// 产生一个值全为0的二维数组function creat2dArr(width, height) { var arr = new Array(width); for(var j = 0; j < width; j++) { arr[j] = new Array(height); for(var k = 0; k < height; k++) { arr[j][k] = 0; } } return arr;}
每次只需比较 position[x][y] 的值即可知道该位置的状态。
3.蛇爬行方向的改变
游戏是通过方向键来控制的,那么如果玩家在两次重绘之间,按下了多次不同的方向键,那么蛇下一次爬行的方向该定为什么?怎么解决这个冲突?我想到的是用一个队列来保存玩家的输入,每次重绘前取出队列的首项,如果该方向合理(即不是与当前方向相同或相反),则修改下一步的方向,通过这种方式,玩家的每一次输入都可以得到响应,只是快与慢的问题罢了。
function Snake(args) { // 爬行方向("up": 上,"down": 下,"left": 左,"right": 右) this.directionQueue = []; this.nextDirection = "up"; // 定义初始爬行方向为上 //...}// 设置下一次爬行的方向Snake.prototype.setNextDirection = function () { if(this.directionQueue.length === 0) { // 如果用户没有输入下一个方向则返回 return; } var temp = ""; while(this.directionQueue.length !== 0) { if((temp = this.directionQueue.shift()) !== this.nextDirection) { // 判断方向合法性 if(this.judgeLegality(temp)) { this.nextDirection = temp; // 设置dx与dy的值 if(temp === "up") { this.dx = 0; this.dy = -1; } else if(temp === "down") { this.dx = 0; this.dy = 1; } else if(temp === "left") { this.dx = -1; this.dy = 0; } else { this.dx = 1; this.dy = 0; } break; } } }};// 页面加载完成后window.onload = function () { var snake = new Snake(args); // 注册键盘事件 onEvent(document, "keydown", function (e) { e = e || window.event; if(e.keyCode === 37) { // left snake.directionQueue.push("left"); } else if(e.keyCode === 38) { // up snake.directionQueue.push("up"); } else if(e.keyCode === 39) { // right snake.directionQueue.push("right"); } else if(e.keyCode === 40) { // down snake.directionQueue.push("down"); } });};
结语
这些是我做贪吃蛇时碰到的几个问题,写出来分享下。如果觉得太白痴了请略过… 如果觉得还可以改进,欢迎在下方留言。
- 用canvas写贪吃蛇
- 用html5中canvas标签写个贪吃蛇
- canvas的贪吃蛇
- HTML5+Canvas贪吃蛇
- Canvas贪吃蛇
- Canvas 贪吃蛇
- canvas贪吃蛇
- canvas贪吃蛇
- html5 贪吃蛇canvas小游戏
- 贪吃蛇 HTML5 Canvas代码
- 贪吃蛇(canvas+javaScript)
- canvas+js 贪吃蛇实现
- 用Html 5的canvas及javascript实现贪吃蛇
- 用java写的贪吃蛇游戏
- 用MFC写了个贪吃蛇
- 用Python写了个贪吃蛇
- 用windows sdk写一个贪吃蛇
- 用c语言写的贪吃蛇
- 理解RemoteViews
- flexble.js简单的demo
- JAVA并发的底层实现
- HBase-compact
- HTTP AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式
- 用canvas写贪吃蛇
- Error: A library uses the same package分析和处理
- 软件开发项目流程
- 内存管理之memblock
- 4730: Alice和Bob又在玩游戏
- ObjectOutputStream和ObjectInputStream
- lua 运算符
- Codeforces 253D-Table with Letters
- 算法分析学习1