贪吃蛇案例

贪吃蛇案例(面对对象)

案例目标

游戏的目的是用来体会js高级语法的使用,不需要具备抽象对象的能力,使用面向对象的方式分析问题,需要一个漫长的过程。

游戏实现后的图片

在这里插入图片描述

功能实现
搭建页面

放一个容器盛放游戏场景div#map

 <div id="map">

    </div>

设置样式

#map {
  width: 800px;
  height: 600px;
  background-color: lightgray;
  position: relative;
}
* {
  margin: 0;
  padding: 0;
}

分析对象
  • 食物对象
  • 蛇对象
  • 游戏对象
Tools工具

创建随机数的工具,使用自调用函数,开启一个新的作用域,避免命名冲突,通过自调用函数,进行封装,通过window属性暴露Tools对象

(function (window, undefined) {
  var Tools = {
    getRandom: function (min, max) {
      // min = Math.ceil(min);
      // max = Math.floor(max);
      return Math.floor(Math.random() * (max - min + 1)) + min; //[0,1)  10-1+1+1  random <10
      // window.Tools = Tools;
    },
  };
  window.Tools = Tools;
})(window, undefined)



创建食物对象
  • food
    • 属性
      • x
      • y
      • width
      • height
      • color
    • 方法
      • render 随机创建一个食物对象,并渲染到map上
  • 创建Food的构造函数,并设置属性

用一个options对象作参数

 // 局部作用域
  var position = "absolute";
  // 记录上次创建的食物,为删除做准备
  var elements = [];
  function Food(options) {
    options = options || {};
    this.x = options.x || 0;
    this.y = options.y || 0;
    this.width = options.width || 20;
    this.height = options.height || 20;
    this.color = options.color || "green";
  }
  • 通过原型设置render方法,实现随机产生食物对象,并渲染到map上
// 渲染
  Food.prototype.render = function (map) {
    // 删除之前创建的食物
    remove();
    // 随机设置x和y
    this.x = Tools.getRandom(0, map.offsetWidth / this.width - 1) * this.width;
    this.y = Tools.getRandom(0, map.offsetHeight / this.height - 1) * this.height;
    // 动态创建div页面上显示的食物
    var div = document.createElement("div");
    map.appendChild(div);
    elements.push(div);
    // 设置div的样式
    div.style.position = position;
    div.style.left = this.x + "px";
    div.style.top = this.y + "px";
    div.style.width = this.width + "px";
    div.style.height = this.height + "px";
    div.style.backgroundColor = this.color;
  };
  • 删除食物方法
// 删除食物
  function remove() {
    // 倒着遍历,从最后一个开始删除
    for (var i = elements.length - 1; i >= 0; i--) {
      // 删除div
      elements[i].parentNode.removeChild(elements[i]);
      // 删除数组中的元素
      // 删除数组元素
      // 第一个参数,从哪个元素开始删除
      // 第二个参数,删除几个元素
      elements.splice(i, 1);
    }
  }

食物对象已经创建完成,可以测试一下是否有效果

var map = document.getElementById('map');
         var food = new Food();
         food.render(map);
创建蛇对象
  • Snake
  • 属性
    • width 蛇节的宽度默认20
    • height 蛇节的高度默认20
    • body 数组,蛇的头部和身体,第一个位置是蛇头
    • direction 蛇运动的方向,默认right 可以是left 、top、bottom
  • 方法
    • render 把蛇渲染到map上
  • Snake构造函数
   var position = 'absolute';
    // 记录之前创建的蛇
    var elements = [];
    function Snake(options) {
        options = options || {};
        // 蛇节大小
        this.width = options.width || 20;
        this.height = options.height || 20;
        // 蛇的方向
        this.direction = options.direction || 'right';
        // 蛇的身体
        this.body = [
            { x: 3, y: 2, color: 'red' },
            { x: 2, y: 2, color: 'blue' },
            { x: 1, y: 2, color: 'blue' }
        ];
    }
  • render 方法
 Snake.prototype.render = function (map) {
        // 删除之前创建的蛇
        remove();
        // 把每一个蛇节渲染到地图上
        for (var i = 0, len = this.body.length; i < len; i++) {
            // 蛇节
            var object = this.body[i];
            var div = document.createElement('div');
            map.appendChild(div);
            elements.push(div);
            // 设置div的样式
            div.style.position = position;
            div.style.left = object.x * this.width + "px";
            div.style.top = object.y * this.height + "px";
            div.style.width = this.width + "px";
            div.style.height = this.height + "px";
            div.style.backgroundColor = object.color;
        }
    }

  • 删除蛇的方法
 // 删除蛇的方法
    function remove() {
        for (var i = elements.length - 1; i >= 0; i--) {
            // 删除div
            elements[i].parentNode.removeChild(elements[i]);
            // 删除数组中的元素
            // 删除数组元素
            // 第一个参数,从哪个元素开始删除
            // 第二个参数,删除几个元素
            elements.splice(i, 1);

        }


    }
  • 控制蛇移动的方法
 Snake.prototype.move = function (food, map) {
        // 控制蛇的身体移动(当前蛇节到上一个蛇节的位置)
        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;
        }
        // 控制蛇的头部移动
        // 判断蛇移动的方向
        var head = this.body[0];
        switch (this.direction) {
            case 'right':
                head.x += 1;
                break;
            case 'bottom':
                head.y += 1;
                break;
            case 'top':
                head.y -= 1;
                break;
            case 'left':
                head.x -= 1;
                break;
        }
        // 2.4 当蛇遇到食物做相应的处理
        var headX = head.x * this.width;
        var headY = head.y * this.height;
        if (headX === food.x && headY === food.y) {
            // 1.让蛇增加一节
            // 获取蛇的最后一节
            var last = this.body[this.body.length - 1];
            this.body.push({
                x: last.x,
                y: last.y,
                color: last.color
            })
            // 2.随机在地图上重新生成食物
            food.render(map);
            var score = this.body.length - 3;
            // console.log(this.body.length);
            // console.log(score);

            window.score = score;
            // console.log(window);
            // console.log(window.score);
        }
        // console.log(score);
    }

测试代码是否正确

         var snake = new Snake();
         snake.render(map);
         snake.move(food, map);
创建游戏对象

游戏对象用来管理游戏中所有的对象和开始游戏

  • Game
    • 属性
      • food
      • snake
      • map
    • 方法
      • start 开始游戏(绘制所有游戏对象)
  • 构造函数
 function Game(map) {
        this.food = new Food();
        this.snake = new Snake();
        this.map = map;
        that = this;
    }
  • 开始游戏,渲染食物对象和蛇对象
 Game.prototype.start = function () {
        // 1.把蛇和食物对象,渲染到地图上
        this.food.render(this.map);

        // this.snake.move(that.food, that.map);
        this.snake.render(this.map);
        // 2.开始游戏的逻辑
        // 2.1让蛇移动起来
        runSnake();

        // 2.3通过键盘控制蛇移动的方向
        bindKey();
    }
  • 控制蛇动起来
  function runSnake() {
        var timerId = setInterval(function () {
            // 让蛇走一格
            // 在定时器的function中this指向window对象的
            this.snake.move(this.food, this.map);
            this.snake.render(this.map);
            // 2.2 当蛇遇到边界的时候游戏结束
            // 获取蛇头的坐标
            var maxX = this.map.offsetWidth / this.snake.width;
            var maxY = this.map.offsetHeight / this.snake.height;
            var headX = this.snake.body[0].x;
            var headY = this.snake.body[0].y;
            if (headX < 0 || headX >= maxX) {
                clearInterval(timerId);
                alert('游戏结束!分数是:' + window.score);
            }
            if (headY < 0 || headY >= maxY) {
                clearInterval(timerId);
                alert('游戏结束!分数是:' + window.score);
            }
        }.bind(that), 150)
    }
  • 通过键盘控制蛇移动的方向
    // 通过键盘控制蛇移动的方向
    function bindKey() {
        // document.onkeydown = function () {

        // };
        document.addEventListener('keydown', function (e) {
            // console.log(e.keyCode);
            // 37 == left 38 == top  39 == right  40 == bottom
            switch (e.keyCode) {
                case 37:
                    this.snake.direction = 'left';
                    break;
                case 65:
                    this.snake.direction = 'left';
                    break;
                case 38:
                    this.snake.direction = 'top';
                    break;
                case 87:
                    this.snake.direction = 'top';
                    break;
                case 39:
                    this.snake.direction = 'right';
                    break;
                case 68:
                    this.snake.direction = 'right';
                    break;
                case 40:
                    this.snake.direction = 'bottom';
                    break;
                case 83:
                    this.snake.direction = 'bottom';
                    break;
            }
            // bind 方法ES5中新增的方法
            // 新建一个方法,bind中第一个参数可以改变函数中this的指向
            // bind并没有调用方法
        }.bind(that), false);
    }

最后,测试代码

var map = document.getElementById('map');
 var game = new Game(map);
        game.start();

总结,面对对象编程,先将对象的属性和方法写出来,再渲染到地图上,可以自己再这个基础上多做些补充。
比如可以将食物的颜色发生变化,可以用Tools工具取rgb的随机数在这里插入图片描述
或者提高游戏难度等等。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值