Search code examples
javascripthtmljqueryrandomoverlap

Javascript Randomly Positioned Div's without overlapping them


I've been working on a random concept idea of having 6 clouds appear on a page with random comments pulled from a database. That part is easy, however I'm finding it extremely difficult to make sure the 6 clouds don't overlap each other. I've looked into Collision Detection a lot and found that there's no real suitable method of checking for a DIV within a range at X or Y before placing the new "randomly positioned" div on the page. I have my code below which I know is extremely messy right now. I currently have it checking the last DIV with reasonable success but if DIV 1 and DIV 3 for example, have similar X Y positions then It's a problem. Sorry If I'm making no sense.. here's my code and a jsFiddle

$(document).ready(function () {
var counter = 0;
//var colide = {};
var px = 0;
var py = 0;

var clouds = new Array("cloud1", "cloud2", "cloud3", "cloud4", "cloud5", "cloud6");
var cloudtext = new Array("This is text for cloud 1 :D", "This is text for cloud 2 :D", "This is text for cloud 3 :D", "This is text for cloud 4 :D", "This is text for cloud 5 :D", "This is text for cloud 6 :D");

function makeDiv() {
    if (counter < 6) {
        counter++;

        //var divsize = ((Math.random() * 100) + 50).toFixed();
        //var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
        $newdiv = $('<div class="' + clouds[counter - 1] + '">' + cloudtext[counter - 1] + '<div/>').css({

            'width': '354px',
                'height': '202px'

            //'width': divsize + 'px',
            //'height': divsize + 'px',
            //'background-color': color,
        });

        var posx = (Math.random() * ($(document).width() - 354)).toFixed();
        var posy = (Math.random() * ($(document).height() - 202)).toFixed();

        while (posy < 180) {
            posy = (Math.random() * ($(document).height() - 202)).toFixed();
        }


        if ((px > posx + 354) || (px < posx - 354)) {
            if ((py > posy + 202) || (py < posy - 202)) {


                //alert(px + ' - ' + posx + ' px(temp) - posx(newdiv) - good to go!');
                py = posy;
                px = posx;
                $newdiv.css({
                    'position': 'absolute',
                        'left': posx + 'px',
                        'top': posy + 'px',
                        'display': 'none',
                        'background-image': 'url(http://www.demixgaming.co.uk/cloud/images/Cloud.png)',
                        'text-align': 'center',
                        'line-height': '202px',
                        'color': '#000'
                }).appendTo('body').fadeIn(150).delay(300, function () {
                    makeDiv();
                });
            } else {
                counter--;
                px = posx;
                py = posy;
                makeDiv();
            }
        } else {
            counter--;
            px = posx;
            py = posy;
            makeDiv();
        };

    }
}
makeDiv();

});

JS Fiddle - Link to JSFiddle


Solution

  • The algorithm would look something like this; I might have made a mistake though

    1. Get the document's height and width y = docH, x = docW
    2. Subtract the <div>'s height and width, y = y - divH, x = x - divH
    3. Choose random co-ordinates curX, curY between 0..x, 0..y
    4. newX = curX, newY = curY
    5. For each previous <div>
      1. Call it's info prevX, prevY, prevW, prevH
      2. If prevX < curX then newX = newX + prevW
      3. If prevY < curY then newY = newY + prevH
    6. Append <div> at newX, newY
    7. Save <div> info curX, curY, divW, divH
    8. If there is another <div>, go to step 2.