效果如下
代码
贪吃蛇
let canvas = document.getElementById("canvas");let context = canvas.getContext("2d");// 分数记录let fraction = 0;// 定义贪吃蛇的组成,方块对象class Block{ // 按照size的大小划分行列 // 列 col; // 行 row; // 大小 size; constructor(col, row, size){ this.col = col; this.row = row; this.size = size; } // 画方法 draw(){ context.fillRect(this.col * this.size, this.row * this.size, this.size, this.size); }}// 蛇类class Snake{ body = [new Block(20, 20, 10), new Block(20, 21, 10)]; direction = "right"; apple; constructor(apple) { this.apple = apple; } draw(){ for(let i = 0; i < this.body.length; i++){ this.body[i].draw(); } }; move(){ let head = this.body[0]; // 用于生成新蛇的方块 let newhead; if(this.direction == "right"){ newhead = new Block(head.col + 1, head.row, head.size); } if(this.direction == "left"){ newhead = new Block(head.col - 1, head.row, head.size); } if(this.direction == "up"){ newhead = new Block(head.col, head.row - 1, head.size); } if(this.direction == "down"){ newhead = new Block(head.col, head.row + 1, head.size); } // 增加头部 this.body.unshift(newhead); // 进行判断蛇头是否碰到了苹果,若碰到了则不删除最后一个方块,反之删除最后一个方块 if(newhead.col == this.apple.col && newhead.row == this.apple.row){ // 进行检测,如果生成在蛇身上,继续生成,反之结束循环 while(true){ this.apple.initialization(); for(let i = 0; i < this.body.length; i++){ if(this.apple.row == this.body[i].row && this.apple.col == this.body[i].col){ this.apple.initialization(); } } break; } // 分数加入 fraction++; }else{ // 弹出 this.body.pop(); } }; // 碰撞检测 impactChecking(){ // 获取头节点 let newBody = this.body[0]; console.log(newBody.col); // 查看行,列是否超过边界 if(newBody.col > 40 || newBody.row > 40 || newBody.row < 0 || newBody.col < 0){ alert("游戏结束"); fraction = 0; this.body = [new Block(20, 20, 10), new Block(20, 21, 10)]; } // 查看是否碰到自己身体 for(let i = 1; i < this.body.length; i++){ if(newBody.col == this.body[i].col && newBody.row == this.body[i].row){ alert("游戏结束"); fraction = 0; this.body = [new Block(20, 20, 10), new Block(20, 21, 10)]; } } }}// 实物,苹果类class Apple{ // 列 col; // 行 row; sizeR; constructor(){ this.initialization(); }; // 初始化苹果 initialization(){ // 生成列坐标 this.col = Math.floor(Math.random() * (40 - 1) + 1); // 生成行坐标 this.row = Math.floor(Math.random() * (40 - 1) + 1); // 设置苹果半径 this.sizeR = 5; } // 画苹果的方法 draw(){ // 颜色 context.fillStyle = "Red"; // 画苹果 context.beginPath(); // 圆心坐标 context.arc(this.col * this.sizeR * 2 + this.sizeR, this.row * this.sizeR * 2 + this.sizeR, this.sizeR, 0, Math.PI * 2, false); // 填充 context.fill(); // 恢复原来颜色 context.fillStyle = "Black"; }}// 生成一个苹果let apple = new Apple();// 生成一个蛇let snake = new Snake(apple);setInterval(() => { context.clearRect(0, 0, 400, 400); // 绘制分数 context.fillText("分数为 " + fraction, 10, 10); // 绘制蛇 snake.draw(); // 对蛇进行移动 snake.move(); // 绘制苹果 apple.draw(); // 进行检测 snake.impactChecking(); context.strokeRect(0, 0, 400, 400);}, 200);// 对贪吃蛇控制// 上下左右运动$("body").keydown((event) => { // 左 if(event.keyCode == 37 && snake.direction != "right"){ snake.direction = "left"; } // 上 if(event.keyCode == 38 && snake.direction != "down"){ snake.direction = "up"; } // 右 if(event.keyCode == 39 && snake.direction != "left"){ snake.direction = "right"; } // 下 if(event.keyCode == 40 && snake.direction != "up"){ snake.direction = "down"; }});
思路
思路,蛇由两个类组成,方块类和蛇类,蛇类的存在依赖于方块类。蛇类当中的body保存当前蛇类的所有的方块。绘图,直接遍历body内部的所有绘图方法。移动,根据保存的私有变量方向用来对数组中保存的方块对象进行更改
还有一个苹果类。用于进行随机生成吃苹果,在移动方法中,如果蛇的头方块和苹果方块重合那么吃到苹果,重新调用生成苹果方法。碰撞检测,如果行和列超过范围,即碰撞发生最重要的,坐标行和列化,使用的时候乘以一个数就行