JavaScript(二十)经典贪吃蛇demo

JS实现贪吃蛇小游戏,效果图如下:

 

思路分析:

一、创建地图

1.封装一个地图类

function map() {
         this._map = null;    //封装接受地图对象的属性
         this._span=null;
       //创建地图的方法
         this.createMap = function () {
          if (this._map == null) {
          this._map = document.createElement("div");
           this._map.className = "map";
      }
  }
}

2.通过实例化调用类的属性和方法创建地图;

//实例化地图 
  Map = new map();
  Map.createMap();
  Map.createSpan();

二、创建蛇及其移动的方法

1.经典款贪吃蛇由若干个小方块组成身体,蛇头与蛇身的颜色不一致,但大小相同,即蛇是由很多属性一致的方块组成,要存储一系列类型一致的数据第一时间考虑数组,并且数组有push()追加方法,也解决了后面吃食物后身体增长的问题;默认蛇开始为3个小方块长度;(30x30的小方块)

说明:数组中存储left,top,颜色,null四个值

function snake() {
            this._map = null;
            this._span=null;
            this.direct = "right";            //蛇的默认元素  x,y,颜色
            this._snake = [[3, 1, "red", null], [2, 1, "yellow", null], [1, 1, "yellow", null]];
            this.createSnake = function () {
                for (var i = 0; i < this._snake.length; i++) {
                    if (this._snake[i][3] == null) {
                        this._snake[i][3] = document.createElement('div');
                        this._snake[i][3].style.backgroundColor = this._snake[i][2];
                        this._snake[i][3].className = "snake";
                    }
                    this._snake[i][3].style.left = this._snake[i][0] * 30 + "px";
                    this._snake[i][3].style.top = this._snake[i][1] * 30 + "px";
                    this._map.appendChild(this._snake[i][3]);
                }
            }

2.封装蛇移动方法

(1)贪吃蛇运动其实是属性(left,top)的传递,即蛇头移动后,其后那节身体移动到蛇头移动前的位置,再后面的身体依次移动到前一节移动前的位置;

需增加一个蛇头默认方向属性   this.direct = "right"; 控制蛇头在不同方向上的运动,带动蛇身体的移动;

在改变每节属性改变之后需再次调用蛇的创建方法,相当于每次移动后在新的位置创建蛇利用计时器;

this.snakeMove = function () {
                //蛇的属性传递 x,y
                var len = this._snake.length - 1;
                for (var i = len; i > 0; i--) {
                    this._snake[i][0] = this._snake[i - 1][0];
                    this._snake[i][1] = this._snake[i - 1][1];
                }
 //设置蛇头在不同方向的移动 带动蛇的移动 需增加一个默认方向属性
                switch (this.direct) {
                    case "right":
                        this._snake[0][0] += 1;
                        break;
                    case "left":
                        this._snake[0][0] -= 1;
                        break;
                    case "up":
                        this._snake[0][1] -= 1;
                        break;
                    case "down":
                        this._snake[0][1] += 1;
                        break;
                }

(2)通过按键wsad控制蛇的上下左右移动

e.keyCode 获取按键码的方法 利用获取到的按键码控制上下左右移动;

注意:当蛇朝着一个方向正在运动的时候,按相反键时不能使蛇反向移动,需要处理这个bug;(在执行按键操作之前对现在的方向进行判断)

 document.onkeypress = function (e) {
                switch (e.key) {
                    case "w":
                        if (Snake.direct == "down")
                            return;
                        Snake.direct = "up";
                        break;
                    case "a":
                        if (Snake.direct == "right")
                            return;
                        Snake.direct = "left";
                        break;
                    case "d":
                        if (Snake.direct == "left")
                            return;
                        Snake.direct = "right";
                        break;
                    case "s":
                        if (Snake.direct == "up")
                            return;
                        Snake.direct = "down";
                        break;
                }
            }

 

(3)封装蛇的穿墙方法 即当蛇运到到边界令其从相反方向的边间穿出; 

利用蛇头坐标值(left和top)与边界做比较,相等时设置蛇头的坐标为相反方向的边界值

注意:判断上下左右方向值,只需要改变相应坐标即可;

            需要在蛇移动的方法中调用蛇穿墙方法

           判断时可以使用方块个数值(垂直方向最多有30 个,水平方向20个),但是判断条件需要减1,使蛇出现在地图内侧

  //封装蛇穿墙的方法
            this.snakeBack = function () {
                if (this._snake[0][0] > 29) {
                    this._snake[0][0] = 0;
                }
                if (this._snake[0][0] < 0) {
                    this._snake[0][0] = 29;
                }
                if (this._snake[0][1] >19) {
                    this._snake[0][1] = 0;
                }
                if (this._snake[0][1] < 0) {
                    this._snake[0][1] = 19;
                }
            };

3.创建食物的方法

(1).封装食物的类 随机位置创建食物

利用Math.random()的方法,随机产生食物,需要注意的是必须向下取整,保证食物出现在30*20的地图内,食物的大小与蛇大小相同30*30

 function food() {
            this._food = null;
            this._map = null;
            this.x = 0;
            this.y = 0;
            this.createFood = function () {
                this.x = Math.floor(Math.random() * 30);
                this.y = Math.floor(Math.random() * 20);
                if (this._food == null) {
                    this._food = document.createElement("div");
                    this._food.className = "food";
                }
                this._food.style.left = this.x * 30 + "px";
                this._food.style.top = this.y * 30 + "px";
                this._map.appendChild(this._food);
            }
        }

 (2)实例化食物,将蛇挂载在地图上


//函数调用    创建食物
CreateFood(Map._map);
function CreateFood(map) {
            Food = new food();
            Food._map = map;
            Food.createFood();
        }

(4)蛇吃食物

判断蛇的left top与豆豆的left top是否一致,一致时,重新创建随机食物,同时蛇身体数组追加一节; 

      if (this._snake[0][0] == Food.x && this._snake[0][1] == Food.y) {
                  //蛇数组追加
                    this._snake.push([
                        this._snake[this._snake.length - 1][0],
                        this._snake[this._snake.length - 1][1],
                        "yellow",
                        null
                    ]);
                    //重新随机创建食物
                    Food.createFood();
                }

 4.蛇头与蛇身相撞,游戏结束,清除计时器, 在蛇移动时调用

 //封装蛇撞死的方法
            this.snakeBackDie = function () {
                for (var i = 1; i < this._snake.length; i++) {
                    if (this._snake[0][0] == this._snake[i][0] && this._snake[0][1] == this._snake[i][1]) {
                        alert("游戏结束");
                        clearInterval(time);
                    }
                }
            }

完整代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .map {
            width: 900px;
            height: 600px;
            background-color: black;
            position: relative;
            margin: 0 auto;
        }

        .snake {
            width: 30px;
            height: 30px;
            position: absolute;
            border: 1px solid deeppink;
            box-sizing: border-box;
        }

        .food {
            position: absolute;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background-color: greenyellow;
        }

        .score {
            position: absolute;
            display: block;
            width: 500px;
            right: 10px;
            text-align: right;
            top: 10px;
            color: white;
            font-size: 20px;
        }
    </style>
</head>
<body>
<script>
    var Map;
    var Snake;
    var Food;
    var score = 0;
    var speed = 500;
    var time;
    var game = (function () {
        /*1.创建地图*/

        function map() {
            this._map = null;
            this._span = null;
            this.createMap = function () {
                if (this._map == null) {
                    this._map = document.createElement("div");
                    this._map.className = "map";
                }
            }
            this.createSpan = function () {
                if (this._span == null) {
                    this._span = document.createElement("span");
                    this._span.className = "score";
                    this._span.innerHTML = "总分:0";
                }
                this._map.appendChild(this._span);
            }
        }


        function snake() {
            this._map = null;
            this._span = null;
            this.direct = "right";            //蛇的默认元素  x,y,颜色
            this._snake = [[3, 1, "red", null], [2, 1, "yellow", null], [1, 1, "yellow", null]];
            this.createSnake = function () {
                for (var i = 0; i < this._snake.length; i++) {
                    if (this._snake[i][3] == null) {
                        this._snake[i][3] = document.createElement('div');
                        this._snake[i][3].style.backgroundColor = this._snake[i][2];
                        this._snake[i][3].className = "snake";
                    }
                    this._snake[i][3].style.left = this._snake[i][0] * 30 + "px";
                    this._snake[i][3].style.top = this._snake[i][1] * 30 + "px";
                    this._map.appendChild(this._snake[i][3]);
                }
            };
            this.snakeMove = function () {
                //蛇的属性传递 x,y
                var len = this._snake.length - 1;
                for (var i = len; i > 0; i--) {
                    //通过传递蛇的left top值完成蛇的运动
                    this._snake[i][0] = this._snake[i - 1][0];
                    this._snake[i][1] = this._snake[i - 1][1];
                }
                //设置蛇头在不同方向的移动 带动蛇的移动 需增加一个默认方向属性
                switch (this.direct) {
                    case "right":
                        this._snake[0][0] += 1;
                        break;
                    case "left":
                        this._snake[0][0] -= 1;
                        break;
                    case "up":
                        this._snake[0][1] -= 1;
                        break;
                    case "down":
                        this._snake[0][1] += 1;
                        break;
                }
                //调用蛇穿墙的方法
                this.snakeBack();

                //蛇吃食物
                if (this._snake[0][0] == Food.x && this._snake[0][1] == Food.y) {
                    score += 100;
                    this._span.innerHTML = "总分:" + score + "分";
                    if (score == 500) {
                        speed -= 200;
                    }
                    this._snake.push([
                        this._snake[this._snake.length - 1][0],
                        this._snake[this._snake.length - 1][1],
                        "yellow",
                        null
                    ]);
                    //食物换位置
                    Food.createFood();
                }
                //调用蛇撞死的方法
                this.snakeBackDie();
                //重新创建蛇
                this.createSnake();

            };
            //封装蛇穿墙的方法
            this.snakeBack = function () {
                if (this._snake[0][0] > 29) {
                    this._snake[0][0] = 0;
                }
                if (this._snake[0][0] < 0) {
                    this._snake[0][0] = 29;
                }
                if (this._snake[0][1] >19) {
                    this._snake[0][1] = 0;
                }
                if (this._snake[0][1] < 0) {
                    this._snake[0][1] = 19;
                }
            };
            //封装蛇撞死的方法
            this.snakeBackDie = function () {
                for (var i = 1; i < this._snake.length; i++) {
                    if (this._snake[0][0] == this._snake[i][0] && this._snake[0][1] == this._snake[i][1]) {
                        alert("游戏结束");
                        clearInterval(time);
                    }
                }
            }
        }

        function food() {
            this._food = null;
            this._map = null;
            this.x = 0;
            this.y = 0;
            this.createFood = function () {
                this.x = Math.floor(Math.random() * 30);
                this.y = Math.floor(Math.random() * 20);
                if (this._food == null) {
                    this._food = document.createElement("div");
                    this._food.className = "food";
                }
                this._food.style.left = this.x * 30 + "px";
                this._food.style.top = this.y * 30 + "px";
                this._map.appendChild(this._food);
            }
        }


        function getMaps() {
            Map = new map();
            Map.createMap();
            Map.createSpan();
            //创建食物
            CreateFood(Map._map);
            //创建蛇 把map作为参数传进去  添加蛇
            CreateSnake(Map._map, Map._span);
            return Map._map;
        }

        function CreateFood(map) {
            Food = new food();
            Food._map = map;
            Food.createFood();
        }

        function CreateSnake(map, span) {
            Snake = new snake();
            Snake._map = map;
            Snake._span = span;
            Snake.createSnake();
            //蛇移动
          time = setInterval(function () {
                Snake.snakeMove();
            }, speed);
            document.onkeypress = function (e) {
                switch (e.key) {
                    case "w":
                        if (Snake.direct == "down")
                            return;
                        Snake.direct = "up";
                        break;
                    case "a":
                        if (Snake.direct == "right")
                            return;
                        Snake.direct = "left";
                        break;
                    case "d":
                        if (Snake.direct == "left")
                            return;
                        Snake.direct = "right";
                        break;
                    case "s":
                        if (Snake.direct == "up")
                            return;
                        Snake.direct = "down";
                        break;
                }
            }
        }

        return {
            SnakeMap: getMaps()
        }
    })
    ();
    /*最后创建的元素显示到body页面*/
    document.body.appendChild(game.SnakeMap);
</script>
</body>
</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值