贪吃蛇案例

贪吃蛇案例

案例目标

游戏的目的是用来体会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的随机数在这里插入图片描述
或者提高游戏难度等等。。。。

这篇文章有 67 个评论

  1. is cbd illegal in canada

    Does your website have a contact page? I’m having trouble locating it but, I’d like to send you an e-mail. I’ve got some recommendations for your blog you might be interested in hearing. Either way, great website and I look forward to seeing it grow over time.

  2. lig tv izle webspor

    I do not know what I would have tried without these techniques shared by you regarding this subject matter.

  3. Israel

    I got this web site from my buddy who told me concerning this web page
    and at the moment this time I am visiting this site and reading very informative posts at this place.

  4. Maria Photo

    I genuinely enjoy studying on this website , it has got superb posts . “A man of genius has been seldom ruined but by himself.” by Samuel Johnson.

  5. Bud Me

    Hi there! This article couldnít be written much better! Looking through this post reminds me of my previous roommate! He continually kept talking about this. I am going to send this post to him. Pretty sure he’s going to have a very good read. Many thanks for sharing!

  6. auto approve list

    Thank you for sharing your info. I really appreciate your efforts and I will be waiting for your
    next write ups thank you once again.

  7. instagram takipçi satın al

    Hi! This is kind of off topic but I need some guidance from
    an established blog. Is it difficult to set up your own blog?
    I’m not very techincal but I can figure things out pretty fast.
    I’m thinking about making my own but I’m not sure where to begin. Do you have any ideas or suggestions?
    With thanks

  8. Rodger- Ultrasonic Repeller

    Everything is very open with a very clear description of the challenges. It was really informative. Your site is extremely helpful. Thank you for sharing.

  9. Andree Laminator

    Hiya very cool web site!! Guy .. Excellent .. Wonderful .. I’ll bookmark your site and take the feeds also…I’m happy to find so many useful info right here within the put up, we need work out more strategies in this regard, thank you for sharing.

  10. cbd oil for dogs with seizures

    Undeniably believe that that you said. Your favorite justification appeared to be at the net the easiest factor
    to be mindful of. I say to you, I definitely get irked whilst people think about concerns that they just don’t know
    about. You managed to hit the nail upon the
    top and also outlined out the whole thing with no need side effect , other people could take a signal.

    Will probably be again to get more. Thanks

  11. auto approve list

    Remarkable things here. I’m very happy to peer your article.
    Thank you so much and I’m having a look forward to contact
    you. Will you kindly drop me a e-mail?

  12. Franklin Slip

    Thanks in support of sharing such a good idea, paragraph is fastidious, thats why i have read it entirely|

  13. umanfootball.com.ua

    Nice blog! Is your theme custom made or did you download it
    from somewhere? A theme like yours with a few simple adjustements would really make my
    blog jump out. Please let me know where you got your design. Thanks
    a lot

  14. cbd near me now

    I will right away seize your rss feed as I can’t find your e-mail subscription link or e-newsletter service. Do you have any? Please permit me realize in order that I may subscribe. Thanks.

发表评论