直接Vue上代码
- <div>
- <div>贪吃蛇div>
- <canvas id="canvas" width="400" height="400">canvas>
- div>
-
-
- <script>
- export default {
- data() {
- return {
- ctx: null,
- interval: null,
- snakeData: [],
- count: 0,//步数
- pointList: [{ x: 36, y: 18 }],//默认点
- direction: "d", // 默认右,w:上,s:下,a:左,d:右
- controll: null,//监听
- controll2: null,//监听
- speedCount: 0, // 渲染倍数
- speed: 8 // 渲染倍数分子
- };
- },
- mounted() {
- // 贪吃蛇,canvas
- const canvas = document.getElementById("canvas");
- this.ctx = canvas.getContext("2d"); // 获取绘制上下文
- const list = [];
- for (let i = 0; i < 2; i++) {
- list.push({
- x: 0 + i * 6,
- y: 0,
- type: "right"
- });
- }
- this.snakeData = list;
- console.log("snakeData", this.snakeData);
- this.setView(list);
- this.controll = new AbortController();
- this.controll2 = new AbortController();
- window.addEventListener(
- "keydown",
- val => {
- if (
- val.key === "w" ||
- val.key === "a" ||
- val.key === "s" ||
- val.key === "d"
- ) {
- // 方向不能相反
- switch (val.key) {
- case "w":
- if (this.direction !== "s") {
- this.direction = "w";
- this.speed = 4;
- }
- break;
- case "a":
- if (this.direction !== "d") {
- this.direction = "a";
- this.speed = 4;
- }
- break;
- case "s":
- if (this.direction !== "w") {
- this.direction = "s";
- this.speed = 4;
- }
- break;
- case "d":
- if (this.direction !== "a") {
- this.direction = "d";
- this.speed = 4;
- }
- break;
- default:
- console.log("方向不合法或无效按键");
- break;
- }
- }
- },
- { signal: this.controll.signal }
- );
- window.addEventListener(
- "keyup",
- val => {
- if (
- val.key === "w" ||
- val.key === "a" ||
- val.key === "s" ||
- val.key === "d"
- ) {
- this.speed = 8;
- }
- },
- { signal: this.controll2.signal }
- );
- this.count = 0;
- this.intervalFun();
- },
- beforeDestroy() {
- this.count = 0;
- this.interval && cancelAnimationFrame(this.interval);
- this.controll.abort();
- this.controll2.abort();
- },
- methods: {
- intervalFun() {
- this.count++;
- this.speedCount++;
- // 默认向右移动
- if (this.count > 5000) {
- // clearInterval(this.interval);
- cancelAnimationFrame(this.interval);
- } else {
- if (this.speedCount % this.speed === 0) {
- // 速度缩减10倍,执行10次才渲染1次
- const w = canvas.clientWidth;
- const h = canvas.clientHeight;
- this.ctx.clearRect(0, 0, w, h);
- this.goForword(this.snakeData);
- }
- }
-
- this.interval = requestAnimationFrame(this.intervalFun);
- },
- goForword(list) {
- // console.log("list1", list);
- const option = { ...list[list.length - 1] };
- if (this.direction === "d") {
- option.x = Number(option.x) + 6;
- } else if (this.direction === "a") {
- option.x = Number(option.x) - 6;
- } else if (this.direction === "w") {
- option.y = Number(option.y) - 6;
- } else if (this.direction === "s") {
- option.y = Number(option.y) + 6;
- }
-
- list.push(option);
- let flag = false;
- // console.log("option", option);
- this.pointList = this.pointList.filter(item => {
- if (option.x === item.x && option.y === item.y) {
- flag = true;
- }
- return item.x !== option.x || item.y !== option.y;
- });
- if (!flag) {
- list.shift();
- } else {
- // 重新生成点
- const x = Math.floor(Math.random() * Math.round(400 / 6)) * 6;
- const y = Math.floor(Math.random() * Math.round(400 / 6)) * 6;
- this.pointList.push({
- x,
- y
- });
- }
- this.snakeData = list;
- // console.log("snakeData", this.snakeData);
- this.setView(this.snakeData); // 画蛇
- this.setView(this.pointList); // 画点
- },
- setView(list) {
- // this.ctx.clearRact(0, 0, 400, 400);
- this.ctx.beginPath();
- for (let i = 0; i < list.length; i++) {
- this.ctx.rect(list[i].x, list[i].y, 6, 6); // 绘制矩形
- }
- this.ctx.fill(); // 描边一个矩形轮廓
- }
- }
- }
- script>
- <style lang="scss" scoped>
-
- #canvas {
- border: 1px solid #dee2ed;
- }
- style>
直接拿着用即可