实验二、贪吃蛇

         (文末提供原码)

        贪吃蛇游戏主要由蛇、食物这两部分组成。再加上游戏的控制部分。因此采用面向对象的方法可以很好的解决问题。

目录

主页部分:

通过链接引入蛇类、食物类、游戏类:

css样式:

页面基本功能:

游戏类:

蛇类:

食物类

最终成果:

 死亡界面:

 实验总结:


主页部分:

        完成一些基本背景的布局和游戏初始化的设定。

通过链接引入蛇类、食物类、游戏类:

    <script src="./Food.js"></script>
    <script src="./Snake.js"></script>
    <script src="./Game.js"></script>

css样式:

  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .map {
      width: 1350px;
      height: 600px;
      /* background-color: #ccc; */
      position: relative;
      left: 0px;
      top: 0px;
    }
    .btn{
      position: absolute;
      top: 270px;
      left: 620px;
      width: 80px;
      height: 60px;
    }
  </style>

页面基本功能:

    <script>
      // 1.获取地图
      var map = document.getElementById('map')
      // 2.创建一个Game控制对象
      var game1 = new Game(map);
      game1.start();

      // 点击button,重新开始
      function reload(){
        window.location.reload();
      }
    </script>

游戏类:

        游戏类负责控制渲染页面、蛇和食物、控制蛇的移动等功能 

1.声明一个Game构造函数,生成这个对象

    function Game (map) {
        this.food1 = new Food()
        this.snake1 = new Snake()
        this.map = map
        that = this
    }

2.准备开始的方法

    Game.prototype.start = function () {
        // 2.1渲染食物和蛇
        this.food1.render(this.map)
        this.snake1.render(this.map)
        // 2.2让蛇自动动起来,并且渲染
        snakeAutoMove()
        bindKey()
    }

3.定时器让蛇动起来

    function snakeAutoMove () {
        var timeId = setInterval(function () {
            this.snake1.move(this.food1, this.map)
            // 判断蛇移动是否出界,如果蛇头坐标小于0,或者大于宽/高,就出界了
            var snakeHeadX = this.snake1.body[0].x * this.snake1.width;
            var snakeHeadY = this.snake1.body[0].y * this.snake1.height;
            if (snakeHeadX < 0 || snakeHeadY < 0 || snakeHeadX >= this.map.offsetHeight || snakeHeadY >= this.map.offsetWidth) {
                // 出界就结束游戏
                alert('Game Over')
                clearInterval(timeId)
                return;
            }

            // 吃到自己身体也死
            if (this.snake1.body.length > 0) {
                for (var i = 1; i < this.snake1.body.length; i++) {
                    if (this.snake1.body[0].x == this.snake1.body[i].x && this.snake1.body[0].y == this.snake1.body[i].y){
                        alert('咬蛇自尽')
                        clearInterval(timeId)
                    }
                }
            }

            this.snake1.render(this.map);
        }.bind(that), 100);
    }

4.让蛇根据那键盘按键来移动

    function bindKey () {
        document.onkeydown = function (e) {
            e = e || window.event;
            switch (e.keyCode) {
                case 37:
                    if (this.snake1.direction != 'right') {
                        this.snake1.direction = 'left';
                    }
                    break;
                case 38:
                    if (this.snake1.direction != 'bottom') {
                        this.snake1.direction = 'top';
                    }
                    break;
                case 39:
                    if (this.snake1.direction != 'left') {
                        this.snake1.direction = 'right';
                    }
                    break;
                case 40:
                    if (this.snake1.direction != 'top') {
                        this.snake1.direction = 'bottom';
                    }
                    break;
            }
        }.bind(that);
    }

蛇类:

1.创建一条蛇

    // 声明一个list保存蛇
    var list = [];
    // 1.声明一个构造函数,创建蛇对象
    function Snake (width, height, direction) {
        this.width = width || 30;
        this.height = height || 30;
        // 蛇开始默认向右走
        this.direction = direction || 'right';
        // 初始化创建出来的蛇,用数组来表示蛇身体,吃到了就添加一个
        this.body = [
            // 蛇的每一节身体都有不同的x,y
            { x: 1, y: 2, bgColor: '#3EBFA0'},
            { x: 1, y: 1, bgColor: '#8DE2C9'}
        ];
    }

2.把创建出来的蛇对象渲染到地图上

    Snake.prototype.render = function (map) {
        // 渲染新蛇之前删除老蛇
        remove(map)
        // 把蛇的每一节遍历出来
        for (var i = 0; i < this.body.length; i++) {
            // 创建div
            var div1 = document.createElement('div');
            // 把当前蛇这一节身体所有的显示信息赋值给这个div
            div1.style.width = this.width + 'px';
            div1.style.height = this.height + 'px';
            div1.style.backgroundColor = this.body[i].bgColor;
            div1.style.position = 'absolute';
            div1.style.borderRadius = 20 + 'px';
            div1.style.top = this.body[i].x * this.width + 'px';
            div1.style.left = this.body[i].y * this.height + 'px';
            // 把div添加到map中
            map.appendChild(div1);
            list.push(div1)
        }
    }

3.蛇的移动

Snake.prototype.move = function (food, map) {
        // 3.1蛇身的移动,从蛇尾开始改变,比较简单
        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;
        }
        // 3.2根据方向改变蛇头
        switch (this.direction) {
            case 'right':
                this.body[0].y++;
                break;
            case 'left':
                this.body[0].y--;
                break;
            case 'top':
                this.body[0].x--;
                break;
            case 'bottom':
                this.body[0].x++;
                break;
        }

        // 判断蛇有没有吃到食物,蛇头是否与食物重叠
        var snakeHeadX = this.body[0].x * this.width
        var snakeHeadY = this.body[0].y * this.width
        var foodX = food.x
        var foodY = food.y
        // 去除蛇尾的坐标备用
        var lastSnakeUnit = this.body[this.body.length - 1];
        // 判断
        if (snakeHeadX == foodX & snakeHeadY == foodY) {
            // 吃到了食物,长身体
            this.body.push({
                x: lastSnakeUnit.x,
                y: lastSnakeUnit.y,
                bgColor: '#7CDEC1'
            })
            // 产生新食物,即重新渲染
            food.render(map)
        }
    }

4.声明一个方法,删除老蛇

   function remove (map) {
        for (var i = 0; i < list.length; i++) {
            map.removeChild(list[i]);
        }
        // 删除list里真正的蛇
        list = []
    }

食物类

1.创建一个食物

    // 声明一个list存放食物
    var list = []
    // 1.创建食物对象的构造函数
    function Food (width, height, bgColor, x, y) {
        this.width = width || 30
        this.height = height || 30
        this.bgColor = bgColor || '#0061BC'
        this.x = x || 0
        this.y = y || 0
    }

2.根据Food构造函数创建出来的食物对象,渲染到地图上

   Food.prototype.render = function (map) {
        removeFood(map);
        // 2.1给食物对象随机生成xy坐标
        // 生成0-1的随机数,乘上地图宽/小方块宽,向下取整。就是对于整个地图来说的随机数,再乘上div宽,就可以随机生成在地图内的x
        this.x = Math.floor((Math.random() * map.offsetHeight) / this.width) * this.width
        this.y = Math.floor((Math.random() * map.offsetWidth) / this.height) * this.height
        // 2.2创建一个div,让这个div拥有这个食物对象的所有显示信息
        var div1 = document.createElement('div')
        div1.style.width = this.width + 'px'
        div1.style.height = this.height + 'px'
        div1.style.backgroundColor = this.bgColor
        div1.style.position = 'absolute'
        div1.style.borderRadius = 20 + 'px'
        div1.style.top = this.x + 'px'
        div1.style.left = this.y + 'px'
        // 2.3把这个div追加到地图中去
        map.appendChild(div1)

        // 把div保存起来
        list.push(div1)
    }

3.删除老食物div的方法

    function removeFood(map){
        for(var i = 0; i<list.length; i++){
            map.removeChild(list[i]);
        }
        list = []
    }

最终成果:

 死亡界面:

        1.撞墙而死

        2.咬到自己身体而死

 实验总结:

        通过本次开发,熟悉了面向对象多类的开发、以及对于定时器的控制。由于缺乏开发经验,并且时间紧张。因此开发的不够完善,只能实现基本的游戏功能。对于样式以及玩法的多样性没有丰富起来

实验原码:

        index.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>Document</title>
    <script src="./Food.js"></script>
    <script src="./Snake.js"></script>
    <script src="./Game.js"></script>
  </head>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .map {
      width: 1920px;
      height: 930px;
      /* background-color: #ccc; */
      position: relative;
      left: 0px;
      top: 0px;
    }
    .btn{
      position: absolute;
      top: 400px;
      left: 850px;
      width: 80px;
      height: 60px;
    }
  </style>
  <body>
    <div class="map" id="map"></div>
    <button class="btn" onclick="reload()">重新开始</button>
    <script>
      // 1.获取地图
      var map = document.getElementById('map')
      // 2.创建一个Game控制对象
      var game1 = new Game(map);
      game1.start();
      // 点击button,重新开始
      function reload(){
        window.location.reload();
      }
    </script>
  </body>
</html>

        Game.js:

// Ganme控制蛇和食物的生成,引入地图等等

(function (window) {
    var that = null;
    // 1.声明一个Game构造函数,生成这个对象
    function Game (map) {
        this.food1 = new Food()
        this.snake1 = new Snake()
        this.map = map
        that = this
    }
    // 2.准备开始的方法
    Game.prototype.start = function () {
        // 2.1渲染食物和蛇
        this.food1.render(this.map)
        this.snake1.render(this.map)
        // 2.2让蛇自动动起来,并且渲染
        snakeAutoMove()
        bindKey()
    }

    // 3.定时器让蛇动起来,定时器的this是window,因此需要用that引用一下
    function snakeAutoMove () {
        var timeId = setInterval(function () {
            this.snake1.move(this.food1, this.map)
            // 判断蛇移动是否出界,如果蛇头坐标小于0,或者大于宽/高,就出界了
            var snakeHeadX = this.snake1.body[0].x * this.snake1.width;
            var snakeHeadY = this.snake1.body[0].y * this.snake1.height;
            if (snakeHeadX < 0 || snakeHeadY < 0 || snakeHeadX >= this.map.offsetHeight || snakeHeadY >= this.map.offsetWidth) {
                // 出界就结束游戏
                alert('Game Over')
                clearInterval(timeId)
                return;
            }

            // 吃到自己身体也死
            if (this.snake1.body.length > 0) {
                for (var i = 1; i < this.snake1.body.length; i++) {
                    if (this.snake1.body[0].x == this.snake1.body[i].x && this.snake1.body[0].y == this.snake1.body[i].y){
                        alert('咬蛇自尽')
                        clearInterval(timeId)
                    }
                }
            }

            this.snake1.render(this.map);
        }.bind(that), 100);
    }

    // 4.让蛇根据那键盘按键来移动
    function bindKey () {
        document.onkeydown = function (e) {
            e = e || window.event;
            switch (e.keyCode) {
                case 37:
                    if (this.snake1.direction != 'right') {
                        this.snake1.direction = 'left';
                    }
                    break;
                case 38:
                    if (this.snake1.direction != 'bottom') {
                        this.snake1.direction = 'top';
                    }
                    break;
                case 39:
                    if (this.snake1.direction != 'left') {
                        this.snake1.direction = 'right';
                    }
                    break;
                case 40:
                    if (this.snake1.direction != 'top') {
                        this.snake1.direction = 'bottom';
                    }
                    break;
            }
        }.bind(that);
    }
    // 暴露这个方法
    window.Game = Game
}(window))

        Food.js:


// Food类
(function (window) {
    // 声明一个list存放食物
    var list = []
    // 1.创建食物对象的构造函数
    function Food (width, height, bgColor, x, y) {
        this.width = width || 30
        this.height = height || 30
        this.bgColor = bgColor || '#0061BC'
        this.x = x || 0
        this.y = y || 0
    }

    // 2.根据Food构造函数创建出来的食物对象,渲染到地图上
    // 渲染方法写原型链中
    Food.prototype.render = function (map) {
        removeFood(map);
        // 2.1给食物对象随机生成xy坐标
        // 生成0-1的随机数,乘上地图宽/小方块宽,向下取整。就是对于整个地图来说的随机数,再乘上div宽,就可以随机生成在地图内的x
        this.x = Math.floor((Math.random() * map.offsetHeight) / this.width) * this.width
        this.y = Math.floor((Math.random() * map.offsetWidth) / this.height) * this.height
        // 2.2创建一个div,让这个div拥有这个食物对象的所有显示信息
        var div1 = document.createElement('div')
        div1.style.width = this.width + 'px'
        div1.style.height = this.height + 'px'
        div1.style.backgroundColor = this.bgColor
        div1.style.position = 'absolute'
        div1.style.borderRadius = 20 + 'px'
        div1.style.top = this.x + 'px'
        div1.style.left = this.y + 'px'
        // 2.3把这个div追加到地图中去
        map.appendChild(div1)

        // 把div保存起来
        list.push(div1)
    }

    // 删除老食物div的方法
    function removeFood(map){
        for(var i = 0; i<list.length; i++){
            map.removeChild(list[i]);
        }
        list = []
    }

    // 把Food构造函数暴露出去
    window.Food = Food;
}(window));

        Snake.js:


// 蛇类
(function (window) {
    // 声明一个list保存蛇
    var list = [];
    // 1.声明一个构造函数,创建蛇对象
    function Snake (width, height, direction) {
        this.width = width || 30;
        this.height = height || 30;
        // 蛇开始默认向右走
        this.direction = direction || 'right';
        // 初始化创建出来的蛇,用数组来表示蛇身体,吃到了就添加一个
        this.body = [
            // 蛇的每一节身体都有不同的x,y
            { x: 1, y: 2, bgColor: '#3EBFA0'},
            { x: 1, y: 1, bgColor: '#8DE2C9'}
        ];
    }

    // 2.把创建出来的蛇对象渲染到地图上
    Snake.prototype.render = function (map) {
        // 渲染新蛇之前删除老蛇
        remove(map)
        // 把蛇的每一节遍历出来
        for (var i = 0; i < this.body.length; i++) {
            // 创建div
            var div1 = document.createElement('div');
            // 把当前蛇这一节身体所有的显示信息赋值给这个div
            div1.style.width = this.width + 'px';
            div1.style.height = this.height + 'px';
            div1.style.backgroundColor = this.body[i].bgColor;
            div1.style.position = 'absolute';
            div1.style.borderRadius = 20 + 'px';
            div1.style.top = this.body[i].x * this.width + 'px';
            div1.style.left = this.body[i].y * this.height + 'px';
            // 把div添加到map中
            map.appendChild(div1);
            list.push(div1)
        }
    }

    // 3.蛇的移动
    Snake.prototype.move = function (food, map) {
        // 3.1蛇身的移动,从蛇尾开始改变,比较简单
        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;
        }
        // 3.2根据方向改变蛇头
        switch (this.direction) {
            case 'right':
                this.body[0].y++;
                break;
            case 'left':
                this.body[0].y--;
                break;
            case 'top':
                this.body[0].x--;
                break;
            case 'bottom':
                this.body[0].x++;
                break;
        }

        // 判断蛇有没有吃到食物,蛇头是否与食物重叠
        var snakeHeadX = this.body[0].x * this.width
        var snakeHeadY = this.body[0].y * this.width
        var foodX = food.x
        var foodY = food.y
        // 去除蛇尾的坐标备用
        var lastSnakeUnit = this.body[this.body.length - 1];
        // 判断
        if (snakeHeadX == foodX & snakeHeadY == foodY) {
            // 吃到了食物,长身体
            this.body.push({
                x: lastSnakeUnit.x,
                y: lastSnakeUnit.y,
                bgColor: '#7CDEC1'
            })
            // 产生新食物,即重新渲染
            food.render(map)
        }
    }

    // 4.声明一个方法,删除老蛇
    function remove (map) {
        for (var i = 0; i < list.length; i++) {
            map.removeChild(list[i]);
        }
        // 删除list里真正的蛇
        list = []
    }

    // 暴露蛇函数
    window.Snake = Snake;
}(window));

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值