简体   繁体   English

检测 2 个 div 与 JavaScript 的冲突

[英]Detecting the collision of 2 divs with JavaScript

I'm making a simple Space Invaders Clone in Web and ran into an issue.我在 Web 中制作了一个简单的 Space Invaders Clone 并遇到了一个问题。 The code works well so far with the exception of the collision system.到目前为止,该代码运行良好,但碰撞系统除外。 I need to destroy an enemy every time that the player's bullet hits it.每次玩家的子弹击中敌人时,我都需要消灭它。 In order to make it, I'm grabbing the x and y coordinates of both the enemies' div and the bullet's div.为了做到这一点,我抓住了敌人 div 和子弹 div 的 x 和 y 坐标。 The issue appears on the values comparison: apparently getBoundingClientRect() grabs the x and y coordinates from within the element excluding its real size.问题出现在值比较上:显然getBoundingClientRect()从元素内获取 x 和 y 坐标,不包括其实际大小。 Hence, according to my code, only when the bullet is perfectly inside the enemy that things would trigger.因此,根据我的代码,只有当子弹完全在敌人体内时才会触发。 Is there a better way of doing it?有更好的方法吗? How so?怎么会这样?

Thanks in advance.提前致谢。

 const shoot = (x) => { //Creates bullet const main = document.getElementById("main"); const div_bullet = document.createElement("div"); //Appends child main.appendChild(div_bullet); //Sets position div_bullet.style.top = "340px"; div_bullet.style.left = x + "px"; //Gives it a class div_bullet.classList.add("div_bullet"); div_bullet.setAttribute("id", "bullet"); //Deletes bullet setTimeout(() => { div_bullet.remove(); }, 1000); }; const load_game = () => { //Adding movement to the spaceship const space_ship = document.getElementById("space_ship"); let x = 375; window.addEventListener("keydown", (e) => { switch (e.key) { case "ArrowLeft": if (x <= 15) break; x = x - 10; space_ship.style.left = x + "px"; break; case "ArrowRight": if (x >= 725) break; x = x + 10; space_ship.style.left = x + "px"; break; case "ArrowUp": if (document.getElementsByClassName("div_bullet").length === 0) shoot(x + 20); break; default: break; } }); }; const collision_system = () => { setInterval(() => { //Checks if any enemy was hit const e1 = document.getElementById("e1"); const e2 = document.getElementById("e2"); const e3 = document.getElementById("e3"); const e4 = document.getElementById("e4"); const e5 = document.getElementById("e5"); const enemies_position = [{ x: e1.getBoundingClientRect().x, y: e1.getBoundingClientRect().y }, { x: e2.getBoundingClientRect().x, y: e2.getBoundingClientRect().y }, { x: e3.getBoundingClientRect().x, y: e3.getBoundingClientRect().y }, { x: e4.getBoundingClientRect().x, y: e4.getBoundingClientRect().y }, { x: e5.getBoundingClientRect().x, y: e5.getBoundingClientRect().y }, ]; if (document.getElementById("bullet")) { const x_bullet = document .getElementById("bullet") .getBoundingClientRect().x; const y_bullet = document .getElementById("bullet") .getBoundingClientRect().y; console.log( "X: " + enemies_position[0].x + "Y: " + enemies_position[0].y ); console.log("X bullet: " + x_bullet + "Y bullet : " + y_bullet); for (let i = 0; i < 5; i++) { if ( enemies_position[i].x === x_bullet && enemies_position[i].y === y_bullet ) alert("Shoot!"); } } }, 10); }; document.addEventListener("DOMContentLoaded", () => { load_game(); collision_system(); });
 * { padding: 0px; margin: 0px; } body { background-color: black; width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; } .main { width: 800px; height: 500px; border: 2px white solid; border-radius: 10px; } @keyframes enemies_move { from { left: 80px; } to { left: -80px; } } .enemies { margin-top: 20px; position: fixed; width: 800px; height: 50px; display: flex; justify-content: space-evenly; } .enemies div { position: relative; width: 50px; height: 50px; background-color: orange; animation: enemies_move 4s alternate infinite; } .barriers { width: 800px; height: 20px; position: fixed; top: 460px; display: flex; justify-content: space-evenly; } .barriers div { width: 100px; height: 20px; background-color: white; } .space_ship { width: 50px; height: 50px; border: 2px white solid; position: relative; top: 440px; left: 375px; } @keyframes shoot_bullet { from { top: 340px; } to { top: -50px; } } .div_bullet { left: 17px; width: 15px; height: 40px; background-color: white; position: relative; animation: shoot_bullet 1s; }
 <div id="main" class="main"> <div class="enemies"> <div id="e1"></div> <div id="e2"></div> <div id="e3"></div> <div id="e4"></div> <div id="e5"></div> </div> <div class="barriers"> <div></div> <div></div> <div></div> <div></div> </div> <div id="space_ship" class="space_ship"></div> </div>

The problem in your code is that you are using only the x and y of the bullet and enemy to check for collisions.您的代码中的问题是您仅使用子弹和敌人的xy来检查碰撞。 You need to use the width and height of both items to check if they collide.您需要使用两个项目的宽度和高度来检查它们是否发生碰撞。

The checks needed to see if two rects collide is查看两个矩形是否碰撞所需的检查是

function rectCollision(rectA, rectB) {
  return (
    rectA.x < rectB.x + rectB.width &&
    rectA.x + rectA.width > rectB.x &&
    rectA.y < rectB.y + rectB.height &&
    rectA.height + rectA.y > rectB.y
  );
}

And using this in your code makes it work在你的代码中使用它可以让它工作

 const shoot = (x) => { //Creates bullet const main = document.getElementById("main"); const div_bullet = document.createElement("div"); //Appends child main.appendChild(div_bullet); //Sets position div_bullet.style.top = "340px"; div_bullet.style.left = x + "px"; //Gives it a class div_bullet.classList.add("div_bullet"); div_bullet.setAttribute("id", "bullet"); //Deletes bullet setTimeout(() => { div_bullet.remove(); }, 1000); }; const load_game = () => { //Adding movement to the spaceship const space_ship = document.getElementById("space_ship"); let x = 375; window.addEventListener("keydown", (e) => { switch (e.key) { case "ArrowLeft": if (x <= 15) break; x = x - 10; space_ship.style.left = x + "px"; break; case "ArrowRight": if (x >= 725) break; x = x + 10; space_ship.style.left = x + "px"; break; case "ArrowUp": if (document.getElementsByClassName("div_bullet").length === 0) shoot(x + 20); break; default: break; } }); }; const collision_system = () => { setInterval(() => { //Checks if any enemy was hit const e1 = document.getElementById("e1"); const e2 = document.getElementById("e2"); const e3 = document.getElementById("e3"); const e4 = document.getElementById("e4"); const e5 = document.getElementById("e5"); const enemies_position = [ e1.getBoundingClientRect(), e2.getBoundingClientRect(), e3.getBoundingClientRect(), e4.getBoundingClientRect(), e5.getBoundingClientRect(), ]; if (document.getElementById("bullet")) { const bullet = document .getElementById("bullet") .getBoundingClientRect(); console.log( "X: " + enemies_position[0].x + "Y: " + enemies_position[0].y ); console.log("X bullet: " + bullet.x + "Y bullet : " + bullet.y); for (let i = 0; i < 5; i++) { if ( rectCollision(enemies_position[i], bullet) ) alert("Shoot!"); } } }, 10); }; function rectCollision(rectA, rectB) { return (rectA.x < rectB.x + rectB.width && rectA.x + rectA.width > rectB.x && rectA.y < rectB.y + rectB.height && rectA.height + rectA.y > rectB.y) } document.addEventListener("DOMContentLoaded", () => { load_game(); collision_system(); });
 * { padding: 0px; margin: 0px; } body { background-color: black; width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; } .main { width: 800px; height: 500px; border: 2px white solid; border-radius: 10px; } @keyframes enemies_move { from { left: 80px; } to { left: -80px; } } .enemies { margin-top: 20px; position: fixed; width: 800px; height: 50px; display: flex; justify-content: space-evenly; } .enemies div { position: relative; width: 50px; height: 50px; background-color: orange; animation: enemies_move 4s alternate infinite; } .barriers { width: 800px; height: 20px; position: fixed; top: 460px; display: flex; justify-content: space-evenly; } .barriers div { width: 100px; height: 20px; background-color: white; } .space_ship { width: 50px; height: 50px; border: 2px white solid; position: relative; top: 440px; left: 375px; } @keyframes shoot_bullet { from { top: 340px; } to { top: -50px; } } .div_bullet { left: 17px; width: 15px; height: 40px; background-color: white; position: relative; animation: shoot_bullet 1s; }
 <div id="main" class="main"> <div class="enemies"> <div id="e1"></div> <div id="e2"></div> <div id="e3"></div> <div id="e4"></div> <div id="e5"></div> </div> <div class="barriers"> <div></div> <div></div> <div></div> <div></div> </div> <div id="space_ship" class="space_ship"></div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM