贪吃蛇案例

贪吃蛇案例

案例目标

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

这篇文章有 20 个评论

  1. movies

    A person essentially assist to make critically articles I might state. This is the first time I frequented your website page and to this point? I surprised with the analysis you made to make this actual post incredible. Wonderful activity! Teddie Marlon Cynth

  2. dizi izle

    Hi there! I just want to offer you a huge thumbs up for your excellent information you have got right here on this post. I am returning to your site for more soon. Happy Godwin Bobbee

  3. dizi

    Pretty! This has been a really wonderful article. Thanks for supplying these details. Nike Aron Belicia Corrianne Jose Torrlow

  4. indir

    Wow, fantastic blog layout! How long have you been blogging for? you made blogging look easy. The overall look of your website is magnificent, as well as the content! Phyllys Lee Garratt

  5. episodes

    Neistat makes the best vids I hope he uploads soon Beverly Bartlett Milurd

  6. episodes

    Stunning quest there. What happened after? Take care! Chrysa Shawn Thacker

  7. hindi movie

    Helpful information. Lucky me I discovered your website by accident, and I am surprised why this twist of fate did not happened earlier! I bookmarked it. Licha Osbourn Adel

  8. 123movies

    This is one awesome blog post. Thanks Again. Much obliged. Stevena Dewain Octavla

  9. episodes

    You completed a few fine points there. I did a search on the subject matter and found nearly all persons will go along with with your blog. Phelia Frederico Hulbert

  10. episodes

    Its like you read my mind! You appear to know a lot about this, like you wrote the book in it or something. I think that you could do with some pics to drive the message home a little bit, but other than that, this is fantastic blog. A fantastic read. I will certainly be back. Marji Tyrone Alberic

  11. episodes

    I have recently started a blog, the info you offer on this website has helped me tremendously. Thanks for all of your time & work. Coletta Sayre Harvison

  12. online

    Hello there. I discovered your web site by the use of Google while searching for a related topic, your site came up. It seems great. I have bookmarked it in my google bookmarks to visit then. Benetta Harald Paviour

  13. watch

    Hey there. I discovered your web site by way of Google at the same time as searching for a similar subject, your site got here up. It looks great. I have bookmarked it in my google bookmarks to come back then. Alvira Pattie Mayne

  14. dizi

    After exploring a few of the blog posts on your web site, I really appreciate your way of blogging. I book marked it to my bookmark webpage list and will be checking back in the near future. Please visit my web site too and tell me how you feel. Merrie Bob Trisa

  15. diziler

    You have remarked very interesting details! ps decent web site. Malanie Hervey Kuster

  16. aksiyon

    I was very happy to find this page. I want to to thank you for your time due to this fantastic read!! I definitely appreciated every bit of it and I have you saved as a favorite to look at new stuff on your site. Gabbi Royce Thain

  17. I am actually glad to glance at this webpage posts which carries plenty
    of helpful information, thanks for providing these kinds
    of information.

  18. erotik

    I got this web site from my friend who told me regarding this site and now this time I am browsing this site and reading very informative articles or reviews here. Shina Anatol Magbie

  19. cannabidiol gummies

    Spot on with this write-up, I absolutely believe this web site needs
    a lot more attention. I’ll probably be returning to read more, thanks for the advice!

  20. stornobrzinol

    Great wordpress blog here.. It’s hard to find quality writing like yours these days. I really appreciate people like you! take care

发表评论