【问题标题】:Collision detection algorithm碰撞检测算法
【发布时间】:2013-10-21 17:36:37
【问题描述】:

我要解决的算法有问题,我有一个我要检查碰撞的点列表,我可能使用一些 pytagoras,但我的主要问题是效率该算法,因为我需要检查是否仅在一个轴上相交,假设我有一个矩形点(0,100),其他点(300,100),两者都在y = 100,所以对于我的应用程序我决定它们发生碰撞,现在我如何检查是否有任何矩形与其他矩形发生碰撞?

我的第一次尝试是循环检查我添加的每个矩形是否与其他矩形发生碰撞,但我认为这是错误的,因为如果我有 100 个矩形,我将需要检查第一个碰撞其他 99 个,以及它们中的每一个(如果它们与其余部分发生碰撞)。

我很确定循环会以指数方式增加,这很糟糕,所以有人可以指出正确的方向,告诉我如何才是最有效的检查方式,谢谢!

编辑 13 年 10 月 22 日 使用@John Phu Nguyen 函数

var events = [ {start: 30, end: 150}, {start: 540, end: 600}, {start: 560, end: 620}, {start: 610, end: 670} ];
//each start and end props are y coordinates, basically where the rect start and ends
function layOutDay(events) {
    //console.log(events);

    var events_container = document.querySelector('.events-col');
    var frag = document.createDocumentFragment();
    for(var i=0; i<events.length; i++){
        //console.log(events[i].start);
        var top = events[i].start;
        var bottom = events[i].end-events[i].start;

        var event = createEventDOM();
        var gutter = event.querySelector('.gutter');

        event.style.top = top + 'px';
        event.style.height = gutter.style.height = bottom + 'px';

        if(y_coords.indexOf(top) === -1 && y_coords.indexOf(bottom) === -1){
            y_coords.push(top);
            y_coords.push(bottom);

            y_coords.sort();

            event.style.left = '10px';
            console.log('NO collision', top, bottom);
        }else{
            console.log('collision', top, bottom);
            event.style.width = '250px';
            event.style.left = '220px';
        }

        frag.appendChild(event);
    }

    events_container.appendChild(frag);
}

所以运行函数我得到 2 个矩形碰撞,但有 3 个而不是 2 个,我需要知道谁在与谁在 x 轴上相互移动矩形!

Here is a screenshot of what I'm trying to do

可能是一个调整,但我找不到它,非常感谢任何帮助,谢谢!!!

【问题讨论】:

  • 如果你有一组点,那么它们怎么会“碰撞”呢?当我想到点碰撞时,在同一个地方对我来说似乎是最明显的方式。但是,您似乎正在绘制矩形来检测碰撞?您能否更深入地解释一下在您的情况下如何确定碰撞,以及什么构成碰撞?
  • 除非所有矩形都一直在移动,否则您只需要检查那些确实移动的矩形。
  • 首先,感谢大家的回复,感谢大家抽出宝贵时间提供帮助!,我将留下一些最适合我的解决方案,但一切都完全有意义
  • 所有的矩形都在同一个 y 上还是只是你的例子,它们可以在任何 y 上并且有任何咏叹调?
  • 是的,它们可以在任何y,基本上我需要知道谁在y的同一范围内,我可以使用for循环来做到这一点,但我想检查它们中的每一个是不是效率

标签: javascript algorithm collision-detection


【解决方案1】:

循环不会呈指数增长,而是呈二次方增长,这仍然很糟糕。

有几种解决方案,例如取决于有多少矩形在移动,有多少是固定的。

一个非常简单的代码解决方案是

  • 构建一个 NxN 单元格的网格,其中每个单元格都可以包含一个与该单元格接触的矩形列表
  • 遍历矩形并将每个矩形放入它们接触的每个单元格的列表中。这样做时,您还可以检查矩形是否与同一单元格列表中的其他矩形发生冲突。

当你移动一个矩形时,这个网格数据结构很容易保持更新:只需将它从当前列表中删除,然后将它插入到新位置的列表中。

什么是最佳N 确实取决于应用程序。

【讨论】:

    【解决方案2】:

    如果您只是想检查沿轴的各个点,排序列表会很好用。

    在 Javascript 中:

    //Existing points:
    var x_coords = [0, 20, 310, 400];
    var y_coords = [0, 50, 100, 500];
    
    //New point
    x_new = 300;
    y_new = 100;
    
    //Check for collision
    if(x_cords.indexOf(300) == -1 && y_cords.indexOf(100) == -1) 
    {
        //No collision, add to list
        //Add another point
        x_coords.push(300);
        x_coords.push(100);
    
        //Sort list, complexity should be low if sorted after every insert
        x_coords.sort();
        y_coords.sort();
    }
    

    如果你正在寻找一个范围内的碰撞,

    x_cords.indexOf( 100 )
    x_cords.indexOf( 200 )
    

    将为您提供值 100 和 200 的索引。该范围内的任何内容都将出现在排序列表中的这两个索引之间。


    附加信息:

    'bottom' 当前是元素高度,而不是底部。 if 语句应该是:

    if(y_coords.indexOf(top) === -1 && y_coords.indexOf(end) === -1)
    

    但是,这仍然不会产生任何结果,因为 indexOf() 函数专门查找一个值,而不是如果某些值之间存在值。

    为此,您可以使用列表推导:

    elements_between_y100_and_y300 = [i for i in y_cords if (i >= 100 && i <=300)]
    

    如果列表返回空,则没有冲突。

    为了找出哪些元素发生了碰撞,您很可能必须保留一个单独的列表,例如: element_at[200] = 2

    【讨论】:

    • 您好,感谢您的帮助,我正在尝试理解这种方法,但我对此功能有一些疑问,请检查我的问题的编辑,看看我到目前为止得到了什么,再次感谢
    • 您好,请参阅“附加信息:”下答案的附录。如果语法不完全正确,我很抱歉,我已经有一段时间没有使用 Javascript
    • 没问题,你只是给我一个线索,谢谢你的帮助,我想我做的和你刚才提到的很相似,所以我认为这可能是我问题的正确答案,谢谢!想一想,我认为列表理解仅在 python 中,无论如何仍然有效,谢谢!
    猜你喜欢
    • 2015-02-02
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多