canvas贪吃蛇效果 html+css+js
发布日期:2021-05-07 18:24:12 浏览次数:12 分类:原创文章

本文共 13537 字,大约阅读时间需要 45 分钟。

一.话不多,先瞅效果:

视频演示~

在这里插入图片描述

又在别的地方嫖到了这个效果研究了亿下下,制作过程如下(超详细):

二.实现过程(源码在最后):

1.定义canvas标签:

 <canvas id="canvas"></canvas>

2.基本css样式:

#canvas{               position: absolute;            top: 50%;            left: 50%;            transform: translate(-50%,-50%);            box-shadow:  0 0 10px rgb(150, 150, 150);             }

position: absolute; 绝对定位。
top: 50%;
left: 50%;
transform: translate(-50%,-50%); 居中。
box-shadow: 0 0 10px rgb(150, 150, 150); 阴影。

3.开始js部分,获取标签:

var canvas = document.querySelector("#canvas");var ctx = canvas.getContext('2d');            

4.定义基本变量:

        //画布宽        var wide=600;        //画布高        var high=600;        // 变量,判断一次渲染中只识别按键一次        var kd = 0;        //当前分数        var fraction =0;        //速度,就是执行定时器的时间参数        var speed = 250;        // 蛇的初始颜色 红色        var yanse = `red`;        // 蛇数组,组成蛇的每一个方块        var snake = [];        // 食物数组        var food = {   };        // 蛇的移动方向,x轴:1为向右,-1为向左;y轴:1为向下,-1为向上 。不能斜着走,所以0为某轴无方向。        var diretion = {               x:-1,            y:0        }        // 给画布宽高赋值 打算画一个长宽都是30个20px的方块画布        canvas.width = wide;        canvas.height = high;

5. 初始化:

function chushi(){                       //蛇初始长度为3个方块,位置如下(这个随意)            for(let i =0;i<3;i++){                   snake.push({                       x: i+10,                    y: 10                })            }            // 给食物一个随机位置和随机颜色            food = {                   x: parseInt(Math.random()*30),                y: parseInt(Math.random()*30),                color:`rgb(${     Math.random()*255},${     Math.random()*255},${     Math.random()*255})`            }        }

6. 绘制图形:

  // 绘制图形        function draw(){               // 绘制显示当前分数的文字            ctx.fillStyle = 'rgba(255,255,255,0.5)';                ctx.font="50px 仿宋";                ctx.textAlign = 'center';                 ctx.fillText("你的分数为:"+fraction+" 分",300,300);             // 绘制方格,长宽都是30个,都是19px*19px的方格               for(let i=0;i<30;i++){                   for(let j=0;j<30;j++){                       ctx.fillStyle = 'rgba(255, 255, 255,.3)';                    ctx.fillRect(i*20,j*20,19,19);                }            }              // 绘制蛇            for(let i=0;i<snake.length;i++){                   temp = snake[i];                ctx.fillStyle = yanse;                ctx.fillRect(temp.x*20,temp.y*20,19,19);                // 判断蛇头(第一个方块)是否与身体某个方块重合 ,就是头撞到身体                if(temp.x==snake[0].x&&temp.y==snake[0].y&&i!=0){                       // 游戏结束,重新给初始化                    alert('游戏结束~点击确认再来一次~');                     fraction = 0;                    snake.length=0;                      chushi();                                    }            }               // 绘制食物,绘制一个圆形                ctx.beginPath();                ctx.fillStyle = food.color;                ctx.arc(food.x*20+9.5,food.y*20+9.5,7,0,Math.PI*2,false);                ctx.stroke();                ctx.fill();                ctx.closePath();                     // 给蛇头绘制一个字符,☆ ,好区分头尾 ,也可省略                ctx.fillStyle = 'yellow';                ctx.font="15px 仿宋";                ctx.textAlign = "start";                ctx.fillText("☆",snake[0].x*20+2,snake[0].y*20+14.5);                                       }

7.更新位置:

 //更新        function update(){               // 建一个对象head,这个为蛇的新头,通过绘制新头,去掉尾部实现移动效果            var head = {   };            //判断蛇头是否遇到边界,到边界则在另一边重新绘制 x轴            switch (snake[0].x+diretion.x){                   case -1: head.x=29;break;                case 30: head.x=0;break;                // 没到边界则为当前位置加方向                default:  head.x = snake[0].x+diretion.x;            }           //判断蛇头是否遇到边界,到边界则在另一边重新绘制 y轴            switch (snake[0].y+diretion.y){                   case -1: head.y=29;break;                case 30: head.y=0;break;                // 没到边界则为当前位置加方向                default:  head.y = snake[0].y+diretion.y;            }            // 判断新蛇头是否与食物重合,就是吃到食物           if(head.x==food.x&&head.y==food.y){                  //蛇的颜色为吃到食物的颜色            yanse = food.color;             // 重新给食物初始化            food = {                   x: parseInt(Math.random()*30),                y: parseInt(Math.random()*30),                color:`rgb(${     Math.random()*255},${     Math.random()*255},${     Math.random()*255})`            }            //在蛇尾添加一节            let temp = snake[length-1];            snake.push(temp);            fraction+=1;            // 吃完食物速度加快            if(speed>80){                   //定时器间隔减10                speed = speed-10;                // 清除原来定时器,重新绘制                clearInterval(time);                 time = setInterval(function () {                       kd = 0;                    ctx.clearRect(0, 0, wide, high);                    update();                    draw();                }, speed);                        }                      }            //添加新头            snake.splice(0,0,head);            //去掉尾部            snake.pop();                             }

8.判断点击键盘事件:

 //判断点击事件         document.addEventListener('keydown', event=>{                 switch (event.keyCode){                     // 按了向上键                  case 38:                      // 判断当前不是向下移动与还没按过键,否则蛇会重叠                      if(diretion.y!=1&&kd==0){                             // 重新给移动方向赋值                        diretion.x=0;                        diretion.y=-1;                        kd=1;                      }                      break;                      // 下面以此类推一样的原理                  case 39:                      if(diretion.x!=-1&&kd==0){                           diretion.x=1;                        diretion.y=0;                        kd=1;                      }                      break;                  case 40:                      if(diretion.y!=-1&&kd==0){                                              diretion.x=0;                      diretion.y=1;                      kd=1;                      }                      break;                   case 37:                      if(diretion.x!=1&&kd==0){                           diretion.x=-1;                        diretion.y=0;                        kd=1;                      }                      break;                      }        })

9.设置定时器,开始动画:

 chushi();                var time = setInterval(function(){               kd=0;            ctx.clearRect(0,0,wide,high);            update();            draw();                      },speed);

三.完整代码:

<!DOCTYPE html><html lang="zh-CN"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    <style>        *{                margin: 0;            padding: 0;            box-sizing: border-box;        }        body{                height: 100vh;        }        video{                position: fixed;            z-index: -10;            width: 100%;            height: 100%;            object-fit: cover;        }        #canvas{                position: absolute;            top: 50%;            left: 50%;            transform: translate(-50%,-50%);            box-shadow:  0 0 10px rgb(150, 150, 150);             }    </style></head><body>    <video src="video/rain.mp4" muted autoplay loop></video>    <canvas id="canvas"></canvas>    <script>        var canvas = document.querySelector("#canvas");        var ctx = canvas.getContext('2d');        //画布宽         var wide=600;        //画布高        var high=600;        // 变量,判断一次渲染中只识别按键一次        var kd = 0;        //当前分数        var fraction =0;        //速度,就是执行定时器的时间参数        var speed = 250;        // 蛇的初始颜色 红色        var yanse = `red`;        // 蛇数组,组成蛇的每一个方块        var snake = [];        // 食物数组        var food = {    };        // 蛇的移动方向,x轴:1为向右,-1为向左;y轴:1为向下,-1为向上 。不能斜着走,所以0为某轴无方向。        var diretion = {                x:-1,            y:0        }        // 给画布宽高赋值 打算画一个长宽都是30个20px的方块画布        canvas.width = wide;        canvas.height = high;        function chushi(){                        //蛇初始长度为3个方块,每个位置如下(这个随意)            for(let i =0;i<3;i++){                    snake.push({                        x: i+10,                    y: 10                })            }            // 给食物一个随机位置和随机颜色            food = {                    x: parseInt(Math.random()*30),                y: parseInt(Math.random()*30),                color:`rgb(${      Math.random()*255},${      Math.random()*255},${      Math.random()*255})`            }        }        // 绘制图形        function draw(){                // 绘制显示当前分数的文字            ctx.fillStyle = 'rgba(255,255,255,0.5)';                ctx.font="50px 仿宋";                ctx.textAlign = 'center';                 ctx.fillText("你的分数为:"+fraction+" 分",300,300);             // 绘制方格,长宽都是30个,都是19px*19px的方格               for(let i=0;i<30;i++){                    for(let j=0;j<30;j++){                        ctx.fillStyle = 'rgba(255, 255, 255,.3)';                    ctx.fillRect(i*20,j*20,19,19);                }            }              // 绘制蛇            for(let i=0;i<snake.length;i++){                    temp = snake[i];                ctx.fillStyle = yanse;                ctx.fillRect(temp.x*20,temp.y*20,19,19);                // 判断蛇头(第一个方块)是否与身体某个方块重合 ,就是头撞到身体                if(temp.x==snake[0].x&&temp.y==snake[0].y&&i!=0){                        // 游戏结束,重新给初始化                    alert('游戏结束~点击确认再来一次~');                     fraction = 0;                    snake.length=0;                      chushi();                                    }            }               // 绘制食物,绘制一个圆形                ctx.beginPath();                ctx.fillStyle = food.color;                ctx.arc(food.x*20+9.5,food.y*20+9.5,7,0,Math.PI*2,false);                ctx.stroke();                ctx.fill();                ctx.closePath();                /* var img = new Image();                img.src = "img/snake/orange.png";                img.onload = function(){                    ctx.drawImage(img,food.x*20,food.y*20,19,19);                }  */                     // 给蛇头绘制一个字符,☆ ,好区分头尾 ,也可省略                ctx.fillStyle = 'yellow';                ctx.font="15px 仿宋";                ctx.textAlign = "start";                ctx.fillText("☆",snake[0].x*20+2,snake[0].y*20+14.5);                                       }        //更新        function update(){                // 建一个对象head,这个为蛇的新头,通过绘制新头,去掉尾部实现移动效果            var head = {    };            //判断蛇头是否遇到边界,到边界则在另一边重新绘制 x轴            switch (snake[0].x+diretion.x){                    case -1: head.x=29;break;                case 30: head.x=0;break;                // 没到边界则为当前位置加方向                default:  head.x = snake[0].x+diretion.x;            }           //判断蛇头是否遇到边界,到边界则在另一边重新绘制 y轴            switch (snake[0].y+diretion.y){                    case -1: head.y=29;break;                case 30: head.y=0;break;                // 没到边界则为当前位置加方向                default:  head.y = snake[0].y+diretion.y;            }            // 判断新蛇头是否与食物重合,就是吃到食物           if(head.x==food.x&&head.y==food.y){                   //蛇的颜色为吃到食物的颜色            yanse = food.color;             // 重新给食物初始化            food = {                    x: parseInt(Math.random()*30),                y: parseInt(Math.random()*30),                color:`rgb(${      Math.random()*255},${      Math.random()*255},${      Math.random()*255})`            }            //在蛇尾添加一节            let temp = snake[length-1];            snake.push(temp);            fraction+=1;            // 吃完食物速度加快            if(speed>80){                    //定时器间隔减10                speed = speed-10;                // 清除原来定时器,重新绘制                clearInterval(time);                 time = setInterval(function () {                        kd = 0;                    ctx.clearRect(0, 0, wide, high);                    update();                    draw();                }, speed);                        }                      }            //添加新头            snake.splice(0,0,head);            //去掉尾部            snake.pop();                             }       //判断点击事件         document.addEventListener('keydown', event=>{                  switch (event.keyCode){                      // 按了向上键                  case 38:                      // 判断当前不是向下移动与还没按过键,否则蛇会重叠                      if(diretion.y!=1&&kd==0){                              // 重新给移动方向赋值                        diretion.x=0;                        diretion.y=-1;                        kd=1;                      }                      break;                      // 下面以此类推一样的原理                  case 39:                      if(diretion.x!=-1&&kd==0){                            diretion.x=1;                        diretion.y=0;                        kd=1;                      }                      break;                  case 40:                      if(diretion.y!=-1&&kd==0){                                               diretion.x=0;                      diretion.y=1;                      kd=1;                      }                      break;                   case 37:                      if(diretion.x!=1&&kd==0){                            diretion.x=-1;                        diretion.y=0;                        kd=1;                      }                      break;                      }        })        chushi();                var time = setInterval(function(){                kd=0;            ctx.clearRect(0,0,wide,high);            update();            draw();                      },speed);            </script></body></html>

四.总结:

最近又在听蕊希电台了。干点鸡汤~
在这里插入图片描述

上一篇:跟随鼠标移动的星星✩直接在页面引用✧✧✧
下一篇:3D分层图像悬停效果 html+css

发表评论

最新留言

关注你微信了!
[***.104.42.241]2025年04月11日 12时49分21秒