h5贪吃蛇

01/19 12:55
阅读数 79

h5制作贪吃蛇


使用canvas制作的一个贪吃蛇小游戏,写了一写比较简单的算法,望大佬们多多指正!!!多的不说直接看代码吧。

html

规划一个游戏界面

<div class="mian">
        <canvas id='huaban'></canvas>
    </div>

css

html,
        body {
   
    
            padding: 0;
            margin: 0;
        }

        body {
   
    
            background: black;
        }

        .mian {
   
    
            margin: auto;
            width: 800px;
            height: 500px;
            margin-top: 30px;
            background: rgba(255, 251, 251, 0.089);
        }

js

var s_X = 0, s_Y = 0;//存储鼠标实时的位置
        var c_w = window.innerWidth / 2 - 400, c_h = 30;//初始窗口的大小
        var life = true;//蛇的生命
        var body_arr = [],//身体继承存储数组 
            body_jc = [],
            food_color = ['#1db0b8', '#de8100', '#3b200c', '#ff534d', '#edd0be'], //食物随机颜色存储的数组
            _bg,//背景的对象
            sk,//蛇的对象 
            speed = 1000 / 120,//定时器的速度
            food_number = 1,//单位大小内食物的个数
            zanti = 1,//暂停
            time = 0;//整体的时间线
        var food = [
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []],
            [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
        ];//食物池
        var huabu = document.querySelector('#huaban');
        var huaban = huabu.getContext('2d');
        function daxiao() {
   
    
            huabu.width = 800;
            huabu.height = 500;
        }//画板的宽高
        daxiao();
        window.onresize = function () {
   
    
            c_w = window.innerWidth / 2 - 400;//当界面窗口发生变化时窗口大小
        }
        class bg {
   
    
            x = -800;
            y = -500;
            hua() {
   
    //使用两个循环来制作地图,而不是循环的嵌套,从而减轻计算机的负担
                huaban.clearRect(0, 0, 800, 500);
                huaban.lineWidth = 1;
                huaban.strokeStyle = 'rgba(255, 251, 251, 0.25)';
                for (var i = 0; i < 2400 / 145; i++) {
   
    
                    huaban.beginPath();
                    huaban.moveTo(this.x, this.y + i * 120);
                    huaban.lineTo(this.x + 800 * 3, this.y + i * 120);
                    huaban.closePath();
                    huaban.stroke();

                }
                for (var j = 0; j < 1500 / 72; j++) {
   
    
                    huaban.beginPath();
                    huaban.moveTo(this.x + j * 120, this.y);
                    huaban.lineTo(this.x + j * 120, this.y + 500 * 3 + 420);
                    huaban.closePath();
                    huaban.stroke();
                }


            };
            move() {
   
    
                this.d = Math.sqrt((s_X - (sk.x + c_w)) ** 2 + (s_Y - (sk.y + c_h)) ** 2);//背景的位置与蛇的位置的距离,一切判断基于此条件
                if (this.d != 0) {
   
    
                    if (this.x < sk.x - sk.r - 2 && this.x + 800 * 3 > sk.x + sk.r + 2) {
   
    //范围判断
                        this.x -= (s_X - (sk.x + c_w)) / this.d;
                        sk.relative_x += (s_X - (sk.x + c_w)) / this.d;
                    } else {
   
    
                        life = false;
                        // if (s_X > sk.x + c_w && this.x + 800 * 3 > sk.x + sk.r + 2) {
   
    
                        //     this.x -= (s_X - (sk.x + c_w)) / this.d;
                        // }
                        // if (s_X < sk.x + c_w && this.x < sk.x - sk.r - 2) {
   
    
                        //     this.x -= (s_X - (sk.x + c_w)) / this.d;
                        // }//边界不会超出
                    }//注释掉的代码为当蛇到达x边界时不会死亡只是不能超游戏界面外运动
                    if (this.y < sk.y - sk.r - 2 && this.y + 600 * 3 + 120 > sk.y + sk.r + 2) {
   
    
                        this.y -= (s_Y - (sk.y + c_h)) / this.d;
                        sk.relative_y += (s_Y - (sk.y + c_h)) / this.d;
                    } else {
   
    
                        life = false;
                        // if (s_Y > sk.x + c_h && this.y + 600 * 3 + 120 > sk.y + sk.r + 2) {
   
    
                        //     this.y -= (s_Y - (sk.y + c_h)) / this.d;
                        // }
                        // if (s_Y < sk.y + c_h && this.y < sk.y - sk.r - 2) {
   
    
                        //     this.y -= (s_Y - (sk.y + c_h)) / this.d;
                        // }//边界不会超出
                    }//注释掉的代码为当蛇到达y边界时不会死亡只是不能超游戏界面外运动


                }
                sk.body(sk.x - (s_X - (sk.x + c_w)) / this.d * 20, sk.y - (s_Y - (sk.y + c_h)) / this.d * 20);//一直传递蛇身体新的位置
                sk.eat();//画食物
                this.hua();//背景画
                for (var i = 0; i < 20; i++) {
   
    
                    for (var j = 0; j < 16; j++) {
   
    
                        for (var k = 0; k < food[i][j].length; k++) {
   
    
                            food[i][j][k].x -= (s_X - (sk.x + c_w)) / this.d;
                            food[i][j][k].y -= (s_Y - (sk.y + c_h)) / this.d;
                            food[i][j][k].creta();
                        }//食物的遍历更新食物的位置
                    }
                }
                // if (body_arr.length >= 9) {
   
    
                //     console.log(body_jc, body_arr)
                //     body_jc[0].x = body_arr[5].x;
                //     body_jc[0].y = body_arr[5].y;
                //     body_jc[0].hua();
                // }//对蛇身体开始更新位置
                sk.eye_x = 14 * ((s_X - (sk.x + c_w))) / this.d;
                sk.eye_y = 14 * (-(s_Y - (sk.y + c_h))) / this.d;//蛇眼睛珠子的位置随着不同方向从而一直变化
                sk.head();//画蛇头
                time++;
            }
            run() {
   
    
                var time = setInterval(() => {
   
    
                    this.move()
                    if (life == false) {
   
    //当蛇死掉时清除定时器
                        clearInterval(time);
                        jieshu();
                    }
                }, speed)
            }//蛇身体开始运动并且开始一直从新画背景
        }
        class snake {
   
    
            x = 800 / 2;
            y = 500 / 2;
            r = 20;//蛇头位置固定在屏幕中间
            color = '#ffa400';
            relative_x = 400;
            relative_y = 250;
            eye_x = 14;
            eye_y = 0;//眼睛珠子初始的位置
            weight = 0;
            head() {
   
    
                huaban.beginPath();
                huaban.fillStyle = 'white';
                huaban.arc(this.x, this.y, this.r + 2, 0, Math.PI * 2);
                huaban.fill();//蛇头边界
                huaban.beginPath();
                huaban.fillStyle = this.color;
                huaban.arc(this.x, this.y, this.r, 0, Math.PI * 2);
                huaban.fill();//蛇头主体
                huaban.beginPath();
                huaban.fillStyle = 'white';
                huaban.arc(this.x + this.eye_y, this.y + this.eye_x, 10, 0, Math.PI * 2);
                huaban.fill();//蛇左眼睛
                huaban.beginPath();
                huaban.fillStyle = 'black';
                huaban.arc(this.x + this.eye_y, this.y + this.eye_x, 5, 0, Math.PI * 2);
                huaban.fill();//蛇左眼睛珠子
                huaban.beginPath();
                huaban.fillStyle = 'white';
                huaban.arc(this.x - this.eye_y, this.y - this.eye_x, 10, 0, Math.PI * 2);
                huaban.fill();//蛇右眼睛
                huaban.beginPath();
                huaban.fillStyle = 'black';
                huaban.arc(this.x - this.eye_y, this.y - this.eye_x, 5, 0, Math.PI * 2);
                huaban.fill();//蛇右眼睛珠子
            };//蛇头的函数
            body(x, y) {
   
    
                body_arr.push({
   
     'x': x, 'y': y });
                if (body_arr.length >= 10) {
   
    
                    body_arr.splice(0, 1);
                }
            };//将蛇头的坐标传递进body_arr数组实现第二节身体继承
            eat() {
   
    
                var i = 19 - Math.abs(parseInt((_bg.x - this.x + 800 * 3) / 120));
                var j = 15 - Math.abs(parseInt((_bg.y - this.y + 600 * 3 + 120) / 120));
                for (var k = 0; k < food[i][j].length; k++) {
   
    
                    food[i][j][k].d = Math.sqrt((food[i][j][k].x - this.x) ** 2 + (food[i][j][k].y - this.y) ** 2);//计算食物与自己的距离
                    // console.log('中心点'+sk.relative_x,'食物'+food[i][j][k].x);
                    // console.log('中心点'+sk.relative_y,'食物'+food[i][j][k].y)
                    if (food[i][j][k].d < food[i][j][k].r + this.r + 20) {
   
    
                        food[i][j][k].move(i, j, k);
                        this.weight += food[i][j][k].weight;
                    }
                }
            }
        }//吃东西的函数
        function _body(x, y) {
   
    
            this.x = x;
            this.y = y;
            this.r = 15;
            this.d = 100;
            this.color = '#ffa400';
            this.hua = function () {
   
    
                huaban.beginPath();
                huaban.fillStyle = 'white';
                huaban.arc(this.x, this.y, this.r + 2, 0, Math.PI * 2);
                huaban.fill();//蛇头边界
                huaban.beginPath();
                huaban.fillStyle = this.color;
                huaban.arc(this.x, this.y, this.r, 0, Math.PI * 2);
                huaban.fill();//蛇头主体
            }
        }//蛇身体的构造函数
        function _food(x, y) {
   
    
            this.x = x;
            this.y = y;
            this.r = suiji(1, 3);
            this.weight = this.r;
            this.color = food_color[parseInt(suiji(0, 4))];
            this.creta = function () {
   
    
                huaban.beginPath();
                huaban.fillStyle = this.color;
                huaban.arc(this.x, this.y, this.r + 2, 0, Math.PI * 2);
                huaban.fill();//画食物
            };
            this.move = function (i, j, k) {
   
    
                var moveTime = setInterval(() => {
   
    
                    if (this.d < sk.r) {
   
    
                        clearInterval(moveTime);
                        food[i][j].splice(k, 1);
                    } else {
   
    
                        this.c = Math.sqrt((this.x - sk.x) ** 2 + (this.y - sk.y) ** 2);
                        this.x -= (this.x - sk.x) / this.c;
                        this.y -= (this.y - sk.y) / this.c;//
                    }
                }, 1000 / 60)
            }
        }//食物的构造函数
        function suiji(max, min) {
   
    
            return Math.random() * (max - min) + min;
        }//随机数函数
        function add_food() {
   
    
            for (var i = 0; i < 20; i++) {
   
    
                for (var j = 0; j < 16; j++) {
   
    
                    for (var k = 0; k < food_number; k++) {
   
    
                        var _food_ = new _food(suiji(-800 + i * 120, -800 + (i + 1) * 120), suiji(-500 + j * 120, -500 + (j + 1) * 120));
                        food[i][j].push(_food_);
                        _food_.creta();
                    }
                }
            }
        }//将食物添加进地图并用food三维数组来存储
        function start() {
   
    
            _bg = new bg();
            _bg.hua();
            sk = new snake();
            sk.head();
            _bg.run();
            add_food();
            body_jc.push[new _body(0, 0)];
        }//开始函数
        function jieshu() {
   
    
            // huaban.clearRect(0, 0, 800, 500);//清除屏幕
        }//蛇死掉时执行的函数
        start();//开始执行的函数

        function mouseMove(ev) {
   
    
            ev = ev || window.event;
            var mousePos = mouseCords(ev);
            s_X = mousePos.x, s_Y = mousePos.y;
        }//传递鼠标实时位置给s_X,s_Y。
        function mouseCords(ev) {
   
    
            if (ev.pageX || ev.pageY) {
   
    
                return {
   
    
                    x: ev.pageX, y: ev.pageY
                };
            }
            //获取鼠标的实时位置
        }
        document.onmousemove = mouseMove;//鼠标位置
        document.querySelector('.mian').onclick = function () {
   
    
            zanti++;
            zanti % 2 == 0 ? life = false : life = true;
            _bg.run();
        }

游戏效果

游戏效果图
在这里插入图片描述
在这里插入图片描述
食物池来来存放的食物,减轻计算机的工作量,更高效的运行这个游戏,对手还没有写,自己的身体也还没有写,涉及到一些继承的算法,还在思考中,请大佬们赐教。



展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部