繁体   English   中英

如何检测圆形和矩形之间的碰撞?

[英]How to detect a collision between a circle and a rectangle?

有一个碰撞函数可以找到两个 div(圆形和矩形)的边界,第一个条件有效但其余条件无效,到目前为止我不知道我做错了什么。 基本上,这个想法是让圆圈不要超出矩形的边缘。

const $circle = document.getElementById("circle");
const $box = document.getElementById("box");
let mtop = 0;
let mleft = 0;
let boxTop  = 0;
let boxLeft  = 0;
let boxRight  = 0;
let boxBottom  = 0;
document.addEventListener("keydown", (e) =>{
   if(e.keyCode == "39") {
        mleft++;
        $circle.style.marginLeft = mleft +"px";
        colission();
    }  
    if(e.keyCode == "37"){
        mleft --;
        $circle.style.marginLeft = mleft +"px"
       // colission();
    }
    if(e.keyCode == "38"){
        mtop --;
        $circle.style.marginTop = mtop + "px";
        //colission();
    }
    if(e.keyCode == "40"){
        mtop ++;
        $circle.style.marginTop = mtop + "px";
        //colission();
    }
    e.preventDefault();
})
function colission(){
    let boxPos = $box.getBoundingClientRect();
    let boxTop  = boxPos.top;
    let boxLeft  = boxPos.left;
    let boxRight  = boxPos.right;
    let boxBottom  = boxPos.bottom;
     
    let circlePos = $circle.getBoundingClientRect();
    let circleTop = circlePos.top;
    let circleLeft = circlePos.left;
    let circleRight = circlePos.right;
    let circlebottom = circlePos.bottom;
    
    
    if(Math.round(circleRight) == Math.round(boxRight)){
         mleft = mleft - 2;
    }

    /*if(Math.round(circleLeft) == Math.round(boxLeft)){
        mleft = mleft - 2;
   }

    if(Math.round(circleTop) == Math.round(boxTop)){
        mtop = mtop -2;
   }

   if(Math.round(circlebottom) == Math.round(boxBottom)){
       mtop = mtop -2;
   }*/
}

这是您问题的解决方案, collision函数在collision返回true ,否则返回false 然后,您可以实现一些逻辑来防止发生碰撞时的最后一个用户操作(尝试使用键盘箭头进行演示):

 document.addEventListener('keydown', (function() { function collision(box, circle) { const { top: boxTop, left: boxLeft, right: boxRight, bottom: boxBottom, } = box.getBoundingClientRect(); const { top: circleTop, left: circleLeft, right: circleRight, bottom: circleBottom, } = circle.getBoundingClientRect(); const circleRadius = (circleBottom - circleTop ) / 2; const circleCenterX = (circleLeft + circleRight ) / 2; const circleCenterY = (circleTop + circleBottom ) / 2; /** * Distance between the center of the circle and the nearest point of * the rectangle (on the X axis) */ const deltaX = circleCenterX - Math.max(boxLeft, Math.min(circleCenterX, boxRight)); /** * Distance between the center of the circle and the nearest point of * the rectangle (on the Y axis) */ const deltaY = circleCenterY - Math.max(boxTop, Math.min(circleCenterY, boxBottom)); /** * Is the distance between the center of the circle and the nearest point * of the rectangle inferior to the circle radius ? */ return deltaX ** 2 + deltaY ** 2 < circleRadius ** 2; } const circle = document.getElementById('circle'); const rectangle = document.getElementById('rectangle'); let circleTop = 26; let circleLeft = 8; return function(e) { e.preventDefault(); if(e.keyCode === 37) { circleLeft -= 1; } if(e.keyCode === 38) { circleTop -= 1; } if(e.keyCode === 39) { circleLeft += 1; } if(e.keyCode === 40) { circleTop += 1; } circle.style.top = `${circleTop}px`; circle.style.left = `${circleLeft}px`; if (collision(rectangle, circle)) { rectangle.style['background-color'] = 'red'; circle.style['background-color'] = 'red'; } else { rectangle.style['background-color'] = 'blue'; circle.style['background-color'] = 'blue'; } } })());
 .shape { position: absolute; background-color: blue; } #circle { border-radius: 50%; height: 20px; width: 20px; } #rectangle { height: 20px; width: 50px; top: 40px; left: 40px; }
 <div>Use the keyboard arrows to move the circle</div> <div class="shape" id="circle"></div> <div class="shape" id="rectangle"></div>

编辑:实际问题是关于不应超出矩形的圆

然后只需检查圆的边界是否在矩形的边界内:

 document.addEventListener('keydown', (function() { function isInInterval(value, interval) { const [min, max] = interval; return value >= min && value <= max; } function collision(box, circle) { const { top: boxTop, left: boxLeft, right: boxRight, bottom: boxBottom, } = box.getBoundingClientRect(); const { top: circleTop, left: circleLeft, right: circleRight, bottom: circleBottom, } = circle.getBoundingClientRect(); return !( isInInterval(circleLeft, [boxLeft, boxRight]) && isInInterval(circleRight, [boxLeft, boxRight]) && isInInterval(circleTop, [boxTop, boxBottom]) && isInInterval(circleBottom, [boxTop, boxBottom]) ); } const circle = document.getElementById('circle'); const rectangle = document.getElementById('rectangle'); let circleTop = 26; let circleLeft = 8; return function(e) { e.preventDefault(); if(e.keyCode === 37) { circleLeft -= 1; } if(e.keyCode === 38) { circleTop -= 1; } if(e.keyCode === 39) { circleLeft += 1; } if(e.keyCode === 40) { circleTop += 1; } circle.style.top = `${circleTop}px`; circle.style.left = `${circleLeft}px`; if (collision(rectangle, circle)) { rectangle.style['background-color'] = 'red'; circle.style['background-color'] = 'red'; } else { rectangle.style['background-color'] = 'blue'; circle.style['background-color'] = 'blue'; } } })());
 .shape { position: absolute; background-color: red; } #circle { border-radius: 50%; height: 20px; width: 20px; } #rectangle { height: 20px; width: 50px; top: 40px; left: 40px; }
 <div>Use the keyboard arrows to move the circle</div> <div class="shape" id="circle"></div> <div class="shape" id="rectangle"></div>

谢谢你的回答,我已经可以解决问题了

 const $circle = document.getElementById("circle"); const $box = document.getElementById("box"); let mtop = 0; let mleft = 0; let boxTop = 0; let boxLeft = 0; let boxRight = 0; let boxBottom = 0; document.addEventListener("keydown", (e) =>{ e.preventDefault(); let boxPos = $box.getBoundingClientRect(); let boxTop = boxPos.top; let boxLeft = boxPos.left; let boxRight = boxPos.right; let boxBottom = boxPos.bottom; let circlePos = $circle.getBoundingClientRect(); let circleTop = circlePos.top; let circleLeft = circlePos.left; let circleRight = circlePos.right; let circlebottom = circlePos.bottom; if(e.keyCode === 39) { mleft++; $circle.style.marginLeft = mleft +"px"; if(Math.trunc(circleRight) === Math.trunc(boxRight)){ mleft = mleft - 5; } } if(e.keyCode === 37){ mleft--; $circle.style.marginLeft = mleft +"px" if(Math.trunc(circleLeft) === Math.trunc(boxLeft)){ mleft = mleft + 5; } } if(e.keyCode === 38){ mtop--; $circle.style.marginTop = mtop + "px"; if(Math.trunc(circleTop) === Math.trunc(boxTop)){ mtop = mtop + 5; } } if(e.keyCode === 40){ mtop++; $circle.style.marginTop = mtop + "px"; if(Math.trunc(circlebottom) === Math.trunc(boxBottom)){ mtop = mtop - 5; } } })
 :root { --main-color: red; --second-color: blue; } .container { background-color: var(--main-color); border: black; width: 50%; height: 60%; position: absolute; } #circle{ position: absolute; width: 60px; height: 60px; left: 0; right: 0; border-radius: 100%; background-color: var(--second-color); padding: 10px; }
 <div id="box" class="container"> <div id="circle"></div> </div>

暂无
暂无

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

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