手把手教学弟用js写的打砖块游戏,学弟乐哉~ 附(思路注释+源码)

Posted 贪吃ღ大魔王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手教学弟用js写的打砖块游戏,学弟乐哉~ 附(思路注释+源码)相关的知识,希望对你有一定的参考价值。

打砖块游戏demo


游戏试玩:😀



思路详解:😉
  1. 创建地图板块,上半部分是放置砖块盒子,砖块选择动态创建;底部放置小球和滑块;设置他们相应的样式
  2. 根据brickBox大小,规定砖块大小,计算砖块数量,根据砖块数量动态创建
  3. 滑块跟随鼠标进行移动
  4. 滑块点击事件,小球移动。检测小球碰撞。

源码附注释见末尾 🌈




布局创建: 🌞

  1. 地图container
  2. 放置砖块的板块brickBox
  3. 小球ball,滑块slider

实现效果:




动态创建砖块: 🤸

定义砖块大小:

放置砖块盒子brickBox宽度500px,一行放置5个砖块,那么砖块的宽度是100px;高度雷同,则高度就是30px。

 var brickWidth = 100;
 var brickHeight = 30;

计算创建砖块的列数:

brickBox的宽度 / 单个砖块的宽度 = 列数

var brickColNum = brickBox.clientWidth / brickWidth

计算砖块数量:

整体brickBox面积 / 单个砖块面积 = 砖块数量

 var brickNum = brickBox.clientWidth * brickBox.clientHeight / (brickWidth * brickHeight)

根据砖块数量动态创建:

循环创建砖块,设置砖块的位置,颜色; 这里需要注意的是砖块定位的 left 和 top 需要单独进行计算。

一共创建的是100个砖块,循环创建,那么每个砖块对应的下标就是从0 - 99

规律:

left : 如果是最左边一列,下标为0,5,10的砖块,他们的下标 i % 5 为 0 ; 第二列,下标为 1,6,11的砖块,下标 i % 5 为 1;第三列就是 i % 5 为 2;依次类推…

则: left

left: (i % brickColNum) * brickWidth + 'px'

top : 如果第一行,下标为 0,1,2,3,4的砖块,i / 5 为 0;第二行,下标为5,6,7,8,9的砖块, i / 5 为 1;依次类推…

则: top

top: parseInt(i / brickColNum) * brickHeight + 'px',

计算出left 和top 就可以动态创建了,砖块颜色选择随机,进行动态创建

    for (var i = 0; i < brickNum; i++) 
        var div = document.createElement('div')
        setStyle(div, 
            width: brickWidth + "px",
            height: brickHeight + "px",
            backgroundColor: getColor(true),
            position: 'absolute',
            top: parseInt(i / brickColNum) * brickHeight + 'px',
            left: (i % brickColNum) * brickWidth + 'px'
        )
        brickBox.appendChild(div)
    

封装的随机颜色函数:

function getColor(hex = true) 
        if (hex) 
            var color = '#'
            for (var i = 0; i < 3; i++) 
                var rgb = getRandom(256).toString(16);
                rgb = rgb.length === 1 ? '0' + rgb : rgb;
                color += rgb
            
            return color;
        
        return `rgb($getRandom(256),$getRandom(256),$getRandom(256))`
    

实现效果:




让滑块跟随鼠标移动: 🎯

移入滑块,让滑块跟随鼠标移动,

注意:地图边框的 1px 也需要减掉

    slider.onmouseover = function () 
        slider.onmousemove = function (e) 
            var e = e || window.event;
            var x = e.pageX;
            var l = x - container.offsetLeft - 1 - slider.offsetWidth / 2
            if (l < 0) 
                l = 0
            
            if (l > container.clientWidth - slider.offsetWidth) 
                l = container.clientWidth - slider.offsetWidth
            
            slider.style.left = l + "px"
        
    

实现效果:





点击滑块让小球运动:

定义 left 和 top 方向的速度,都设置为 1 ,注意这里两个速度需要分开设置,因为情况会有所不同。
点击滑块,小球开始移动,设置小球的 left 和 top 增加,并将 left 和 top 给小球,放在定时器里。

 timer = setInterval(function () 
            let left = ball.offsetLeft;
            let top = ball.offsetTop
            left += speedX
            top += speedY
            ball.style.left = left + "px"
            ball.style.top = top + "px"
        , 5)

检测小球和滑块碰撞,如果碰撞,小球向反方向移动

 if (boom(slider, ball)) 
                speedY = -speedY
            

检测小球和地图边框相撞

if (left <= 0 || left >= container.clientWidth - ball.offsetWidth) 
                speedX = -speedX
            
            if (top <= 0) 
                speedY = -speedY
            

检测小球和砖块碰撞

for (let i = 0; i < brickBox.children.length; i++) 
                if (boom(brickBox.children[i], ball)) 
                    speedY = -speedY
                    brickBox.removeChild(brickBox.children[i])
                    break;
                
            

如果小球到达地图下边框,也就是滑块没有接住小球,GAME OVER

if (top >= container.clientHeight - ball.offsetHeight) 
                clearInterval(timer)
                alert('GAME OVER')
            

封装一个检测碰撞的函数:

因为碰撞的方式太多,不好写。这里可以反过来思考,判断不碰撞的方式,那么有四种可能。

function boom(node1, node2) 
        if (node1.offsetLeft + node1.offsetWidth < node2.offsetLeft || node1.offsetTop + node1.offsetHeight < node2.offsetTop || node2.offsetLeft + node2.offsetWidth < node1.offsetLeft || node2.offsetTop + node2.offsetHeight < node1.offsetTop) 
            return false;
         else 
            return true;
        
    

实现效果:




源码: 🤪

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>document</title>
    <style>
        .container 
            width: 500px;
            height: 500px;
            border: 1px solid #000;
            margin: auto;
            position: relative;
        

        .brickBox 
            width: 500px;
            height: 300px;
            /* background-color: yellowgreen; */
            position: absolute;
            left: 0;
            top: 0;
        

        .ball 
            width: 30px;
            height: 30px;
            background-color: red;
            border-radius: 50%;
            position: absolute;
            bottom: 30px;
            left: 235px;
            /* margin-left:-15px; */
        

        .slider 
            width: 150px;
            height: 30px;
            background-color: #00f;
            position: absolute;
            /* left:50%; */
            left: 175px;
            /* margin-left:-75px; */
            bottom: 0;
            cursor: pointer;
        
    </style>
</head>

<body>
    <div class="container">
        <div class="brickBox"></div>
        <div class="ball"></div>
        <div class="slider"></div>
    </div>
</body>
<script>
    // 获取所有标签
    var container = document.querySelector('.container')
    var brickBox = container.querySelector('.brickBox')
    var ball = container.querySelector('.ball')
    var slider = container.querySelector('.slider')
    // 动态创建砖块
    // 定义砖块大小
    var brickWidth = 100;
    var brickHeight = 30;
    // 计算砖块数量
    var brickNum = brickBox.clientWidth * brickBox.clientHeight / (brickWidth * brickHeight)
    // console.log(brickNum);
    var brickColNum = brickBox.clientWidth / brickWidth
    // 根据数量去创建
    for (var i = 0; i < brickNum; i++) 
        var div = document.createElement('div')
        setStyle(div, 
            width: brickWidth + "px",
            height: brickHeight + "px",
            backgroundColor: getColor(true),
            position: 'absolute',
            top: parseInt(i / brickColNum) * brickHeight + 'px',
            left: (i % brickColNum) * brickWidth + 'px'
        )
        brickBox.appendChild(div)
    


    // 点击滑块让小球开始运动
    // 定义横向移动的值和纵向移动的值
    var speedX = 1;
    var speedY = 1;
    var timer;
    slider.onclick = function () 
        clearInterval(timer)
        timer = setInterval(function () 
            // 开始移动
            // 获取小球的left和top
            let left = ball.offsetLeft;
            let top = ball.offsetTop
            // 让left和top增加速度
            // 小球和滑块相撞
            if (boom(slider, ball)) 
                speedY = -speedY
            
            // 小球和大盒子相撞
            if (left <= 0 || left >= container.clientWidth - ball.offsetWidth) 
                speedX = -speedX
            
            if (top <= 0) 
                speedY = -speedY
            
            // 检测所有砖块和小球是否相撞
            for (let i = 0; i < brickBox.children.length; i++) 
                if (boom(brickBox.children[i], ball)) 
                    speedY = -speedY
                    brickBox.removeChild(brickBox.children[i])
                    break;
                
            
            // GAME OVER
            if (top >= container.clientHeight - ball.offsetHeight) 
                clearInterval(timer)
                alert('GAME OVER')
            
            left += speedX
            top += speedY
            // console.log(left,speedX);
            // 设置给小球的left和top
            ball.style.left = left + "px"
            ball.style.top = top + "px"
        , 5)
    
    // 让滑块跟着鼠标移动
    slider.onmouseover = function () 
        slider.onmousemove = function (e) 
            var e = e || window.event;
            var x = e.pageX;
            var l = x - container.offsetLeft - 1 - slider.offsetWidth / 2
            if (l < 0) 
                l = 0
            
            if (l > container.clientWidth - slider.offsetWidth) 
                l = container.clientWidth - slider.offsetWidth
            
            slider.style.left = l + "px"
        
    
    // 封装检测相撞的函数
    function boom(node1, node2) 
        // 不撞在一起的只有4中可能
        if (node1.offsetLeft + node1.offsetWidth < node2.offsetLeft || node1.offsetTop + node1.offsetHeight < node2.offsetTop || node2.offsetLeft + node2.offsetWidth < node1.offsetLeft || node2.offsetTop + node2.offsetHeight < node1.offsetTop) 
            return false;
         else 
            return true;
        
    
    // 封装获取随机颜色的函数
    function getColor(hex = true) 
        if (hex) 
            var color = '#'
            for (var i = 0; i < 3; i++) 
                var rgb = getRandom(256).toString(16);
                rgb = rgb.length === 1 ? '0' + rgb : rgb;
                color += rgb
            
            return color;
        
        return `rgb($getRandom(256),$getRandom(256),$getRandom(256))`
    
    // 封装设置样式的函数
    function setStyle(ele, styleObj) 
        for (var attr in styleObj) 
            ele.style[attr] = styleObj[attr]
        
    
    // 封装获取随机数的函数
    function getRandom(a, b = 0) 
        var max = Math.max(a, b);
        var min = Math.min(a, b)
        return Math.floor(Math.random() * (max - min)) + min
    
</script>

</html>



觉得博主写的不错的,可以收藏支持一波~ 😊



以上是关于手把手教学弟用js写的打砖块游戏,学弟乐哉~ 附(思路注释+源码)的主要内容,如果未能解决你的问题,请参考以下文章

自从教学弟学会了Python,他每天都爬一些好不正经的图片!

我用端午假期写了个贪吃蛇,学弟玩的不亦乐乎!附(思路注释+源码)

我用端午假期写了个贪吃蛇,学弟玩的不亦乐乎!附(思路注释+源码)

学姐手把手教我怎么写冒泡排序,我转身就教会了学妹,爽!

手把手教你完成第一个JS项目:用简单到极致的贪吃蛇游戏熟悉JS语法

手把手教你完成第一个JS项目:用简单到极致的贪吃蛇游戏熟悉JS语法