Обнаружение столкновения div? - PullRequest
5 голосов
/ 09 мая 2011

Вот что я сейчас делаю:

<!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 (спрайт попадает в «чанк»), а затем его необходимо переместить. Знаете ли вы лучший способ обнаружить столкновение divs? Спасибо.

Ответы [ 5 ]

6 голосов
/ 09 мая 2011

Я дам вам теоретический ответ:

Вы хотите вычислить границы вашего 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()
3 голосов
/ 02 мая 2015
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 голосов
/ 19 мая 2011

Попробуйте jquery-collision .Полное раскрытие: я написал это недавно и только что загрузил.Я сам недавно столкнулся с этим и не увидел очевидного решения, поэтому решил сам создать плагин и опубликовать его в source-forge.

Это позволяет вам:

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

или "#chunk" может быть своего рода ".obstacle", и он вернет все class = "препятствия", которые перекрывают id = "sprite".

1 голос
/ 09 мая 2011

Я использую эту технику ... функция может быть оптимизирована, но для ясности я оставил ее немного многословной:

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, вам следует выбрать селектор.

0 голосов
/ 05 сентября 2013

Возможно, я что-то не так понимаю, но некоторые из приведенных примеров кажутся либо неправильными, либо недостаточно информативными. При проверке на столкновение нельзя просто проверить одну сторону, потому что вы вырезаете всю плоскость. Вы также не можете просто проверить один 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);
});
...