首页 > 解决方案 > 简单的 HTML/JS 碰撞检测不起作用

问题描述

第一次发帖,如果我的礼节不好,我很抱歉。我正在尝试设置一个简单的 HTML/JavaScript 页面,在具有一维运动的两个 2D 对象之间进行碰撞检测,但我不知道为什么它没有做任何事情。

包含所有商品的代码片段:

var field = document.getElementById("battlefield");
var allies = document.getElementsByClassName("ally");
var enemies = document.getElementsByClassName("enemy");
var fighters = document.getElementsByClassName("fighter");

var c1speed = 3; //Speed of fighters

function spawna1() { //spawns a blue fighter
  node = document.createElement("div");
  node.classList.add("fighter", "ally", "c1");
  field.appendChild(node);
}

spawna1();

function spawne1() { //spawns a red fighter
  node = document.createElement("div");
  node.classList.add("fighter", "enemy", "e1");
  field.appendChild(node);
}

spawne1();

var movea = setInterval(function() {
  for (i = 0; i < allies.length; i++) { //Move blue
    allies[i].style.left = (allies[i].offsetLeft + c1speed) + "px";
    if (allies[i].offsetLeft > window.innerWidth + 200) {
      allies[i].remove();
    }
  }
  for (i = 0; i < enemies.length; i++) { //Move red
    enemies[i].style.left = (enemies[i].offsetLeft - c1speed) + "px";
    if (enemies[i].offsetLeft < -200) {
      enemies[i].remove();
    }
  }
  for (i = 0; i < fighters.length; i++) { //Collision detection, theoretically
    for (j = i + 1; j < fighters.length; j++) {
      if (fighters[i].offsetLeft < fighters[j].offsetLeft + fighters[j].width || //If i=red and j=blue
        fighters[i].offsetLeft + fighters[i].width > fighters[j].offsetLeft) { //or if i=blue and j=red
        fighters[i].remove(); //Remove the fighters when they collide
        fighters[j].remove();
      }
    }
  }
}, 20);
html,
body,
#page-container {
  margin: 0;
  padding: 0;
  overflow-x: hidden;
}

#page-container {
  width: 100%;
  height: 100%;
  display: block;
  position: absolute;
  background-color: #c5c5c5;
}

#game {
  width: 100%;
  height: 100%;
  min-height: 100%;
  display: block;
  z-index: 99;
}

#battlefield {
  width: 100%;
  height: 67%;
}

#lower {
  width: 100%;
  height: 33%;
  background-color: #000000;
}

.ally {
  position: absolute;
  left: 0px;
  bottom: 33%;
  background-color: blue;
  width: 3em;
  height: 3em;
}

.enemy {
  position: absolute;
  left: 600px;
  bottom: 33%;
  background-color: red;
  width: 3em;
  height: 3em;
}
<div id="page-container">
  <div id="game">
    <div id="battlefield">
    </div>
    <div id="lower">
      <button onclick="spawna1();spawne1()">SPAWN MORE</button>
    </div>
  </div>
</div>

蓝色的“战斗机”应该向右移动,而红色的“战斗机”向左移动。碰撞时,它们都应该消失。这是我所拥有的基础知识(我强烈建议运行代码段):

var fighters = document.getElementsByClassName("fighter");

function spawna1() {
    node = document.createElement("div");
    node.classList.add("fighter", "ally", "c1");
    field.appendChild(node);
}

spawna1();

function spawne1() {
    node = document.createElement("div");
    node.classList.add("fighter", "enemy", "e1");
    field.appendChild(node);
}

spawne1();

var movea = setInterval(function() {
    for (i = 0; i < fighters.length; i++) {     //Hit detection formula
        for (j = i + 1; j < fighters.length; j++) {
            if (fighters[i].offsetLeft < fighters[j].offsetLeft + fighters[j].width ||
            fighters[i].offsetLeft + fighters[i].width > fighters[j].offsetLeft) {
                fighters[i].remove();    //remove fighters on collide
                fighters[j].remove();
            }
        }
    }
}, 20);

我非常感谢您的时间和耐心。感谢:D

标签: javascripthtml

解决方案


我想出了一个解决方案!

由于蓝色和红色对象在被调用时分别被分配了一个allyenemyspawn(),我只需要更改碰撞检测以allies[i]检查enemies[j]. 这是片段:

var field = document.getElementById("battlefield");
var allies = document.getElementsByClassName("ally");
var enemies = document.getElementsByClassName("enemy");
var fighters = document.getElementsByClassName("fighter");
var c10 = document.getElementById("c10");
var c1o = 1;
var c1 = {
  "a": 1,
  "d": 1,
  "s": 3,
  "o": 1,
  "si": 1500,
  "os": c1o
};
var ce1 = {
  "a": 1,
  "d": 1,
  "s": 3,
  "o": 1,
  "si": 1500,
  "os": c1o
};

function spawna1() {
  var spawna1int = setTimeout(function() {
    node = document.createElement("div");
    node.classList.add("fighter", "ally", "c1");
    field.appendChild(node);
    spawna1();
  }, (c1.si / c1.o));
}

spawna1();

function spawne1() {
  var spawna1int = setTimeout(function() {
    node = document.createElement("div");
    node.classList.add("fighter", "enemy", "c1");
    field.appendChild(node);
    spawne1();
  }, (ce1.si / ce1.o));
}

spawne1();

var movea = setInterval(function() {
  for (i = 0; i < allies.length; i++) { //Move A1
    allies[i].style.left = (allies[i].offsetLeft + c1.s) + "px";
    if (allies[i].offsetLeft > window.innerWidth + 200) {
      allies[i].remove(); //Remove when off screen
    }
  }
  for (i = 0; i < enemies.length; i++) { //Move E1
    enemies[i].style.left = (enemies[i].offsetLeft - ce1.s) + "px";
    if (enemies[i].offsetLeft < -200) {
      enemies[i].remove(); //Remove when off screen
    }
  }
  for (i = 0; i < allies.length; i++) { //Hit detection, I hope
    for (j = 0; j < enemies.length; j++) {
      if (allies[i].offsetLeft < enemies[j].offsetLeft + enemies[j].offsetWidth &&
        allies[i].offsetLeft + allies[i].offsetWidth > enemies[j].offsetLeft) {
        //What should happen when they collide???
        if (allies[i].classList[1] == enemies[j].classList[1]) { //Friendly fire off
          return;
        }
        if (eval(allies[i].classList[2]).a > eval(enemies[j].classList[2]).d) { //if I attack is higher than J defense, kill J
          enemies[j].remove();
        }
        if (eval(enemies[j].classList[2]).a > eval(enemies[j].classList[2]).d) { //if J attack is higher than I defense, kill I
          allies[i].remove();
        }
        if (eval(enemies[j].classList[2]).a == eval(enemies[j].classList[2]).a &&
          eval(enemies[j].classList[2]).d == eval(enemies[j].classList[2]).d) { //if I and J are equal, kill both
          allies[i].remove();
          enemies[j].remove();
        }
      }
    }
  }
}, 20);
html,
body,
#page-container {
  margin: 0;
  padding: 0;
  overflow-x: hidden;
}

#page-container {
  width: 100%;
  height: 100%;
  display: block;
  position: absolute;
  background-color: #c5c5c5;
}

#game {
  width: 100%;
  height: 100%;
  min-height: 100%;
  display: block;
  z-index: 99;
}

#battlefield {
  width: 100%;
  height: 67%;
}

#lower {
  width: 100%;
  height: 33%;
  background-color: #000000;
}

.ally {
  position: absolute;
  left: -150px;
  bottom: 33%;
  background-color: blue;
}

.enemy {
  position: absolute;
  left: 600px;
  bottom: 33%;
  background-color: red;
}

.c1 {
  width: 2em;
  height: 2.5em;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Welcome to Valhalla!</title>
  <meta name="author" content="beanamonster">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link rel="stylesheet" type="text/css" href="halla.css">
</head>

<body>
  <div id="page-container">
    <div id="game">
      <div id="battlefield">

      </div>
      <div id="lower">

      </div>
    </div>
  </div>
  <script src="halla.js"></script>
</body>

</html>

我在一夜之间添加了很多,所以这可能不再有意义了。但本质上,我们将红色对象分配给一个类,将蓝色对象分配一个不同的类。循环for通过蓝调,而嵌套for根据各自的类检查红调。


推荐阅读