irpas技术客

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

未知 1900

打砖块游戏demo 游戏试玩:😀

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

源码附注释见末尾 🌈


布局创建: 🌞

地图container放置砖块的板块brickBox小球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>

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


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #学弟乐哉 #附思路注释源码 #检测小球碰撞 #源码附注释见末尾 #布局创建