贪吃蛇游戏(面向对象)

游戏设计

对象:

1.地图

        高度

        宽度

        原子--类似小的div

        x--多少个原子

        y--多少个原子

        显示画布功能

2.食物

        宽度--原子的大小

        高度--原子的大小

        功能,在地图上显示食物

3.蛇

        body---头 体 尾 ---三个div(原子)

        高度---原子的大小

        宽度---原子的大小

        功能:

                1.运动

                2.控制方向

                3.遇到边界,游戏结束,重新开始

                4.遇到食物

                5.自己碰到自己,游戏结束,重新开始

4.升级规则

        1.每升一级,有一个级别号

        2.每升一级,速度加快

        3.每升一级,挑战难度增大

业务流程实现

创建每个对象,相关使用

代码实现

html代码:

<!DOCTYPE html>
<html lang="en">

<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>贪吃蛇</title>
    <script src="js/index.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #main {
            margin: 100px;
        }

        .bnt {
            width: 100px;
            height: 40px;
        }

        .gtitle {
            font-size: 25px;
            font-weight: bold;
        }

        #gnum {
            color: red;
        }
    </style>
</head>

<body>
    <div id="main">
        <h1>贪吃蛇</h1>
        <input class="btn" type="button" value="开始游戏" id="begin">
        <input class="btn" type="button" value="暂停游戏" id="pause">
        <span class="gtitle">第<span id="gnum">1</span>关</span>
        
    </div>
</body>

</html>

js代码:

   /*  !!!注意这里用的是load,不能用onload
    onload可能会有元素没有加载完成,
    load是等所有的元素加载完后才执行 */



window.addEventListener('load',function(){
    var main = document.getElementById('main');
var showcanvas =false;  //是否开启画布上的格子

/* 地图对象的构造方法
atom:原子大小 宽高一样 10
x:横向原子数量
y:纵向原子数量 */
function Map(atom, xnum, ynum) {
    this.atom = atom; //20*20
    this.xnum = xnum;
    this.ynum = ynum;

    // 声明一个画布
    this.canvas = null;

    // 创建画布的方法
    this.create = function () {
        this.canvas = document.createElement("div");

        // canvas的基础样式
        this.canvas.style.cssText = "position:relative;top:40px;border:1px solid darkred;background:#fafafa";
        this.canvas.style.width = this.atom * this.xnum + 'px'; //画布的宽
        this.canvas.style.height = this.atom * this.ynum + 'px'; //画布的高

        // 给main追加子元素,就相当于把main当做父亲,然后通过main来显示this.canvas
        // appendChild里面要添加的是有效节点,而不是字符串,所以不能加引号!!!
        main.appendChild(this.canvas);

        if (showcanvas) {
            // 画出整个画布
            for (var y = 0; y < ynum; y++) {
                // 画一行
                for (var x = 0; x < xnum; x++) {
                    var a = document.createElement('div');
                    a.style.cssText = "border:1px solid #fafafa";
                    a.style.width = this.atom + 'px';
                    a.style.height = this.atom + 'px';
                    a.style.backgroundColor = 'green';
                    // 在画布里追加a
                    this.canvas.appendChild(a);
                    a.style.position = 'absolute';
                    a.style.left = x * this.atom + 'px';
                    a.style.top = y * this.atom + 'px';
                }
            }
        }
    }
}
// 创建食物对象的构造方法,将地图对象作为参数
function Food(map) {
    this.width = map.atom;
    this.height = map.atom;
    // 生成随机颜色的食物 floor--向下取整
    this.bgcolor = 'rgb(' + Math.floor(Math.random() * 200) + ',' + Math.floor(Math.random() * 200) + ',' + Math.floor(Math.random() * 200) + ')';
    // 保证食物不超出地图的范围
    this.x = Math.floor(Math.random() * map.xnum);
    this.y = Math.floor(Math.random() * map.ynum);

    this.flag = document.createElement('div');
    this.flag.style.width = this.width + 'px';
    this.flag.style.height = this.height + 'px';
    this.flag.style.backgroundColor = this.bgcolor;
    this.flag.style.borderRadius = '50%'; //圆形的食物
    this.flag.style.position = 'absolute';
    this.flag.style.left = this.x * this.width + 'px';
    this.flag.style.top = this.y * this.height + 'px';
    // 将食物追加到地图里面
    map.canvas.appendChild(this.flag);
}

// 创建蛇
function Snake(map) {
    //设置宽、高
    this.width = map.atom;
    this.height = map.atom;
    //默认走的方向
    this.direction = 'right';

    this.body = [
        { x: 2, y: 0 }, //蛇头
        { x: 1, y: 0 }, //蛇身
        { x: 0, y: 0 } //蛇尾
    ];

    //显示蛇
    this.display = function () {
        for (var i = 0; i < this.body.length; i++) {
            //当吃到食物时,x===null,不能新建食物,不然会在0,0处新建一个;当x!=null时,才创建新的食物
            if (this.body[i].x != null) {
                var s = document.createElement('div');
                // 将蛇的节点保存到一个状态变量中,以便以后删除使用
                this.body[i].flag = s;

                // 设置蛇的样式
                s.style.width = this.width + 'px';
                s.style.height = this.height + 'px';
                s.style.backgroundColor = 'rgb(' + Math.floor(Math.random() * 200) + ',' + Math.floor(Math.random() * 200) + ',' + Math.floor(Math.random() * 200) + ')';
                s.style.borderRadius = '50%';

                // 设置位置
                s.style.position = 'absolute';
                s.style.left = this.body[i].x * this.width + 'px';
                s.style.top = this.body[i].y * this.height + 'px';
                map.canvas.appendChild(s);

            }
        }
    }
    //让蛇运动起来
    this.run = function () {
        /*   
        0{x:2,y:0}, //蛇头
        1{x:1,y:0}, //蛇身
        2{x:0,y:0} //蛇尾

        0 {x:2,y:0}, //蛇头
        1{x:2,y:0}, //蛇身
        2{x:1,y:0} //蛇尾
        
      
        */
        // 将蛇前一格身体的X赋给后一格,这样蛇身整体向前挪动一格,目前蛇头位置还没变
        // for循环遍历
        for (var i = this.body.length - 1; i > 0; i--) {
            this.body[i].x = this.body[i - 1].x;
            this.body[i].y = this.body[i - 1].y;
        }
        // 默认是向右走(right) 讨论left、up、down
        // 根据方向处理蛇头
        switch (this.direction) {
            case 'left': this.body[0].x -= 1;  //如果向左走 则蛇头为x-1(根据网页坐标系可知)
                break;
            case 'right': this.body[0].x += 1;  //如果向右走 则蛇头为x+1(根据网页坐标系可知)
                break;
            case 'up': this.body[0].y -= 1; //如果向上走 则蛇头为y-1
                break;
            case 'down': this.body[0].y += 1; //如果向下走 则蛇头为y+1
                break;
        }

        // 判断蛇头吃到食物,判断条件蛇头的xy和食物的xy重合
        if (this.body[0].x == food.x && this.body[0].y == food.y) {
            //蛇吃到食物后,加一节,在尾部加
            //加入空的元素,执行run方法时,之前蛇的尾部会赋值给这个空元素
            this.body.push({ x: null, y: null, flag: null });

            // 判断设置级别
            if(this.body.length > l.slength){
                l.set();
            }


            map.canvas.removeChild(food.flag); //蛇吃掉食物,删除食物
            food = new Food(map);  //食物被吃掉后,新建一个食物
        }

        // 判断是否出界,蛇头来判断
        if (this.body[0].x < 0 || this.body[0].x > map.xnum - 1 || this.body[0].y < 0 || this.body[0].y > map.ynum - 1) {
            clearInterval(timer); //清除定时器暂停游戏
            alert('game over');

            // 重新开始游戏
            restart(map, this);

            return false;   //var showcanvas = true;  //是否开启画布上的格子 等于false就是不开启


        }



        // 判断是否和自己重合
        // 为什么i是4,因为考虑到内存和效率的问题,能少循环几次就少循环几次,蛇的长度最短是3,围不成一个环
        for (var i = 4; i < this.body.length; i++) {
            if (this.body[0].x == this.body[i].x && this.body[0].y == this.body[i].y) {
                clearInterval(timer); //清除定时器暂停游戏
                alert('game over');

                // 重新开始游戏
                restart(map, this);

                return false;  
            }
        }




        // 将原来所有的都删掉
        for (var i = 0; i < this.body.length; i++) {
            if (this.body[i].flag != null) { //当吃到食物,flag是等于null,且不能删除
                // flag 是标记div
                map.canvas.removeChild(this.body[i].flag);
            }
        }
        this.display();
    }

}

//设置级别对象
function Level() {
    this.num = 1; //第几级别
    this.speed = 300; //毫秒 ,每升一关,数量减少20, 速度逐渐加快
    this.slength = 10; //通过判断蛇的长度,来判断关卡级别

    this.set = function () {
        this.num++;
        if (this.speed <= 50) {
            this.speed = 50;
        } else {
            this.speed -= 50;
        }
        this.slength += 3; //蛇的长度每加3个就升一关
        this.display();
        start();  //重新开始,速度加快
    }

    this.display = function () {
        document.getElementById('gnum').innerHTML = this.num;
    }

}
var l = new Level();
l.display();




// 重新开始游戏
function restart(map, snake) {
    // 清除之前的蛇和食物
    for (var i = 0; i < snake.body.length; i++) {
        map.canvas.removeChild(snake.body[i].flag);
    }
    // 重建初始页面
    snake.direction = 'right';

    snake.body = [
        { x: 2, y: 0 }, //蛇头
        { x: 1, y: 0 }, //蛇身
        { x: 0, y: 0 } //蛇尾
    ];
    snake.display();

    map.canvas.removeChild(food.flag);
    food = new Food(map);

}

// 给body加键盘事件,上下左右
window.onkeydown = function (e) {
    var event = e || window.event; //兼容

    // console.log(event.keyCode);
    /*  键盘按键值:
         38(up)
         40(down)
         39(right)
         37(left)*/
    switch (event.keyCode) {
        case 38:
            if (snake.direction != 'down') { //防止蛇直接反方向掉头
                snake.direction = 'up';
            }
            break;
        case 40:
            if (snake.direction != 'up') {
                snake.direction = 'down';
            }

            break;
        case 37:
            if (snake.direction != 'right') {
                snake.direction = 'left';
            }
            break;
        case 39:
            if (snake.direction != 'left') {
                snake.direction = 'right';
            }
            break;
    }
}



//创建地图对象
var map = new Map(20, 40, 20);
map.create();
var food = new Food(map); //构造食物对象
var snake = new Snake(map); //构造蛇对象
snake.display();




var timer; //变量可以提升

function start() {
    // 在使用之前清除定时器,保证不重复启动定时器
    clearInterval(timer);
    timer = setInterval(function () {
        snake.run();
    }, l.speed);
}
// 按下开始按钮,游戏就动起来,就是计时器启动
document.getElementById('begin').onclick = function () {
    start();
}
// 按下暂停按钮,游戏就停止起来,就是计时器停止
document.getElementById('pause').onclick = function () {
    // 在使用之前清除定时器,保证不重复启动定时器
    clearInterval(timer);
    // timer = setInterval(function () {

    // }, 300);
}

})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值