在javascript中重叠/命中测试

时间:2012-06-04 21:16:47

标签: javascript html5 canvas html5-canvas

我试图让命中测试/重叠测试在下面的代码中工作,该代码在画布上的随机位置创建200个圆圈。我试图将圆圈的位置存储在一个数组中,然后每次在for循环中创建另一个圆圈时检查该数组,如果随机创建的x和y太接近已经创建的圆圈,它应该继续获得一个新的圆圈随机x和y,直到它不太接近已经创建的圆圈。

我不能在while循环中使用它。

任何帮助请...

由于

    <script type="text/javascript">

    document.addEventListener("DOMContentLoaded", canvasDraw);


    function canvasDraw () {
    var c = document.getElementById("canvas");
    var w = window.innerWidth;
    var h = window.innerHeight;
    c.width = w;
    c.height = h;

    var ctx = c.getContext("2d");
    ctx.clearRect(0,0,c.width, c.height);
    var abc = 0;

    var colours = new Array ("rgb(0,100,0)", "rgb(51,102,255)");
    var positions = new Array();


    function hitTest(x, y) {
    for(var p in positions) {
            pp = p.split(",");
        pp[0] = parseInt(pp[0]);
        pp[1] = parseInt(pp[1]);

        if(((x > (pp[0] - 24)) && (x < (pp[0] + 24))) && ((y > (pp[1] - 24)) && (y < (pp[1] + 24)))) {

            return true;
        }
    }
    return false;
}


            //Loop 200 times for 200 circles
    for (i=0; i<200; i++) {

        var x = Math.floor(Math.random()*c.width);
        var y = Math.floor(Math.random()*c.height);

        while(hitTest(x, y) == true){
            var x = Math.floor(Math.random()*c.width);
            var y = Math.floor(Math.random()*c.height);
        }

        var pos = x.toString() + "," + y.toString();
        positions.push(pos);

        var radius = 10;
        var r = radius.toString();

        var b = colours[Math.floor(Math.random()*colours.length)];

        circle(ctx,x,y, radius, b);

    }   
   }



    function circle (ctx, x, y, radius, b) {
  ctx.fillStyle = b;
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI*2, true);
  ctx.closePath();
  ctx.fill();
   }
  </script>

1 个答案:

答案 0 :(得分:3)

开始前的一些事情:

  1. 除非指定初始长度,否则不要使用new Array()创建数组。使用[];
  2. 不要使用for...in迭代数组:使用带有计数器的标准for。这是一个很好的做法;
  3. 将数字转换为字符串并转换回数字是无用且昂贵的。使用小数组来存储两个值;
  4. 请勿使用“幻数”,即具有精确值但很难立即识别的数字。使用命名的“常量”或在它们附近放置注释,告诉它们的含义,以便将来维护。
  5. 好的,让我们看看代码。

    if(((x > (pp[0] - 24)) && (x < (pp[0] + 24))) && ((y > (pp[1] - 24)) && (y < (pp[1] + 24))))
    
    老实说,这是什么?我称之为一个胡思乱想,不起眼的片段。回想一下你在学校学到的东西:

    var dx = pp[0] - x, dy = pp[1] - y;
    if (dx * dx + dy * dy < 400) return true;
    

    是不是更清楚了?

    让我们看看整个功能:

    function canvasDraw () {
        var c = document.getElementById("canvas");
        var w = window.innerWidth;
        var h = window.innerHeight;
        c.width = w;
        c.height = h;
    
        var ctx = c.getContext("2d");
        ctx.clearRect(0,0,c.width, c.height);
        // Lolwut?
        // var abc = 0;
    
        var colours = ["rgb(0,100,0)", "rgb(51,102,255)"];
        var positions = [];
    
    
        function hitTest(x, y) {
            for (var j = 0; j < positions.length; j++) {
                var pp = positions[j];
                var dx = pp[0] - x, dy = pp[1] - y;
                if (dx * dx + dy * dy < 400) return true;
            }
            return false;
        }
    
    
        // You declare the radius once and for all
        var radius = 10;
        // Declare the local scoped variables. You forgot i
        var x, y, i;
        for (i=0; i<200; i++) {
    
            // How about a do...while instead of a while?
            do {
                var x = Math.floor(Math.random()*c.width);
                var y = Math.floor(Math.random()*c.height);
            // Testing with === is faster, always do it if you know the type
            // I'll let it here, but if the type is boolean, you can avoid testing
            // at all, as in while (hitTest(x, y));
            } while (hitTest(x, y) === true);
    
            positions.push([x, y]);
    
            // This instruction is useless
            // var r = radius.toString();
    
            var b = colours[Math.floor(Math.random()*colours.length)];
    
            circle(ctx,x,y, radius, b);
    
        }   
    }
    
    但是, BEWARE ,根据您的画布大小,可能没有其他圈子的空间,因此它可能会以无限循环结束。尝试在40x40的盒子中放入200个半径为10的圆圈...... 应该进行另一项测试, 可能很复杂。