原生JS实现贪吃蛇项目

原生JS实现贪吃蛇项目

  • HTML部分

  • CSS部分

  • JavaScript部分

  • 原理
    //点击开始游戏---->startPage消失---->游戏开始
    //随机出现食物,出现三节蛇开始运动
    //上下左右===>改变方向运动,
    //判断吃到食物,=>蛇+1
    //判断游戏结束
    ==>弹出框
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
HTML代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>贪吃蛇</title>
    <link rel="stylesheet" href="demo.css">
</head>
<body>
     <div class="startPage" id="startPage">
        <div class="startBtn" id="startGameBtn">
           <!--  开始游戏按钮 -->
        </div>
    </div> 
    <div class="wrapper">
        <!-- 游戏界面 -->
        <div class="leftSide">
            <img src="start.jpg" id="startP">
        </div>
        <div class="main">
            <div class="header">
                <div class="score">
                    分数:
                    <span id="score"></span>
                </div>
            </div>
            <div class="content" id="content">
                <!-- 活动区域 -->
            </div>
        </div>
    </div>
    <div class="loser" id="loser">
        <!-- 游戏结束 -->
        <div class="con">
            <div class="close" id="close">
                <!-- x按钮 -->
            </div>
            <span class="loseScore" id="loseScore"></span>
        </div>
    </div>
    
    <script src="demo.js"></script>
</body>
</html>```



CSS部分:

*{
    margin: 0;
    padding: 0;
}
.startPage{
    width: 100%;
    z-index: 999;
    height: 600px;
    position: absolute;
    top: 0;
    left: 0;
}
.startBtn{
    background-image: url('start.png');
    background-repeat: no-repeat;
    width: 170px;
    height: 200px;
    background-size: 110% 100%;
    cursor: pointer;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
}
.wrapper{
    width: 100%;
    height: 600px;
    background-image: url('beijing.jpg');
    background-repeat: no-repeat;
    background-size: 100% 100%;
    position: relative;
}
.leftSide{
    width: 20%;
    height: 600px;
    position: absolute;
    /* border-right: 1px solid black; */
}
.leftSide img{
    display: none;
    margin-left: 50px;
    margin-top: 50px;
    width: 80px;
    height: 80px;
}
.main{
    position: absolute;
    left: 20.5%;
    width: 60%;
    height: 90%; 
    /* border: 1px solid black; */
}
.header{
    width: 100%;
    height: 65px;
    text-align: center;
}
.score{
    line-height: 80px;
    color: #ddd;
    font-size: 30px;
    font-weight: bold;
}
.content{
    position: absolute;
    width: 97.5%;
    height: 87%;
    /* border: 1px solid blue; */
}
.loser{
    display: none;
    position: 100%;
    height: 600px;
    top: 0;
    left: 0;   
}
.con{
    background-image: url("defen.jpg");
    background-size: 100% 100%;
    background-repeat: no-repeat;
    width: 500px;
    height: 300px;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
    border-radius: 20px;
}
.close{
    background-image: url('x.jpg');
    background-size: 100% 100%;
    background-repeat: no-repeat;
    position: absolute;
    top: 0;
    right: 0;
    height: 40px;
    width: 40px;
    cursor: pointer;
}
.loseScore{
    display: block;
    height: 30px;
    width: 40px;
    position: absolute;
    top: 38%;
    left: 38%;
    color: black;
    font-size: 25px;
    font-weight: bolder;
}
.food{
    background-image: url('food.jpg');
    background-size: 100% 100%;
}
.head{
    background-image: url('she.jpg');
    background-size: 100% 100%;
}
.body{
    background-image: url('sheshen.jpg');
    background-size: 100% 100%;
}

``

JS部分:
var content = document.getElementById('content');//
var startPage = document.getElementById('startPage');//
var scoreBox = document.getElementById('score');//
var loser = document.getElementById('loser');//
var loseScore = document.getElementById('loseScore');
var close = document.getElementById('close');
var startP = document.getElementById('startP');//
var startGameBtn = document.getElementById('startGameBtn');
var startGmaeBool = true;
var startPaushBool = true;
var snakeMove;//蛇运动
var speed = 200; //蛇运动速度 

init();//存着初始属性
function init() {
    //地图       随着浏览器大小content内容跟着变
    this.mapW = parseInt(getComputedStyle(content).width);//存在全局的属性
    this.mapH = parseInt(getComputedStyle(content).height);
    this.mapDiv = content;
    //食物
    this.foodW = 20;
    this.foodH = 20;
    this.foodX = 0;
    this.foodY = 0;//食物初始坐标
    //蛇
    // 位置x-1YxYx+1Y    
    this.snakeW = 20;
    this.snakeH = 20;
    this.snakeBody = [[5, 10, 'head'], [4, 10, 'body'], [3, 10, 'body']];//蛇身 
    //下一秒         [[6, 10, 'head'], [5, 10, 'body'], [4, 10, 'body']];

    //游戏属性
    this.direct = 'right';//默认是向右
    //当向右移动的时候   向左和向右不能改变
    this.left = false;
    this.right = false;
    this.up = true;
    this.down = true;

    //分数
    this.score = 0;
    // startGame();
}

function startGame() {
    startPage.style.display = 'none';
    startP.style.display = 'block';
    food();
    snake();
}

function food() {//产生food  
    var food = document.createElement('div');
    food.style.width = this.foodW + 'px';//宽
    food.style.height = this.foodH + 'px';//高
    //为了有xy坐标值 给它定位 可以通过left top值来控制位置
    food.style.position = 'absolute';
    this.foodX = Math.floor(Math.random() * ((this.mapW) / (this.foodW)));
    this.foodY = Math.floor(Math.random() * ((this.mapH) / (this.foodH)));
    food.style.left = this.foodX * 20 + 'px';
    food.style.top = this.foodY * 20 + 'px';
    this.mapDiv.appendChild(food).setAttribute('class', 'food');
}
function snake() {
    for (var i = 0; i < this.snakeBody.length; i++) {//跟组蛇的数组的长度设置div
        var snake = document.createElement('div');//创建snake
        snake.style.width = this.snakeW + 'px';
        snake.style.height = this.snakeH + 'px';
        snake.style.position = 'absolute';
        snake.style.left = this.snakeBody[i][0] * 20 + 'px';//left是根据里层数组的第0位
        snake.style.top = this.snakeBody[i][1] * 20 + 'px';
        snake.classList.add(this.snakeBody[i][2]);//为snake添加[i][2]的class的food和head
        this.mapDiv.appendChild(snake).classList.add('snake');
        switch (this.direct) {//方向
            case 'right':
                break;
            case 'up':
                snake.style.transform = 'rotate(270deg)';
                break;
            case 'left':
                snake.style.transform = 'rotate(180deg)';
                break;
            case 'down':
                snake.style.transform = 'rotate(90deg)';
                break;
            default:
                break;
        }
    }
}
function move() {
    for (var i = this.snakeBody.length - 1; i > 0; i--) {
        this.snakeBody[i][0] = this.snakeBody[i - 1][0];
        this.snakeBody[i][1] = this.snakeBody[i - 1][1];
    }
    switch (this.direct) {//方向
        case 'right':
            this.snakeBody[0][0] += 1;
            break;
        case 'up':
            this.snakeBody[0][1] -= 1;
            break;
        case 'left':
            this.snakeBody[0][0] -= 1;
            break;
        case 'down':
            this.snakeBody[0][1] += 1;
            break;
        default:
            break;
    }
    removeClass('snake');//把原来的蛇删掉 准备重新渲染一条蛇
    snake();
    if (this.snakeBody[0][0] == this.foodX && this.snakeBody[0][1] == this.foodY) {//吃食物情况,蛇头坐标等于食物坐标
        var snakeEndX = this.snakeBody[this.snakeBody.length - 1][0];  //取蛇的最后一位
        var snakeEndY = this.snakeBody[this.snakeBody.length - 1][1];
        switch (this.direct) {//方向
            case 'right':
                this.snakeBody.push([snakeEndX + 1, snakeEndY, 'body']);
                break;
            case 'up':
                this.snakeBody.push([snakeEndX, snakeEndY - 1, 'body'])
                break;
            case 'left':
                this.snakeBody.push([snakeEndX - 1, snakeEndY, 'body']);
                break;
            case 'down':
                this.snakeBody.push([snakeEndX, snakeEndY + 1, 'body']);
                break;
            default:
                break;
        }

        this.score += 1;
        scoreBox.innerHTML = this.score;
        removeClass('food');
        food();
    }

    //碰到边界问题
    if (this.snakeBody[0][0] < 0 || this.snakeBody[0][0] >= ((this.mapW) / (this.foodW))) {//横向碰到左右
        // console.log('shibai');
        reloadGame();
    }
    if (this.snakeBody[0][1] < 0 || this.snakeBody[0][1] >= ((this.mapH) / (this.foodH))) {//碰到上下
        // console.log('shibai');
        reloadGame();
    }
    //蛇头碰到蛇身和蛇尾
    var snakeHX = this.snakeBody[0][0];//取出蛇头的x
    var snakeHY = this.snakeBody[0][1];
    for (var i = 1; i < this.snakeBody.length; i++) {//从头后面身体第一位开始
        if (snakeHX == snakeBody[i][0] && snakeHY == snakeBody[i][1]) {
            // console.log('shibai');
            reloadGame();
        }
    }
}
function reloadGame() {//重新加载
    removeClass('snake');
    removeClass('food');
    clearInterval(snakeMove);
    this.snakeW = 20;
    this.snakeH = 20;
    this.snakeBody = [[5, 10, 'head'], [4, 10, 'body'], [3, 10, 'body']];//蛇身 
    //下一秒         [[6, 10, 'head'], [5, 10, 'body'], [4, 10, 'body']];

    //游戏属性
    this.direct = 'right';//默认是向右
    //当向右移动的时候   向左和向右不能改变
    this.left = false;
    this.right = false;
    this.up = true;
    this.down = true;

    //分数
    loser.style.display = 'block';
    loseScore.innerHTML = this.score;// 得分
    this.score = 0;
    this.scoreBox = this.score

    startGmaeBool = true;//回到初始化
    startPaushBool = true;
    startP.setAttribute('src', 'start.jpg');
    
}

function removeClass(calssName) {
    var ele = document.getElementsByClassName(calssName);
    while (ele.length > 0) {
        ele[0].parentNode.removeChild(ele[0]);//把原来的snake删掉 
    }
}

function setDerict(code) {//判断键盘按下去的时候返回的ASCII码的值是什么 来判断是上下左右哪一个
    switch (code) {
        case 37:
            if (this.left) {
                this.direct = 'left';
                this.right = false;
                this.left = false;
                this.up = true;
                this.down = true;
            }
            break;
        case 38:
            if (this.up) {
                this.direct = 'up';
                this.right = true;
                this.left = true;
                this.up = false;
                this.down = false;
            }
            break;
        case 39:
            if (this.right) {
                this.direct = 'right';
                this.right = false;
                this.left = false;
                this.up = true;
                this.down = true;
            }
            break;
        case 40:
            if (this.down) {
                this.direct = 'down';
                this.right = true;
                this.left = true;
                this.up = false;
                this.down = false;
            }
            break;
        default:
            break;
    }
}
bindEvent();
function bindEvent() {//
    //
    close.onclick = function () {
        loser.style.display = 'none';
    }
    startGameBtn.onclick = function () {
        startAndPaush();
        // console.log('aaa')
    }
    startP.onclick = function () {
        startAndPaush();
    }
}

function startAndPaush() {
    if (startPaushBool) {
        if (startGmaeBool) {
            startGame();
            startGmaeBool = false;
        }
        startP.setAttribute('src', 'stop.jpg');
        document.onkeydown = function (e) {
            var code = e.keyCode;
            setDerict(code);
        }
        snakeMove = setInterval(function () {//运动
            move();
        }, speed);
        startPaushBool = false;
    } else {
        startP.setAttribute('src', 'start.jpg');
        clearInterval(snakeMove);
        document.onkeydown = function (e) {
            e.returnValue = false;
            return false;
        };
        startPaushBool = true;
    }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值