JS 实现小游戏 打砖块

文章目录

  • 1. 概述
  • 2. 游戏场景
  • 3. 实现砖块布局
  • 4.小球和挡板
  • 5.挡板运动
  • 6.挡板边界
  • 7.小球运动
  • 8.小球边界
  • 9.碰撞检测 (重点复杂点)
  • 10.音效处理

1. 概述

这是一个游戏,这不仅仅是一个游戏,我们的目标不是为了开发游戏,而是为了掌握常见函数和基本开发思路 (多练多练)
实现代码之前 先有思路 实现具体的功能 和进行不断的调式
以下是本人在培训时期老师写的代码 思路图为老师所画

2. 游戏场景

场景为css 和 html 组成
直接上代码
代码如下

  <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      html,
      body {
        background-color: aliceblue;
      }
      h2 {
        text-align: center;
        margin: 20px auto;
      }
      #box {
        background-color: white;
        width: 1000px;
        height: 500px;
        box-shadow: 0 0 3px darkcyan;
        margin: 20px auto;
        position: relative;
      }

      P {
        display: block;
        width: 100px;
        /* 砖块样式 */
        height: 40px;
        position: absolute;
        box-shadow: -2px -3px -6px black;
      }
      #baffle {
        position: absolute;
        width: 200px;
        height: 16px;
        border-radius: 8px;
        background-color: brown;
        left: 454px;
        top: 484px;
      }
      #ball {
        z-index: 99;
        width: 30px;
        height: 30px;
        background: rgb(117, 85, 74);
        box-shadow: #888 2px 2px 3px;
        position: absolute;
        top: 454px;
        left: 534px;
        border-radius: 50%;
      }
    </style>
  </head>
  <body>
    <h2>打砖块</h2>
    <div id="box">
      <!-- 小球 -->
      <div id="ball"></div>
      <!-- 挡板 -->
      <div id="baffle"></div>
    </div>

网页效果如下:
JS 实现小游戏 打砖块_第1张图片

3. 实现砖块布局

技术准备:
JS 实现小游戏 打砖块_第2张图片
代码实现:

       // 让js代码在网页加载后执行
      window.onload = function () {
        //获取场景对象

        var _box = document.querySelector("#box");
         // ----------------------- 砖块处理部分
        //定义行数
        var rows = 3;
        //计算一行放多少砖块
        var cols = Math.floor(_box.offsetWidth / 100);

        //声明一个保存砖数的数组
        var brickArrs = []
        //循环 创建砖块
        for (var i = 0; i < rows; i++) {
          //循环创建多行

          for (var j = 0; j < cols; j++) {
            //循环创建一行中的多个砖块

            //创建砖块 p 标签
            var _p = document.createElement("p");
            _p.style.backgroundColor =
              "#" + Math.random().toString(16).substr(2, 6);

            //p 标签定位;位置
            _p.style.left = j * 100 + "px";
            _p.style.top = i * 40 + "px";

            //将砖块添加到场景中
            _box.appendChild(_p);

            //将砖块保存到数组中
            brickArrs.push(_p)
          }
        }

网页实现效果:
JS 实现小游戏 打砖块_第3张图片

4.小球和挡板

在这里插入图片描述

代码详情在第一段里

5.挡板运动

技术实现:
让挡板运动起来 用左右方向键控制
JS 实现小游戏 打砖块_第4张图片
代码实现:

       //-----------挡板运动
        var _baffle = document.querySelector("#baffle")
        var _speed = 20

        document.onkeydown = function(e) {
              //获取事件对象
              var e = e || window.event

              //判断用户按下的按键
            var keyCode = e.keyCode

            //用户按下,控制挡板运动
            switch(keyCode) {
                case 37:
                    console.log("向左移动")
                    _baffle.style.left = _baffle.offsetLeft - _speed + "px"
                    break
                case 39:
                    console.log("向右移动")
                    _baffle.style.left = _baffle.offsetLeft + _speed + "px"
                    break
            }

6.挡板边界

左右不超出场景边缘

代码实现:

      //挡板边界判断,挡板不能超出边界
            if(_baffle.offsetLeft < 0) {
                _baffle.style.left = 0
            }else if(_baffle.offsetLeft >= (_box.offsetWidth - _baffle.offsetWidth)){
                _baffle.style.left = (_box.offsetWidth - _baffle.offsetWidth) + "px"
            }
        }

网页实现效果:
在这里插入图片描述

7.小球运动

需求:小球在游戏区域可以运动起来,碰撞墙壁的时候需要反弹

分析图如下图
JS 实现小游戏 打砖块_第5张图片
代码实现:

        //----------小球运动
        var _ball = document.querySelector("#ball")
        var speedX = 3 //垂直速度
        var speedY = -5 //水平速度
       // ballInterval   全部间隔
       //setInterval  设置间隔
        var ballInterval = setInterval(function () {
          //小球运动起来
        _ball.style.left = _ball.offsetLeft + speedX + "px"
        _ball.style.top = _ball.offsetTop + speedY + "px"

8.小球边界

需求:小球不能碰撞下边界,一旦碰撞到下边界游戏结束;下边界上必须让小球碰撞到挡板进行反弹

分析图解:
JS 实现小游戏 打砖块_第6张图片
代码实现:

       //边界判断
        if(_ball.offsetLeft < 0 ) {//左边界
           speedX = 3
        }else if(_ball.offsetLeft > (_box.offsetWidth - _ball.offsetWidth)) {
            speedX = -3
        }

        if(_ball.offsetTop < 0 ) { //上边界
           speedY = 5
        } else if(
           ( _ball.offsetLeft >= (_baffle.offsetLeft - _ball.offsetWidth/2))
            &&
            (_ball.offsetLeft <= (_baffle.offsetLeft + _baffle.offsetWidth - _ball.offsetWidth/2))
            &&
            (_ball.offsetTop >= (_baffle.offsetTop -_ball.offsetHeight))
            ) { // 碰到挡板
                speedY = -5

            }else if(_ball.offsetTop > (_box.offsetHeight - _ball.offsetHeight)){
                clearInterval(ballInterval)// clearInterval 清除间隔
                alert("你漏球了,结束") //弹窗 阻止代码执行    计时器仍然执行 
                location.reload()//重新加载当前位置  刷新网页
            }

9.碰撞检测 (重点复杂点)

小球和砖块之间的碰撞检测,小球碰到砖块,砖块消失/小球反弹,
具体操作如图
JS 实现小游戏 打砖块_第7张图片
如果碰撞过程中,按照每一个碰撞面去检测,很容易存在 BUG

代码中通过上下碰撞面、左右碰撞面进行同时检测,检测小球坐标一旦进入砖块
内部就算碰撞成功,让砖块消失/代码中通过 DOM removeChild() 函数移除标签,小球的运动反弹 左右碰撞面-水平速度取反、上下碰撞面-垂直速度取反

代码实现:


        //判断小球是否和砖块发生碰撞
        for(var x = 0; x < brickArrs.length; x++) {
            //获取一个砖块
            var brick = brickArrs[x]
            //碰撞检测
            collide(brick, _ball)
        }

        }, 20)
       
        //--------------------- 碰撞检测:小球、砖块
         // brick :砖块
         // ball:小球
        function collide(brick, ball) {
        console.log("--------------------------------------")
        // console.log(brick.offsetLeft, brick.offsetTop, brick.offsetWidth, brick.offsetHeight, "砖块")
        // console.log(ball.offsetLeft, ball.offsetTop, ball.offsetWidth, ball.offsetHeight, "小球")
        console.log("--------------------------------------")
        // 底部碰撞、左侧碰撞、顶部碰撞、右侧碰撞
        if(
             //offset  抵消
          (ball.offsetLeft > (brick.offsetLeft - ball.offsetWidth/2))
          &&
          (ball.offsetLeft < (brick.offsetLeft + brick.offsetWidth - ball.offsetWidth/2))
          &&
          (ball.offsetTop < (brick.offsetTop + brick.offsetHeight))
          &&
          (ball.offsetTop > (brick.offsetTop - brick.offsetHeight))
        ) {  // 底部碰撞 或者 顶部碰撞
          // 碰撞发生,砖块:消失,小球:反弹
          console.log("碰撞发生,砖块消失,小球反弹.....")
          speedY = -speedY // 垂直速度取反
          _box.removeChild(brick)
        } else if(
            //offset  抵消
        
          (ball.offsetTop > (brick.offsetTop - ball.offsetHeight/2))
          &&
          (ball.offsetTop < (brick.offsetTop + brick.offsetHeight - ball.offsetHeight/2))
          &&
          (ball.offsetLeft > (brick.offsetLeft - ball.offsetWidth))
          &&
          (ball.offsetLeft < (brick.offsetLeft + brick.offsetWidth))
        ) { 
            // 左侧碰撞 或者 右侧碰撞
          speedX = -speedX
          _box.removeChild(brick)
          boom()
        }

      }

10.音效处理

当小球和砖块发生碰撞时
创建 audio 标签
设置 src 属性,添加音效文件
不设置 autoplay=true 自动播放
碰撞时调用 audio.play() 播放音效即可

代码如下:

     // 音效处理 
      var _audio = document.createElement("audio") 
      _audio.src = "./img/y993.wav"
      //  _audio.autoplay = true 
       document.appendChild(_audio) 

       function boom() { 
       _audio.play() 
    }

整体代码如下:

<!DOCTYPE html>
<html lang="zh">
  <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>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      html,
      body {
        background-color: aliceblue;
      }
      h2 {
        text-align: center;
        margin: 20px auto;
      }
      #box {
        background-color: white;
        width: 1000px;
        height: 500px;
        box-shadow: 0 0 3px darkcyan;
        margin: 20px auto;
        position: relative;
      }

      P {
        display: block;
        width: 100px;
        /* 砖块样式 */
        height: 40px;
        position: absolute;
        box-shadow: -2px -3px -6px black;
      }
      #baffle {
        position: absolute;
        width: 200px;
        height: 16px;
        border-radius: 8px;
        background-color: brown;
        left: 454px;
        top: 484px;
      }
      #ball {
        z-index: 99;
        width: 30px;
        height: 30px;
        background: rgb(117, 85, 74);
        box-shadow: #888 2px 2px 3px;
        position: absolute;
        top: 454px;
        left: 534px;
        border-radius: 50%;
      }
    </style>
  </head>
  <body>
    <h2>打砖块</h2>
    <div id="box">
      <!-- 小球 -->
      <div id="ball"></div>
      <!-- 挡板 -->
      <div id="baffle"></div>
    </div>

    <script>
           // 让js代码在网页加载后执行
      window.onload = function () {
        //获取场景对象

        var _box = document.querySelector("#box");
         // ----------------------- 砖块处理部分
        //定义行数
        var rows = 3;
        //计算一行放多少砖块
        var cols = Math.floor(_box.offsetWidth / 100);

        //声明一个保存砖数的数组
        var brickArrs = []
        //循环 创建砖块
        for (var i = 0; i < rows; i++) {
          //循环创建多行

          for (var j = 0; j < cols; j++) {
            //循环创建一行中的多个砖块

            //创建砖块 p 标签
            var _p = document.createElement("p");
            _p.style.backgroundColor =
              "#" + Math.random().toString(16).substr(2, 6);

            //p 标签定位;位置
            _p.style.left = j * 100 + "px";
            _p.style.top = i * 40 + "px";

            //将砖块添加到场景中
            _box.appendChild(_p);

            //将砖块保存到数组中
            brickArrs.push(_p)
          }
        }
        
        //-----------挡板运动
        var _baffle = document.querySelector("#baffle")
        var _speed = 20

        document.onkeydown = function(e) {
              //获取事件对象
              var e = e || window.event

              //判断用户按下的按键
            var keyCode = e.keyCode

            //用户按下,控制挡板运动
            switch(keyCode) {
                case 37:
                    console.log("向左移动")
                    _baffle.style.left = _baffle.offsetLeft - _speed + "px"
                    break
                case 39:
                    console.log("向右移动")
                    _baffle.style.left = _baffle.offsetLeft + _speed + "px"
                    break
            }
            //挡板边界判断,挡板不能超出边界
            if(_baffle.offsetLeft < 0) {
                _baffle.style.left = 0
            }else if(_baffle.offsetLeft >= (_box.offsetWidth - _baffle.offsetWidth)){
                _baffle.style.left = (_box.offsetWidth - _baffle.offsetWidth) + "px"
            }
        }

        //----------小球运动
        var _ball = document.querySelector("#ball")
        var speedX = 3 //垂直速度
        var speedY = -5 //水平速度
       // ballInterval   全部间隔
       //setInterval  设置间隔
        var ballInterval = setInterval(function () {
          //小球运动起来
        _ball.style.left = _ball.offsetLeft + speedX + "px"
        _ball.style.top = _ball.offsetTop + speedY + "px"

        //边界判断
        if(_ball.offsetLeft < 0 ) {//左边界
           speedX = 3
        }else if(_ball.offsetLeft > (_box.offsetWidth - _ball.offsetWidth)) {
            speedX = -3
        }

        if(_ball.offsetTop < 0 ) { //上边界
           speedY = 5
        } else if(
           ( _ball.offsetLeft >= (_baffle.offsetLeft - _ball.offsetWidth/2))
            &&
            (_ball.offsetLeft <= (_baffle.offsetLeft + _baffle.offsetWidth - _ball.offsetWidth/2))
            &&
            (_ball.offsetTop >= (_baffle.offsetTop -_ball.offsetHeight))
            ) { // 碰到挡板
                speedY = -5

            }else if(_ball.offsetTop > (_box.offsetHeight - _ball.offsetHeight)){
                clearInterval(ballInterval)// clearInterval 清除间隔
                alert("你漏球了,结束") //弹窗 阻止代码执行    计时器仍然执行 
                location.reload()//重新加载当前位置  刷新网页
            }
            

        //判断小球是否和砖块发生碰撞
        for(var x = 0; x < brickArrs.length; x++) {
            //获取一个砖块
            var brick = brickArrs[x]
            //碰撞检测
            collide(brick, _ball)
        }

        }, 20)
       
        //--------------------- 碰撞检测:小球、砖块
         // brick :砖块
         // ball:小球
        function collide(brick, ball) {
        console.log("--------------------------------------")
        // console.log(brick.offsetLeft, brick.offsetTop, brick.offsetWidth, brick.offsetHeight, "砖块")
        // console.log(ball.offsetLeft, ball.offsetTop, ball.offsetWidth, ball.offsetHeight, "小球")
        console.log("--------------------------------------")
        // 底部碰撞、左侧碰撞、顶部碰撞、右侧碰撞
        if(
             //offset  抵消
          (ball.offsetLeft > (brick.offsetLeft - ball.offsetWidth/2))
          &&
          (ball.offsetLeft < (brick.offsetLeft + brick.offsetWidth - ball.offsetWidth/2))
          &&
          (ball.offsetTop < (brick.offsetTop + brick.offsetHeight))
          &&
          (ball.offsetTop > (brick.offsetTop - brick.offsetHeight))
        ) {  // 底部碰撞 或者 顶部碰撞
          // 碰撞发生,砖块:消失,小球:反弹
          console.log("碰撞发生,砖块消失,小球反弹.....")
          speedY = -speedY // 垂直速度取反
          _box.removeChild(brick)
        } else if(
            //offset  抵消
        
          (ball.offsetTop > (brick.offsetTop - ball.offsetHeight/2))
          &&
          (ball.offsetTop < (brick.offsetTop + brick.offsetHeight - ball.offsetHeight/2))
          &&
          (ball.offsetLeft > (brick.offsetLeft - ball.offsetWidth))
          &&
          (ball.offsetLeft < (brick.offsetLeft + brick.offsetWidth))
        ) { 
            // 左侧碰撞 或者 右侧碰撞
          speedX = -speedX
          _box.removeChild(brick)
          boom()
        }

      }
      // 音效处理 
      var _audio = document.createElement("audio") 
      _audio.src = "./img/y993.wav"
      //  _audio.autoplay = true 
       document.appendChild(_audio) 

       function boom() { 
       _audio.play() 
    }
      };
    </script>
  </body>
</html>

网页效果展现如下图:
JS 实现小游戏 打砖块_第8张图片

你可能感兴趣的:(javascript,css,css3,前端,html)