【无标题】

<div id="content">

<div id="snake">

<div class="box head"></div>

<div class="box"></div>

</div>

</div>

其中,content为整个布局的大盒子,snake就是蛇,里面的box就是他的身体,为了区分头部我们给第一个box加了个head名字用于区分,下面我们再把css加上。

<style>

.box{

width: 60px;

height: 60px;

background-color: red;

position:absolute;

left: 0;

top: 0;

line-height: 60px;

}

.head{

background-color: yellowgreen;

}

</style>

我们给蛇的每一节的宽高设置为60像素,并给了一个定位,因为如果不加定位的话无法让他脱离文档流(在页面中飘起来),而且后续也无法通过left和top来判断他的坐标。

 

好的这样我们就得到了一条可爱的小蛇(然而并没有看出来哪里可爱 - -)。

什么?你问我他的头哪去了,很简单,在给元素加了定位以后,后面的元素会覆盖掉前面的元素,所以只是头部和身体重叠了你看不到而已。

随后咱们得让这条蛇动起来是吧,那么我们怎么让他动起来呢?

原理很简单,我们可以设置一个定时器,每过一个时间就让他动一下。而怎么让他动呢,只需要设置一个数值,让这个值每动一下就+=60,然后通过判断是上下动还是左右动,来给元素的left与top赋值。

我们把逻辑写成代码,就出来了如下的代码:

<script>

var boxs = document.querySelectorAll(".box");

var snake_x = 0;

var snake_y = 0;

var turn = "right";

setInterval(function(){

snakeMove();

},100)

function snakeMove(){

switch( turn ){

case "right": snake_x += 60;break;

case "left" : snake_x -= 60;break;

case "top" : snake_y -= 60;break;

case "bottom": snake_y += 60;break;

}

for(var i = boxs.length - 1; i > 0 ; i --){

boxs[i].style.left = boxs[i - 1].style.left;

boxs[i].style.top = boxs[i - 1].style.top;

}

boxs[i].style.left = snake_x + "px";

boxs[i].style.top = snake_y + "px";

}

document.onkeydown = function(evt){

var e = evt || event;

var keyCode = e.keyCode || e.which;

switch( keyCode ){

case 37 : turn = "left";break;

case 38 : turn = "top";break;

case 39 : turn = "right";break;

case 40 : turn = "bottom";break;

}

}

</script>

上述代码中,我们给小蛇的初始位置的x和y的坐标都设置为0,并且默认初始向右走,通过键盘上方向键的输入,来改变他的方向。

其中,难点在于

for(var i = boxs.length - 1; i > 0 ; i --){

boxs[i].style.left = boxs[i - 1].style.left;

boxs[i].style.top = boxs[i - 1].style.top;

}

boxs[i].style.left = snake_x + "px";

boxs[i].style.top = snake_y + "px";

这一块代码,这块代码的目的是让后面的元素跟着前面的走,也就是让蛇的每一块身体都跟着上一块去运动,然后最后再给头部设置为snake_x和snake_y当前的值即可,这样就形成了第一块(头部)坐标为snake_x,snake_y实时变化的值,第二块为第一块之前的值,第三块为第二块之前的值。

以此类推就得到了一个身体跟着头部走的效果:

 

但是当你把代码输进去以后一运行会发现,这条小蛇过于顽皮,以至于走到边界以后还会无限的向前走,那这不行啊,总不能让蛇跑了不是,所以得给小蛇加上一个边界:

var snake_x_max = document.documentElement.clientWidth ;

var snake_y_max = document.documentElement.clientHeight;

if(snake_x > snake_x_max){

snake_x = 0;

}

if(snake_x < 0){

snake_x = snake_x_max;

}

if(snake_y > snake_y_max){

snake_y = 0;

}

if(snake_y < 0){

snake_y = snake_y_max;

}

这里我们设置x和y的最大值为当前窗口的宽高,然后通过if语句进行判断,如果当前坐标大于了最大值,就讲当前坐标归0,如果小于0的话(也就是跑到了左边的边界),就将当前坐标设置为最大值,这样就可以得到一个边界啦。

 

你以为这样就完事啦?nonono,没有食物吃的蛇怎么能叫做贪吃蛇呢,那是没有灵魂哒。

下面我们开始制作食物。

<div id="food">

</div>

然后给他加个css

#food{

width: 60px;

height: 60px;

position: absolute;

background: greenyellow;

}

然后再绑定一下元素并将他的left和top值设为范围内随机数,这样可以做到随机位置生成:

var fd=document.getElementById("food");

fd.style.left=Math.random()*snake_x_max+"px";

fd.style.top=Math.random()*snake_y_max+"px";

这样我们就得到了一个随机生成的食物:

 

不过我们的小蛇好像对食物并没有什么兴趣呢,路过以后并不会吃掉,所以我们得给他加一个碰撞检测吧。

碰撞检测的逻辑很简单,只需要让食物的left值与头部的left值相减的绝对值<=食物的大小,并且食物的top值与头部的top值相减的绝对值<=食物的大小,设置小于等于是因为如果直接用相等来判断的话,必须两个元素完全重合才行,我们需要的是碰到边缘就算迟到,所以用两个数值相减小于等于来做。

然后判断当头部与食物发生碰撞时,将蛇的身体部分克隆一块出来放到蛇的身体里面,并让食物的位置重新刷新。适用克隆为偷懒方法,此偷懒方法仅适用于当小蛇开局自带一个身体的时候,如果小蛇开局不自带身体的话,我们无法克隆已有身体,只能通过createElement去新创建一个身体块出来并添加className后再添加到父元素中去才行。

下面我们把逻辑转换为代码:

var dl=snake_x;

var dt=snake_y;

var fl=fd.style.left;

var ft=fd.style.top;

var dv=document.querySelectorAll("#snake div");

var sk=document.getElementById("snake");

var a2=Number(fl.substring(0,fl.indexOf("px")));

var b2=Number(ft.substring(0,ft.indexOf("px")));

if(Math.abs(dl-a2)<=60&&Math.abs(dt-b2)<=60){

fd.style.left=Math.random()*1000+"px";

fd.style.top=Math.random()*800+"px";

sk.appendChild(dv[1].cloneNode());

boxs = document.querySelectorAll(".box");

}

其中那一大长串的substring的方法是因为获取到的left与top的值的格式是例如”200px”这样的数组,无法进行数学运算,所以要把px给截掉,并将剩下的字符串”200”转换成number类型才可以进行数学运算。

 

第2种

<!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>贪恰蛇</title>

    <style>

        #scence{

            width: 800px;

            height: 600px;

            border: 1px solid #000;

            margin: 50px auto;

            background-color: aliceblue;

            position: relative;

            overflow: hidden;

        }

       .head{

           position: absolute;

           width: 20px;

           height: 20px;

           background-color: #000;

       }

       .tail{

        position: absolute;

           width: 20px;

           height: 20px;

           background-color: grey;      

       }

    </style>

</head>

<body>

    <div id="scence">

 

    </div>

</body>

</html>

<script src="tools.js"></script>

<script src="../贪吃蛇/snake.js"></script>

<script src="food.js"></script>

<script src="game.js"></script>

js部分

tools.js

1

2

3

4

5

6

7

8

function getStyle(ele, styleObj) {

    for (const key in styleObj) {

        ele.style[key] = styleObj[key];

    }  

}

function getRandom(a, b) {

    return Math.floor(Math.random() * (b - a) + a +1)

}

snake.js

function Snake() {

    this.scence = document.querySelector('#scence');

    this.body = [

        [0, 0, 'grey', null],

        [0, 1, 'grey', null],

        [0, 2, '#000', null]

    ];

    this.dir = 'right';

    this.lastdir = 'right';

    this.width = 20;

    this.height = 20;

    this.scence_w = scence.offsetWidth;

    this.scence_h = scence.offsetHeight;

}

Snake.prototype.found = function () {

    for (let i = 0; i < this.body.length; i++) {

        if (this.body[i][3] == null) {

            this.body[i][3] = document.createElement('div');

        }

        getStyle(this.body[i][3], {

            width: this.width + 'px',

            height: this.height + 'px',

            position: 'absolute',

            top: this.height * (this.body[i][0]) + 'px',

            left: this.width * (this.body[i][1]) + 'px',

            backgroundColor: this.body[i][2]

        });

        this.scence.appendChild(this.body[i][3]);

    }

}

//运动函数

Snake.prototype.move = function () {

    var length = this.body.length;

    for (let i = 0; i < length - 1; i++) {

        this.body[i][0] = this.body[i + 1][0];

        this.body[i][1] = this.body[i + 1][1];

    }

    let snakehead = this.body[length - 1]

    switch (this.dir) {

        case 'right':

            snakehead[1] += 1;

            break;

        case 'left':

            snakehead[1] -= 1

            break;

        case 'up':

            snakehead[0] -= 1

            break;

        case 'down':

            snakehead[0] += 1

            break;

    }

    this.lastdir = this.dir;

    snake.found();

}

//计时运动

Snake.prototype.shift = function () {

    document.onkeydown = (e) => {

        e = e || window.event;

        let key = e.keyCode;

        switch (key) {

            case 39:

                if (this.lastdir == 'left') {

                    this.dir = 'left'

                } else {

                    this.dir = 'right'

                };

                break;

            case 37:

                if (this.lastdir == 'right') {

                    this.dir = 'right'

                } else {

                    this.dir = 'left'

                };

                break;

            case 38:

                if (this.lastdir == 'down') {

                    this.dir = 'down'

                } else {

                    this.dir = 'up'

                };

                break;

            case 40:

                if (this.lastdir == 'up') {

                    this.dir = 'up'

                } else {

                    this.dir = 'down'

                };

                break;

        }

    }

}

 

//游戏结束

Snake.prototype.over = function () {

    let top = this.body[this.body.length - 1][0];

    let left = this.body[this.body.length - 1][1];

    let width = this.scence_w / this.width - 1;

    let height = this.scence_w / this.height - 1;

    if (top < 0 || left < 0 || top > width || left > height) {

        clearInterval(timeid)

        alert('game over');

    }

    for (let i = 0; i < this.body.length - 1; i++) {

        if (top == this.body[i][0] && left == this.body[i][1]) {

            clearInterval(timeid)

            alert('game over');

        }

    }

}

 

 

let snake = new Snake();

snake.found();

snake.shift();

timeid = setInterval(function () {

    snake.move();

    food.eat();

    snake.over()

}, 100)

food.js

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

2

function Food() {

  this.scence = document.querySelector('#scence');

  this.width = 20;

  this.height = 20;

  this.body = [-1, -1, 'red', null];

  this.scence_w = scence.offsetWidth;

  this.scence_h = scence.offsetHeight;

   

}

//食物生成

Food.prototype.crteate = function () {

  this.body[1] = getRandom(0, this.scence_w / this.width-1);

  this.body[0] = getRandom(0, this.scence_h / this.height-1);

  this.body[3] = document.createElement('div');

  getStyle(this.body[3], {

    width: this.width + 'px',

    height: this.height + 'px',

    position: 'absolute',

    top: this.height * (this.body[0] ) + 'px',

    left: this.width * (this.body[1] ) + 'px',

    backgroundColor: this.body[2],

    borderRadius: ' 50%',

  });

  this.scence.appendChild(this.body[3]);

 

 

}

//蛇吃到食物

Food.prototype.eat=function(){

  // const new=[0, 0, 'grey', null]

if(snake.body[snake.body.length-1][0]==this.body[0] && snake.body[snake.body.length-1][1]==this.body[1]){

  this.scence.removeChild(this.body[3]);

  this.crteate();

  snake.body.unshift([-1,-1,"grey",null])

}

}

let food = new Food();

food.crteate();

food.eat();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值