时间:2022-02-14来源:www.pcxitongcheng.com作者:电脑系统城
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const canvas = document.getElementById( "canvas" ) const ctx = canvas.getContext( "2d" ) const width = 400 const height = 400 const cellLength = 20 let foodPosition let initSnake = [ [0, 0], [1, 0], [2, 0], ] let snake = [...initSnake] let direction = "right" let canChangeDirection = true |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
// 背景 function drawBackground() { ctx.strokeStyle = "#bfbfbf" for (let i = 0; i <= height / cellLength; i++) { ctx.beginPath() ctx.moveTo(0, cellLength * i) ctx.lineTo(width, cellLength * i) ctx.stroke() } for (let i = 0; i <= width / cellLength; i++) { ctx.beginPath() ctx.moveTo(cellLength * i, 0) ctx.lineTo(cellLength * i, height) ctx.stroke() } } // 蛇 function drawSnake() { let step = 100 / (snake.length - 1) for (let i = 0; i < snake.length; i++) { // 这里做了渐变色的蛇,添加动态色彩。尾部有个最小白色阀值,免得跟背景混为一体 const percent = Math.min(100 - step * i, 90) ctx.fillStyle = `hsl(0,0%,${percent}%)` ctx.fillRect( snake[i][0] * cellLength, snake[i][1] * cellLength, cellLength, cellLength ) } } // 绘制食物 // 随机生成食物的位置 function generateRandomFood() { // 如果没有位置可以生成 if (snake.length > width * height) { return alert( "you win" ) } const randomX = Math.floor(Math.random() * (width / cellLength)) const randomY = Math.floor(Math.random() * (height / cellLength)) // 生成的位置如果跟蛇体积碰撞,则重新生成。 for (let i = 0; i < snake.length; i++) { if (snake[i][0] === randomX && snake[i][1] === randomY) { return generateRandomFood() } } foodPosition = [randomX, randomY] } // 绘制 function drawFood() { ctx.fillStyle = "#ff7875" ctx.fillRect( foodPosition[0] * cellLength, foodPosition[1] * cellLength, cellLength, cellLength ) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
// 蛇的移动 // 确定下一次移动的位置,将这个点push到数组末尾(头的位置), // 将数组第一项shift出来(尾的位置) // 吃食物的逻辑 // 如果食物的位置跟下一次移动的位置相同,将这个点加入头部,不推出尾部 function snakeMove() { let next let last = snake[snake.length - 1] // 根据方向确定下一个蛇头的位置 switch (direction) { case "up" : { next = [last[0], last[1] - 1] break } case "down" : { next = [last[0], last[1] + 1] break } case "left" : { next = [last[0] - 1, last[1]] break } case "right" : { next = [last[0] + 1, last[1]] break } } // 边缘碰撞 const boundary = next[0] < 0 || next[0] >= width / cellLength || next[1] < 0 || next[1] >= height / cellLength // 自身碰撞 const selfCollision = snake.some(([x, y]) => next[0] === x && next[1] === y) // 碰撞重新开始游戏 if (boundary || selfCollision) { return restart() } snake.push(next) // 如果下一个点是食物的位置,不推出头部 if (next[0] === foodPosition[0] && next[1] === foodPosition[1]) { generateRandomFood() return } snake.shift() canChangeDirection = true } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
document.addEventListener( "keydown" , (e) => { switch (e.key) { case "ArrowUp" : if (direction === "down" || !canChangeDirection) return direction = "up" canChangeDirection = false break case "ArrowDown" : if (direction === "up" || !canChangeDirection) return direction = "down" canChangeDirection = false break case "ArrowLeft" : if (direction === "right" || !canChangeDirection) return direction = "left" canChangeDirection = false break case "ArrowRight" : if (direction === "left" || !canChangeDirection) return direction = "right" canChangeDirection = false break } }) |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 默认的requestAnimationFrame循环应该是60帧,对于这个游戏来说太快了。 // 所以做了限制,5次loop才渲染(蛇移动一格)一次 function animate() { let count = 0 function loop() { if (++count > 5) { draw() count = 0 } requestAnimationFrame(loop) } requestAnimationFrame(loop) } |
1 2 3 4 5 6 |
// 事件回调 case "ArrowUp" : if (direction === "down" |!canChangeDirection) return direction = "up" canChangeDirection = false break |
到此这篇关于canvas实现贪食蛇的实践的文章就介绍到这了,更多相关 canvas贪食蛇内容请搜索脚本之家以前的文章或继续浏览下面的相关文章!
2022-02-14
bootstrapv4轮播图去除两侧阴影及线框的方法 bootstrapv4轮播图2021-03-20
前端Html5如何实现分享截图的示例代码2021-03-20
使用canvas实现雪花飘动效果的示例代码Canvas实现放大镜效果完整案例分析(附代码),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值...
2020-11-26
webview适配H5上传照片或者视频文件的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值...
2020-11-04