检测div碰撞?

时间:2011-05-08 20:08:14

标签: jquery css html collision-detection

这就是我现在正在做的事情:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>untitled</title>
    <meta name="generator" content="TextMate http://macromates.com/">
    <style type="text/css" media="screen">

        body { font-family:"HelveticaNeue-Light"; margin: 0px; }
        input { width: 75%; }
    #wrap { background: #f1f1f1; border: 1px solid #d9d9d9;  padding: 0px; }

/*    #sprite { position: relative; background: #909090; width: 20px; height: 20px; padding: 20px; }*/
        #spriteChatBubble { position: relative; background: #fff; border: 1px solid #000; font-size: 10px; max-width: 200px; }

        #controlArea { margin-top: 50px; }

        .button { background: #fff; color: #0080ff; padding: 5px; border: 1px solid #0050ff; text-decoration: none; }
        .button:active { background: #0080ff; color: #fff; }

    </style>

    <script type="text/javascript" charset="utf-8">

        $(document).ready(function() {

            // on load
            updatePos();

            // get it ready

            $("#sprite").css("background-image", "url(left100by100.png)");



            // our main block

            function detectCollision() {


        var spritePos = $("#sprite").position();
        var spritePosLeft = spritePos.left;
        var spritePosTop = spritePos.top;

        var chunkPos = $("#chunk").position();
        var chunkPosLeft = chunkPos.left;
        var chunkPosTop = chunkPos.top;


        // show the chunk's position values (test)
        $("#posLeftChunk").text(posLeftChunk);

              if (spritePosLeft == chunkPosLeft || spritePosTop == chunkPosTop) {


          // make it go somewhere random! :D

                var randomLeft = Math.floor(Math.random() * 100);
                var randomTop = Math.floor(Math.random() * -100);

          // $("#chunk").hide();

                $("#chunk").css("top", randomTop + "px");
                $("#chunk").css("left", randomLeft + "px");


          // $("#spriteChatBubble").animate({"top": "-=" + randomTop}, "fast");

              }

            }

            setInterval(detectCollision, 500);


            function insertValues(name){

              var name = "foop";
              var spritePosition = $("#sprite").position();
              var leftVal = spritePosition.left;
              var topVal = spritePosition.top;

            }

            insertValues("");


            function showMessage(message) {

              $("#spriteChatBubble").show('slow');
              $("#messageText").text(message);
              $("#spriteChatBubble").delay(5000).hide('slow');

            }

            function updatePos() {

              var position = $("#sprite").position();
              $("#posLeft").text(position.left);
              $("#posTop").text(position.top);
              // updatePos();

              // insert the values into a database
              insertValues("");

            }



            $(document).keydown(function(ee) {

              $("#spriteChatBubble").hide();  // no need to show this!

              // if ($("#sprite").position.left < 0) {
              //           alert();
              //         }                           // fail

              if (ee.keyCode == 37) {

                // going left!

          $("#sprite").css("background-image", "url(left100by100.png)");
          // alert("going left!");

          $("#sprite").animate({"left": "-=50px"}, "fast");
          $("#spriteChatBubble").animate({"left": "-=50px"}, "fast");
          updatePos();
              } 

              if(ee.keyCode == 39) {

                // going right!

          $("#sprite").css("background-image", "url(right100by100.png)");
          // alert("going right!");

                $("#sprite").animate({"left": "+=50px"}, "fast");
                $("#spriteChatBubble").animate({"left": "+=50px"}, "fast");
          updatePos();
              }

              if(ee.keyCode == 38) {
                $("#sprite").animate({"top": "-=50px"}, "fast");
                $("#spriteChatBubble").animate({"top": "-=50px"}, "fast");
          updatePos();
              }

              if(ee.keyCode == 40) {
                $("#sprite").animate({"top": "+=50px"}, "fast");
                $("#spriteChatBubble").animate({"top": "+=50px"}, "fast");
          updatePos();
              }



            });

            $("#left").click(function() {
              $("#sprite").animate({"left": "-=50px"}, "fast");
         updatePos();
            });

            $("#right").click(function() {
              $("#sprite").animate({"left": "+=50px"}, "fast");
         updatePos();
            });

            $("#talkButton").click(function() {
              showMessage($("#speakField").val());
              $("#speakField").val("") ;
            });

        });




    </script>
    <!-- Date: 2011-05-23 -->
</head>
<body>

  <!-- <div id="spriteChatBubble">
      <a class="mt" id="messageText">message</a>
    </div> -->

  <!-- avatar (you, the player) -->

    <div id="sprite" style="position: relative; background: url('right100by100.png'); width: 100px; height: 100px;">

    </div>


  <!-- chunks -->

    <div id="chunk" style="position: relative; background: #909090; width: 20px; height: 5px; top: 100px; left: 80px;"></div>

    <div id="controlArea">

      position.left: <a id="posLeft">0</a><br>
    position.top: <a id="posTop">0</a><br>
    <br><br>
    position.left (chunk): <a id="posLeftChunk">0</a><br>
    position.top (chunk): <a id="posTopChunk">0</a><br>

      <!-- <input type="text" id="speakField" onchange="javascript:void(0);">
         <a href="javascript:void(0);" class="button" id="talkButton">talk!</a>
         <a href="javascript:void(0);" onclick="showMessage('foo');" class="button" id="">test it</a>

         <br><br>

        <a href="javascript:void(0);" class="button" id="left">(</a>
        <a href="javascript:void(0);" class="button" id="right">)</a>
         -->
    </div>


</body>
</html>

在所需的方向上将其移动50个像素,然而检测到div碰撞(精灵击中“chunk”)然后需要重新定位。你知道更好的方法来检测div碰撞吗?感谢。

5 个答案:

答案 0 :(得分:6)

我会给你一个理论上的答案:

你想计算你的div的界限 - 得到你的x,y角值,看看是否有任何其他div的边界与你的其他div的值相交。如果有一个坐标交叉点,那么你自己就会发生碰撞。

如何获取位置坐标:

Top: $("#div").offset().top
Left: $("#div").offset().left
Bottom: $("#div").offset().top + $("#div").height()
Right: $("#div").offset().left + $("#div").width()

答案 1 :(得分:3)

试试jquery-collision。完全披露:我最近写了这个并刚上传。我最近自己遇到了这个,并没有看到明显的解决方案,所以我决定自己创建一个插件并将其发布在source-forge上。

它允许你这样做:

var hit_by_sprite = $("#sprite").collision("#chunk");

或“#chunk”可以是某种“.obstacle”,它将返回重叠id =“sprite”的所有class =“障碍物”。

答案 2 :(得分:3)

function collision($div1, $div2) {
    var x1 = $div1.offset().left;
    var y1 = $div1.offset().top;
    var x2 = $div2.offset().left;
    var y2 = $div2.offset().top;
    if ((y1 + $div1.outerHeight(true)) < y2 ||
        y1 > (y2 + $div2.outerHeight(true)) ||
        (x1 + $div1.outerWidth(true)) < x2  ||
        x1 > (x2 + $div2.outerWidth(true)))
        return false;
    return true;
}

试试这个?

答案 3 :(得分:1)

我使用这种技术......该功能可以进行优化,但为了清晰起见,我还是留下了一些冗长的内容:

function hitTest(a, b){
    var aPos = a.position();
    var bPos = b.position();

    var aLeft = aPos.left;
    var aRight = aPos.left + a.width();
    var aTop = aPos.top;
    var aBottom = aPos.top + a.height();

    var bLeft = bPos.left;
    var bRight = bPos.left + b.width();
    var bTop = bPos.top;
    var bBottom = bPos.top + b.height();

    // http://tekpool.wordpress.com/2006/10/11/rectangle-intersection-determine-if-two-given-rectangles-intersect-each-other-or-not/
    return !( bLeft > aRight
        || bRight < aLeft
        || bTop > aBottom
        || bBottom < aTop
        );
}

这很好用 - 在一些小游戏中使用它。如果您想考虑边框和填充,可以将position()替换为offset()

我还建议替换它:

$("#sprite").animate({"left": "+=50px"}, "fast");

有类似的东西:

// at top of script cache #sprite selector if possible
var sprite = $("#sprite");
var spriteX = 0;

//... when you do the key check:

spriteX += 10;
sprite.css("left", spriteX);

这会更快,没有理由使用动画进行线性交互动作。没有理由不断选择#sprite,你应该选择。

答案 4 :(得分:0)

我可能正在读错了,但提供的一些例子似乎错了,或者信息不足。检查碰撞时,您不能只检查一侧,因为您正在切割整个飞机。您也不能只检查一个div,因为您尝试放置的div可能会吞没放置的div,您可能还需要检查该碰撞。

我一直在尝试对图像进行碰撞检测,但它可以轻松转换为div。我已经包含了与此相关的所有功能。我的目标是能够在页面上的任意位置放置div,并随机化图像以及它们的位置,而不会影响页面上的任何其他内容。显然,如果您想使用它,您需要使用自己的路径将图像名称更改为您的图像。

此外,如果你在很多图像中使用它,或者在狭小的空间中使用它,或者只是想要一个故障保护,可以在while循环中添加一个计数器,用于打破循环如果达到一定数量。如果在查找所有内容的位置时遇到问题,这将阻止页面锁定。

希望像我一样在这里结束的人可以使用它。

CSS

#imageHolder {
    z-index: -1;
    background-color:red;
    height: 700px;
    width: 200px;
    position: absolute;
    top: 3px;
}
.preloadedImage {
   display: none;    
}

.loadedImage {
   display: normal;
   position: absolute;
   z-index: -1; /* Can be removed. Places the Images underneath everything on the page.
}

函数返回一个随机数

function Random_Number(maxNumber) {
    rndNumber = Math.floor(Math.random() * maxNumber);
    return rndNumber;    
}

函数返回一个随机位置

//Params provide size of the image and which element to use for measurements. 
//Don't want a left position to be against the edge, otherwise it will
//flow passed the div. However, if you want to achieve this look, just pass in 0,0 or remove them. 
function Random_Position(elem, imgHeight, imgWidth) {
    var top = Math.floor(Math.random() * ($(elem).height() - imgHeight));
    var left = Math.floor(Math.random() * ($(elem).width() - imgWidth));    
    var pos = [top, left];    
    return pos;
}

主要功能

function Randomize_Images(elem, numOfImgs, imgNameArr) {
    var imgIDs = [];
    var collision;
    var rndImgPos; //needs to be declared outside of loops so it can access outside of loops.

    for (var z = 0; z < numOfImgs; z++) {
        imgIDs.push("rndImg" + $(elem).attr("id") + z);
    }

    //Main loop - each iterations places a random image inside the div free of collision
    for (var i = 0; i < numOfImgs; i++) {

        //Create the image and hide it until its position has been set.
        $(elem).append($("<img />", {
            src: "libs/images/random_images/" + imgNameArr[Random_Number(imgNameArr.length)] + ".png",
            id: imgIDs[i],
            class: "preloadedImage"
        }));

        collision = true;
        //Collision loop. Will not exit unless its forced, or finds a free a spot.
        while (collision) {

            //the image that will be added.
            var curImg = $("#" + imgIDs[i]);
            rndImgPos = Random_Position(elem, curImg.height(), curImg.width());            
            var imgTop = rndImgPos[0];
            var imgBot = rndImgPos[0] + curImg.height();
            var imgLeft = rndImgPos[1];
            var imgRight = rndImgPos[1] + curImg.width();

            //no reason to check for collision with the first image.
            if (i >= 1) {

                //Image loop. Will loop through all images previously placed, and check for collision.
                for (var x = 0; x < i; x++) {
                    var setImg = $("#" + imgIDs[x]);
                    var setImgPos = setImg.position();
                    var setTop = setImgPos.top;
                    var setBot = setImgPos.top + setImg.height();
                    var setLeft = setImgPos.left;
                    var setRight = setImgPos.left + setImg.width();

                    if (((imgLeft < setLeft && imgRight > setLeft) || (imgLeft < setRight && imgRight > setRight)) && ((imgTop < setTop && imgBot > setTop) || (imgTop < setBot && imgBot > setBot))) {
                        collision = true;
                        break;
                    }
                    else if (((setLeft < imgLeft && setRight > imgLeft) || (setLeft < imgRight && setRight > imgRight)) && ((setTop < imgTop && setBot > imgTop) || (setTop < imgBot && setBot > imgBot))) {
                        collision = true;
                        break;
                    }
                    else {
                        collision = false;
                    }
                }
            }
            else {
                collision = false;
            }
        }
        //Set the coordinates for the new image, and assign it's permanent class.
        var curImg = $("#" + imgIDs[i]);       
        $(curImg).css("top", rndImgPos[0]);
        $(curImg).css("left", rndImgPos[1]);        
        curImg.removeClass("preloadedImage");
        curImg.addClass("loadedImage");         
    }    
}

调用它的示例

//I am calling the function here after window load, with an additional 2 second pause because I have a Datatable loading, and it adds to the height of the page. For this particular call, I want the div to be the length of the entire page. You don't need anything but the function call otherwise.

$(window).on("load", function(){
    setTimeout(function(){
        var imgNames = ["bullethole1", "bullethole2", "bullethole3", "bullethole4", "bullethole5", "bullethole6"];
        $("#imageHolder").height($(document).height());
        Randomize_Images($("#imageHolder"), 20, imgNames);          
    },2000);
});