概述
上代码
- html
<canvas width="600" height="600">不支持 canvas</canvas>
- css
canvas { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #ccc; border-radius: 10px; border: 1px solid #000; }
- js
var ctx = document.querySelector('canvas').getContext('2d'), direction = [{ x: -1, y: 0 }, { x: 0, y: -1 }, { x: 1, y: 0 }, { x: 0, y: 1 }], preDir = direction[1], food = { x: -1, y: -1 }, snkArr = [{ x: 14, y: 20 }, { x: 14, y: 21 }, { x: 14, y: 22 }]; var draw = ({ x, y }, color) => (ctx.fillStyle = color, ctx.fillRect(x * 20, y * 20, 19, 19), 1); var changeDir = e => Math.abs((e.keyCode - 37) - direction.indexOf(preDir)) != 2 && (e.keyCode - 37) >= 0 && (e.keyCode - 37) <= 3 && (preDir = direction[e.keyCode - 37], document.removeEventListener('keydown', changeDir)); setInterval(() => { if (document.addEventListener('keydown', changeDir) || snkArr.map((val, i) => { snkArr[0].x + preDir.x == val.x && snkArr[0].y + preDir.y == val.y && (snkArr[0].x = 31) }) && !(snkArr[0].x + preDir.x >= 30 || snkArr[0].y + preDir.y >= 30 || snkArr[0].x + preDir.x <= -1 || snkArr[0].y + preDir.y <= -1)) { snkArr.unshift({ x: snkArr[0].x + preDir.x, y: snkArr[0].y + preDir.y }); draw({ x: snkArr[0].x, y: snkArr[0].y }, '#0aa'); !(((snkArr[0].x == food.x && snkArr[0].y == food.y) || (food.x == -1 && draw(snkArr.pop(), '#ccc'))) && draw(((() => { while (snkArr.indexOf({ x: food.x = ~~(Math.random() * 29), y: food.y = ~~(Math.random() * 29) }) > -1); })(), food), 'orange')) && draw(snkArr.pop(), '#ccc'); } else alert('Game over!', location.reload()); }, 150);
注释版
var ctx = document.querySelector('canvas').getContext('2d'),
// 2d 对象
direction = [{ x: -1, y: 0 }, { x: 0, y: -1 }, { x: 1, y: 0 }, { x: 0, y: 1 }],
// 方向列表,分别是 左 上 右 下 的位移增量,后面通过 keycode - 37 直接访问到该增量
preDir = direction[1],
// 当前方向,值为 direction 中四个元素之一
food = { x: -1, y: -1 },
// 食物的位置,初始化为 -1 ,第一次循环生成
snkArr = [{ x: 14, y: 20 }, { x: 14, y: 21 }, { x: 14, y: 22 }];
// 蛇身
// 画方块,{x,y} 为方块的坐标,认为 20 * 20 为一个像素,实现中会做处理, color 为方块颜色
var draw = ({ x, y }, color) => (ctx.fillStyle = color, ctx.fillRect(x * 20, y * 20, 19, 19), 1);
// keydown 的回调
var changeDir = e => {
// 禁止同方向变化
Math.abs((e.keyCode - 37) - direction.indexOf(preDir)) != 2
// 禁止其他按键影响
&& (e.keyCode - 37) >= 0
// preDir 赋值
&& (e.keyCode - 37) <= 3 && (preDir = direction[e.keyCode - 37],
// 移除事件监听,防止两帧之间连续改变方向
document.removeEventListener('keydown', changeDir));
}
setInterval(() => {
// 添加事件监听
// map 判断有没有碰到蛇身,碰到后置蛇头超出范围
if (document.addEventListener('keydown', changeDir) || snkArr.map((val, i) => { snkArr[0].x + preDir.x == val.x && snkArr[0].y + preDir.y == val.y && (snkArr[0].x = 31) })
// 判断蛇头有没有超出范围
&& !(snkArr[0].x + preDir.x >= 30 || snkArr[0].y + preDir.y >= 30 || snkArr[0].x + preDir.x <= -1 || snkArr[0].y + preDir.y <= -1)) {
// snkArr 蛇身增加新蛇头
snkArr.unshift({ x: snkArr[0].x + preDir.x, y: snkArr[0].y + preDir.y });
// 画蛇头
draw({ x: snkArr[0].x, y: snkArr[0].y }, '#0aa');
// 条件:if 碰到食物,(同时判断若食物未初始化则画食物)
!(((snkArr[0].x == food.x && snkArr[0].y == food.y) || (food.x == -1 && draw(snkArr.pop(), '#ccc')))
// then 画食物
&& draw(((() => { while (snkArr.indexOf({ x: food.x = ~~(Math.random() * 29), y: food.y = ~~(Math.random() * 29) }) > -1); })(), food), '#fff'))
// else 不去蛇尾(意为没碰到食物则去蛇尾)
&& draw(snkArr.pop(), '#ccc');
} else {
// 游戏结束
alert('Game over!',
location.reload()
);
}
}, 150);
最后
以上就是辛勤母鸡为你收集整理的【贪吃蛇】canvas + 原生 JS, 10 行极限实现贪吃蛇上代码注释版的全部内容,希望文章能够帮你解决【贪吃蛇】canvas + 原生 JS, 10 行极限实现贪吃蛇上代码注释版所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复