javascript - 如何检查一个div是否每秒与另一个div重叠?
问题描述
我正在制作一个关于移动玩家躲避子弹的快速游戏,但我遇到了如何检测是否有任何子弹与玩家碰撞的问题。在游戏引擎中,通常只存在用于两个对象碰撞的事件侦听器,因为我还没有找到类似 webb 开发的东西,我想我可以使用无限循环来检查每个子弹是否与玩家发生碰撞。
我不能做一个while (true)
循环,因为它只是崩溃。我试图在每个子弹的生成函数中设置一个间隔,但我不知道如何在子弹消失后清除间隔。而且我还尝试只创建一个间隔,此时将循环遍历现有的子弹并检查子弹是否正在碰撞,但由于某种原因,我收到了这个错误:Uncaught TypeError: bullets.forEach is not a function
这是代码:
function checkOverlap(){
let bullets = document.getElementsByClassName("bullet");
if (bullets.length > 0){
bullets.forEach(bullet => {
let overlap = !(bullet.right < player.left ||
bullet.left > player.right ||
bullet.bottom < player.top ||
bullet.top > player.bottom)
if (overlap){
console.log("overlap");
}
});
}
}
setInterval(checkOverlap, 1000);
我也想知道这是否甚至可以通过这种方式检测重叠。由于我使用transition
和left, top, right, down
css 属性来移动我的子弹,它会检测到还是我需要使用其他东西?
解决方案
您无法访问forEach
,因为document.getElementsByClassName
它不返回 an Array
- 它返回的 aNodeList
行为有点像 an Array
,但在其他方面有所不同 - 因为它的原型没有forEach
方法。
Array
您可以通过执行以下操作轻松转换为:
let bullets = [ ...document.getElementsByClassName('bullet') ];
就碰撞而言,我建议您使用getBoundingClientRect
(我经常将其拼写混淆为getClientBoundingRect
,现在我提醒自己B
先于C
:D)。这将返回一个 html 元素的绝对几何图形,并考虑所有因素:
let doCollide = (player, bullet) => {
let playerBound = player.getBoundingClientRect();
let bulletBound = bullet.getBoundingClientRect();
// (px, py) and (bx, by) represent the center of the player and bullet
let px = playerBound.left + playerBound.width * 0.5;
let py = playerBound.top + playerBound.height * 0.5;
let bx = bulletBound.left + bulletBound.width * 0.5;
let by = bulletBound.top + bulletBound.height * 0.5;
let wOff = (playerBound.width + bulletBound.width) * 0.5;
let hOff = (playerBound.height + bulletBound.height) * 0.5;
// Collision occurs when bullet and player are separated on neither x nor y axes
return Math.abs(px - bx) < wOff && Math.abs(py - by) < hOff;
}
let player = document.getElementsByClassName('player')[0];
let bullet = document.getElementsByClassName('bullet')[0];
let testFn = () => {
player.style.left = `${Math.floor(Math.random() * 300)}px`;
player.style.top = `${Math.floor(Math.random() * 150)}px`;
bullet.style.left = `${Math.floor(Math.random() * 300)}px`;
bullet.style.top = `${Math.floor(Math.random() * 150)}px`;
if (doCollide(player, bullet)) {
player.classList.add('coll');
bullet.classList.add('coll');
} else {
player.classList.remove('coll');
bullet.classList.remove('coll');
}
};
setInterval(testFn, 1500);
testFn();
html, body { position: relative; width: 100%; height: 100%; overflow: hidden; padding: 0; margin: 0; }
.player, .bullet { position: absolute; }
.player { width: 150px; height: 150px; box-shadow: inset 0 0 0 4px rgba(0, 150, 0, 1); }
.bullet { width: 60px; height: 90px; box-shadow: inset 0 0 0 4px rgba(0, 210, 0, 1); }
.player.coll { box-shadow: inset 0 0 0 4px rgba(200, 0, 0, 1); }
.bullet.coll { box-shadow: inset 0 0 0 4px rgba(255, 0, 0, 1); }
<div class="player"></div>
<div class="bullet"></div>
推荐阅读
- python - Pandas 中 Excel SUM 的替代方案
- sql - 在存储过程 Round() 函数中将 varchar(255) 转换为浮点数?
- html - 打开垫子扩展面板正在移动对面的柱子,如何保持静止?
- jquery - 我的 Woocommerce 网站上出现 Jquery 错误
- mysql - MYSQL 创建“复杂”视图
- r - 通过 FlexTable 列表应用条件文本修改
- pyspark - 如何以将“日期”分组到不同列而不是将所有内容组合在同一列中的方式进行联合
- javascript - 搜索 API 上的重新渲染过多
- powerbi - 如何区分 PowerBI Measure 中的 BLANK 和 0?
- oracle - 我收到此错误:ORA-12560: TNS:protocol adapter error in window 10 while coonecting to sql plus