Javascript 实现一个简单的“别踩白块儿”游戏

2,218 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

前言

之前刚刚学Javascript的时候,写了一个简单的“别踩白块儿”游戏。刚刚整理代码的时候突然发现,刚好可以写个分析,就当是复习原生的Javascript。

一、方法

核心思路:定义一个元素作为块的容器,通过容器的偏移量变化来模拟块的移动。

  1. 初始化的时候,容器向上偏移一定的高度(一个块的高度),并不断移动。
  2. 向容器中添加块,每次添加一行,一行4个,其中一个随机变为黑色块。
  3. 当添加到一定行数(容器铺满),判断最前的一行是否通过,通过则移除并添加新行,不通过则游戏结束。

二、效果

  1. 别踩白块儿基本效果
  2. 实时积分
  3. 可控制速度
  4. 暂停和继续
  5. 随积分增长速度加快

三、实现的过程

1. HTML + CSS

这个就直接贴了,没什么好讲的。


    <div class="wrap">
        <div class="gamebox">
            <div class="gamearea">
                <div class="moveblocks" id="moveblocks"></div>
                <!-- <div class="main" id="main"></div> -->
            </div>
            <button class="start" id="start">
                GAME START!
            </button>
        </div>
        <div class="controlbox">
            <div class="score" id="score">
                <p>Score</p>
                <p>0</p>
            </div>
            <div class="speed" id="speed">
                <p>speed</p>
                <p>0</p>
            </div>
            <button class="speedUp" id="speedUp">
                speed Up!
            </button>
            <button class="slowDown" id="slowDown">
                slow Down!
            </button>
            <button class="pause" id="pause">
                Pause
            </button>
        </div>
    </div>

2. Javascript

  1. 首先获取对应的元素,初始化配置项
        var moveblocks = document.getElementById("moveblocks");
        var main = document.getElementById("main");
        var start = document.getElementById("start");
        var score = document.getElementById("score");
        var speedbox = document.getElementById("speed");
        var speedUp = document.getElementById("speedUp");
        var slowDown = document.getElementById("slowDown");
        var pause = document.getElementById("pause");
        var goOn = document.getElementById("goOn");

        // 计时器
        var timer;
        // 初始速度
        var startspeed = 1;
        // 速度
        var speed = startspeed;
        // 积分
        var num = 0;
  1. 块填充函数

在容器中继续添加块。 主要通过这个函数来添加块,并通过设置样式类名来标志是否是需要点击的块。

        function createNewDiv(classname) {

            var newrow = document.createElement("div");
            newrow.className = classname;
            for (var i = 0; i < 4; i++) {
                var blocks = document.createElement("div");
                newrow.appendChild(blocks);
            }

            // 如果游戏区域是空的,newrow应该放在后面;
            // 如果游戏区域不是空的,newrow应该插入到第一个之前去
            if (moveblocks.children.length == 0) {
                moveblocks.appendChild(newrow);
            }
            else {
                moveblocks.insertBefore(newrow, moveblocks.children[0]);
            }

            //给随机一个block加颜色
            index = Math.floor(Math.random() * 4)
            newrow.children[index].style.backgroundColor = "black";
            newrow.children[index].className = "i";
        }
  1. 容器移动和点击积分函数

容器初始化时位于 -115px 处并通过原来位置和速度更新新的位置

当位置超出时,回到初始位置。
当添加到一定行数(容器铺满),判断最前的一行是否通过。


function movebox(obj) {
            // 初始化 速度 和 分数
            // var startspeed = 1;
            // var speed = startspeed;
            // var num = 0;
            timer = setInterval(
                function () {
                    var y = parseInt(getComputedStyle(obj, null)['top']) + speed;
                    obj.style.top = y + "px";
                    if (parseInt(getComputedStyle(obj, null)['top']) >= 0) {
                        createNewDiv("newrow");
                        obj.style.top = -115 + "px";
                    }

                    // 进行判定
                    if (obj.children.length >= 6) {
                        for (var i = 0; i < 4; i++) {
                            if (obj.children[obj.children.length - 1].children[i].className == 'i') {
                                //游戏结束
                                obj.style.top = '-115px';
                                // score.innerHTML = '游戏结束,最高得分: ' + num;
                                //关闭定时器
                                // clearInterval(obj.timer);
                                clearInterval(timer);
                                //显示开始游戏
                                confirm("游戏结束,最高分:" + num);
                                start.innerHTML = "REPLAY";
                            }
                        }
                        obj.removeChild(obj.children[obj.children.length - 1]);
                    }

                    //点击和积分

                    obj.onclick = function (event) {
                        event = event || window.event;
                        if (((event.target ? event.target : event.srcElement).className == 'i')
                            ||
                            ((event.target ? event.target : event.srcElement).className == 'k')) {
                            if ((event.target ? event.target : event.srcElement).className == 'i') {
                                //点击后的盒子颜色
                                (event.target ? event.target : event.srcElement).style.backgroundColor = "#bbb";
                                //清除盒子标记
                                (event.target ? event.target : event.srcElement).className = 'k';
                                //计分
                                num++;
                            }
                        } else {
                            obj.style.top = 0;
                            // clearInterval(obj.timer);
                            clearInterval(timer);
                            start.innerHTML = "REPLAY";
                            confirm("游戏结束,最高分:" + num);
                        }
                        // 每积10分速度增加一次;
                        if (num != 0 && num % 10 == 0) {
                            speed++;
                        }
                    }

                    // 实时显示分数和速度
                    score.children[1].innerHTML = num;
                    speedbox.children[1].innerHTML = speed;
                }, 20);


        }
  1. 加速,减速,暂停/继续功能
        // 加速
        speedUp.onclick = function () {
            speed++;
        }

        // 减速 不加判定还可以向上走,hhhhhhhhhhh
        slowDown.onclick = function () {
            // if (speed > 1) {
            //     speed--;
            // }
            speed--;
        }

        // 暂停和继续   设置statics属性保存状态
        pause.statics = 0;
        pause.onclick = function () {
            if (speed != 0) {
                prespeed = speed;
            }
            if (pause.statics == 0) {
                pause.statics = 1;
                speed = 0;
                pause.innerHTML = "goOn";
            } else {
                pause.statics = 0;
                speed = prespeed;
                pause.innerHTML = "pause";
            }
        }
  1. 游戏启动函数
        start.onclick = function () {
            clearInterval(timer);
            startspeed = 1;
            speed = startspeed;
            if (moveblocks.children.length != 0) {
                // 游戏开始的时候清空moveblocks盒子
                moveblocks.innerHTML = '';
            }
            //清空计分
            start.innerHTML = "冲呀!";
            score.children[1].innerHTML = 0;
            speedbox.children[1].innerHTML = 0;
            movebox(moveblocks);
        }

完整的代码

<!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>Document</title>
    <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" />
    <script type="text/javascript" src=""></script>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;

        }

        html,
        body {
            margin: 0;
            padding: 0;
            font-size: 16px;

        }

        .wrap {
            width: 35%;
            height: 650px;
            margin: auto;
            background-color: antiquewhite;
            display: flex;

        }

        .gamebox {
            width: 65%;
            height: 650px;
            background-color: white;
            border-style: solid;
            border-width: 0 1px 1px 1px;
        }

        .gamearea {
            height: 575px;
        }

        #moveblocks {
            width: 100%;
            height: 575px;
            position: relative;
            top: -115px;
        }

        #main {
            width: 100%;
            height: 575px;
        }

        .start {
            width: 100%;
            height: 75px;
            line-height: 72px;
            font-size: 1.7rem;
            font-weight: bold;
            text-align: center;
            background-color: antiquewhite;
            cursor: pointer;
        }

        .controlbox {
            width: 35%;
        }

        .score,
        .speed {
            width: 100%;
            height: 100px;
            margin: 25px 0;
            box-sizing: border-box;
            font-size: 1.7rem;
            font-weight: bold;
            text-align: center;
        }

        .score p,
        .speed p {
            height: 50px;
            line-height: 50px;
        }

        .speedUp,
        .slowDown,
        .pause {
            width: 100%;
            height: 50px;
            list-style: none;
            text-decoration: none;
            background-color: antiquewhite;
            cursor: pointer;
            font-size: 1.3rem;
            font-weight: bold;
            text-align: center;
        }

        .speedUp {
            margin: 50px 0 25px 0;
        }

        .slowDown {
            margin: 25px 0 25px 0;
        }

        .pause {
            margin: 25 px 0 50px 0;
        }


        .newrow {
            width: 100%;
            height: 115px;
            display: flex;
        }

        .newrow div {
            width: 25%;
            height: 115px;
            border-style: solid;
            border-width: 0 1px 1px 1px;
            /* border-top-width: 0;
            border-left-width: 0; */
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div class="wrap">
        <div class="gamebox">
            <div class="gamearea">
                <div class="moveblocks" id="moveblocks"></div>
                <!-- <div class="main" id="main"></div> -->
            </div>
            <button class="start" id="start">
                GAME START!
            </button>
        </div>
        <div class="controlbox">
            <div class="score" id="score">
                <p>Score</p>
                <p>0</p>
            </div>
            <div class="speed" id="speed">
                <p>speed</p>
                <p>0</p>
            </div>
            <button class="speedUp" id="speedUp">
                speed Up!
            </button>
            <button class="slowDown" id="slowDown">
                slow Down!
            </button>
            <button class="pause" id="pause">
                Pause
            </button>
        </div>
    </div>

    <script type="text/javascript">

        // 找对象
        var moveblocks = document.getElementById("moveblocks");
        var main = document.getElementById("main");
        var start = document.getElementById("start");
        var score = document.getElementById("score");
        var speedbox = document.getElementById("speed");
        var speedUp = document.getElementById("speedUp");
        var slowDown = document.getElementById("slowDown");
        var pause = document.getElementById("pause");
        var goOn = document.getElementById("goOn");

        // 计时器
        var timer;
        // 初始速度
        var startspeed = 1;
        // 速度
        var speed = startspeed;
        // 积分
        var num = 0;

        // 每行创建一个大div,再在里面创建4个小div,调用一次函数只创建一行div
        function createNewDiv(classname) {

            var newrow = document.createElement("div");
            newrow.className = classname;
            for (var i = 0; i < 4; i++) {
                var blocks = document.createElement("div");
                newrow.appendChild(blocks);
            }

            // 如果游戏区域是空的,newrow应该放在后面;
            // 如果游戏区域不是空的,newrow应该插入到第一个之前去
            if (moveblocks.children.length == 0) {
                moveblocks.appendChild(newrow);
            }
            else {
                moveblocks.insertBefore(newrow, moveblocks.children[0]);
            }

            //给随机一个block加颜色
            index = Math.floor(Math.random() * 4)
            newrow.children[index].style.backgroundColor = "black";
            newrow.children[index].className = "i";
        }

        function movebox(obj) {
            // 初始化 速度 和 分数
            // var startspeed = 1;
            // var speed = startspeed;
            // var num = 0;
            timer = setInterval(
                function () {
                    var y = parseInt(getComputedStyle(obj, null)['top']) + speed;
                    obj.style.top = y + "px";
                    if (parseInt(getComputedStyle(obj, null)['top']) >= 0) {
                        createNewDiv("newrow");
                        obj.style.top = -115 + "px";
                    }

                    // 进行判定
                    if (obj.children.length >= 6) {
                        for (var i = 0; i < 4; i++) {
                            if (obj.children[obj.children.length - 1].children[i].className == 'i') {
                                //游戏结束
                                obj.style.top = '-115px';
                                // score.innerHTML = '游戏结束,最高得分: ' + num;
                                //关闭定时器
                                // clearInterval(obj.timer);
                                clearInterval(timer);
                                //显示开始游戏
                                confirm("游戏结束,最高分:" + num);
                                start.innerHTML = "REPLAY";
                            }
                        }
                        obj.removeChild(obj.children[obj.children.length - 1]);
                    }

                    //点击和积分

                    obj.onclick = function (event) {
                        event = event || window.event;
                        if (((event.target ? event.target : event.srcElement).className == 'i')
                            ||
                            ((event.target ? event.target : event.srcElement).className == 'k')) {
                            if ((event.target ? event.target : event.srcElement).className == 'i') {
                                //点击后的盒子颜色
                                (event.target ? event.target : event.srcElement).style.backgroundColor = "#bbb";
                                //清除盒子标记
                                (event.target ? event.target : event.srcElement).className = 'k';
                                //计分
                                num++;
                            }
                        } else {
                            obj.style.top = 0;
                            // clearInterval(obj.timer);
                            clearInterval(timer);
                            start.innerHTML = "REPLAY";
                            confirm("游戏结束,最高分:" + num);
                        }
                        // 每积10分速度增加一次;
                        if (num != 0 && num % 10 == 0) {
                            speed++;
                        }
                    }

                    // 实时显示分数和速度
                    score.children[1].innerHTML = num;
                    speedbox.children[1].innerHTML = speed;
                }, 20);


        }

        // 加速
        speedUp.onclick = function () {
            speed++;
        }

        // 减速 不加判定还可以向上走,hhhhhhhhhhh
        slowDown.onclick = function () {
            // if (speed > 1) {
            //     speed--;
            // }
            speed--;
        }

        // 暂停和继续   设置statics属性保存状态
        pause.statics = 0;
        pause.onclick = function () {
            if (speed != 0) {
                prespeed = speed;
            }
            if (pause.statics == 0) {
                pause.statics = 1;
                speed = 0;
                pause.innerHTML = "goOn";
            } else {
                pause.statics = 0;
                speed = prespeed;
                pause.innerHTML = "pause";
            }
        }

        start.onclick = function () {
            clearInterval(timer);
            startspeed = 1;
            speed = startspeed;
            if (moveblocks.children.length != 0) {
                // 游戏开始的时候清空moveblocks盒子
                moveblocks.innerHTML = '';
            }
            //清空计分
            start.innerHTML = "冲呀!";
            score.children[1].innerHTML = 0;
            speedbox.children[1].innerHTML = 0;
            movebox(moveblocks);
        }

    </script>
</body>

</html>