簡體   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