canvas 贪吃蛇

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title></title>

        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            
            #myCanvas {
                background-color: burlywood;
            }
        </style>
    </head>

    <body>
        <input type="button" name="btn" id="btn" value="开始" /><br />
        <canvas id="myCanvas" width="1000" height="600"></canvas>
    </body>
    <script type="text/javascript">
        var canvas = document.getElementById("myCanvas");
        var pen = canvas.getContext("2d");
        var btn = document.getElementById("btn");

        var sankeLength = 5;
        var timer = null;
        btn.onclick = function() {
            function Snake() {
                this.x = -40;
                this.y = 40;
                this.w = 40;
                this.h = 40;
                this.color = "gray";
                this.speed = 40;
                // 方向
                this.left = false;
                this.top = false;
                // 默认往右
                this.right = true;
                this.bottom = false;
                // 用于装蛇的每个矩形块的信息(包括头部的)
                this.bodys = [];
            }
            //snake相关的方法
            Snake.prototype.drawSnake = function() {
                    for(var i = 0; i < this.bodys.length; i++) {
                        var snakeRect = this.bodys[i];
                        pen.beginPath();
                        if(i == this.bodys.length - 1) { //找出蛇身颜色黄色
                            pen.fillStyle = "yellow";
                            //其实"蛇头"是在数组中的最后一位
                        } else { //找出蛇头
                            pen.fillStyle = this.color;
                        }
                        pen.fillRect(snakeRect.x, snakeRect.y, snakeRect.w, snakeRect.h)

                        pen.closePath();

                    }
                }
                //处理保存蛇身的数组
            Snake.prototype.savePath = function() {
                var posi = {
                        x: this.x,
                        y: this.y,
                        w: this.w,
                        h: this.h
                    }
                    //把所有位置信息保存数组里
                if(this.bodys.length == sankeLength) { //控制蛇长
                    this.bodys.shift();
                }
                this.bodys.push(posi);
                //改变数组长度

            };
            //画蛇

            //蛇移动
            Snake.prototype.move = function() {
                if(this.top) {
                    this.y -= this.speed;
                } else if(this.bottom) {
                    this.y += this.speed;
                } else if(this.left) {
                    this.x -= this.speed;

                } else if(this.right) {
                    this.x += this.speed;
                }
                //自己吃自己
                for(var i = 0; i < this.bodys.length; i++) {
                    var tempRect = this.bodys[i];
                    if(tempRect.x == this.x && tempRect.y == this.y) {
                        clearInterval(timer);
                        alert("game over");
                    }
                };
                //移动到超出边界的位置
                if(this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height) {
                    clearInterval(timer);
                    alert("game over");
                }
            };
            //上下左右
            document.onkeydown = function(ev) {
                var evObj = ev || window.event;
                switch(ev.keyCode) {
                    case 37:
                        if(!sna.right) {
                            sna.left = true;
                            sna.top = false;
                            sna.right = false;
                            sna.bottom = false;

                        }

                        break;
                    case 38:
                        if(!sna.bottom) {
                            sna.left = false;
                            sna.top = true;

                            sna.right = false;
                            sna.bottom = false;
                        }

                        break;
                    case 39:
                        if(!sna.left) {
                            sna.left = false;
                            sna.top = false;
                            sna.bottom = false;
                            sna.right = true;
                        }

                        break;
                    case 40:
                        if(!sna.top) {
                            sna.left = false;
                            sna.top = false;
                            sna.bottom = true;
                            sna.right = false;
                        }

                        break;
                    default:
                        break;
                }
            };
            var sna = new Snake();
            //食物food
            function Food() {
                this.x = 0;
                this.y = 0;
                this.w = 40;
                this.h = 40;
                this.color = "red";
            }
            //在A类的方法中使用B类的属性
            //1 声明全局变量接受
            //2 将b作为形参传给 a的方法中
            //3 在A方法之前声明一个A类的对象

            //Food相关方法
            Food.prototype.drawFood = function() {
                pen.beginPath();
                pen.fillStyle = this.color;
                pen.fillRect(this.x, this.y, this.w, this.h);
                pen.closePath();
            };

            function rand(max, min) {
                return parseInt(Math.random() * (max + 1 - min) + min);

            }

            //给食物设置位置
            Food.prototype.setFoodPosition = function() {

                //随机位置
                this.x = rand(0, (canvas.width - this.w) / 40) * 40;
                console.log(this.x);
                this.y = rand(0, (canvas.height - this.h) / 40) * 40;
                console.log(this.y);
                for(var i = 0; i < sna.bodys.length; i++) {
                    var tempRect = sna.bodys[i];
                    //当食物出现在蛇身上
                    if(tempRect.x == this.x && tempRect == this.y) {
                        break;

                    }
                }
                //            this.setFoodPosition();
            };
            var food = new Food();
            food.setFoodPosition();
            //验证
            timer = setInterval(function() {
                pen.clearRect(0, 0, canvas.width, canvas.height);
                sna.move();
                sna.savePath();
                sna.drawSnake();
                //            
                food.drawFood();
                var result = checkCrash(sna, food);
                if(result) {
                    food.setFoodPosition();
                    sankeLength++;
                }
            }, 300)

            //公共方法
            //矩形碰撞检测
            //这个方法的使用前提:两个对象必须有x,y,w,h属性
            function checkCrash(obj1, obj2) {
                //求临界值
                var disX = obj1.w / 2 + obj2.w / 2;
                var disY = obj1.h / 2 + obj2.h / 2;
                //计算两个中心点的距离
                var centerX = Math.abs(
                    (obj2.x + obj2.w / 2) -
                    (obj1.x + obj1.w / 2)
                );
                var centerY = Math.abs(
                    (obj2.y + obj2.h / 2) -
                    (obj1.y + obj1.h / 2)
                );

                if(centerX < disX && centerY < disY) {
                    return true;
                } else {
                    return false;
                }
            };
        }
    </script>

</html>

原文地址:https://www.cnblogs.com/zhangbaile/p/5912316.html