用javascript实现四叉树冲突?

用javascript实现四叉树冲突?,javascript,collision,quadtree,Javascript,Collision,Quadtree,我正在开发一个类似于agar.io和sliter.io(使用node.js和socket.io)的io游戏,在这个游戏中,地图上的2d空间中一次最多有50名玩家和大约300种食物。玩家和食物都是循环的。每一帧,服务器都需要检查玩家是否与食物发生碰撞,并采取相应的行动。player和foods都是具有不同坐标和大小的JSON对象数组。蛮力法将遍历所有食物,对于每种食物,遍历所有玩家,查看他们是否发生碰撞。当然,这需要300*50次迭代,每秒60次(每秒60帧),这对服务器来说当然太重了 我确实遇到

我正在开发一个类似于agar.io和sliter.io(使用node.js和socket.io)的io游戏,在这个游戏中,地图上的2d空间中一次最多有50名玩家和大约300种食物。玩家和食物都是循环的。每一帧,服务器都需要检查玩家是否与食物发生碰撞,并采取相应的行动。player和foods都是具有不同坐标和大小的JSON对象数组。蛮力法将遍历所有食物,对于每种食物,遍历所有玩家,查看他们是否发生碰撞。当然,这需要300*50次迭代,每秒60次(每秒60帧),这对服务器来说当然太重了

我确实遇到了四叉树方法,这对我来说是一个新概念。此外,我对javascript缺乏知识,这让我想知道我到底应该如何实现它。我无法解决的问题如下: 1.既然玩家理论上可以是任意大小的(甚至和地图一样大),那么我划分地图的区域应该有多大? 2.即使我把地图分成了几个部分,那么我能看到它工作的唯一方式就是,对于每个玩家,我需要得到与玩家共享相同部分的食物。这是一个大问题——不管我怎么想,我仍然需要循环检查每一种食物,并检查它是否在要求的部分如果没有循环,我怎么做呢?因为这样仍然会进行50*300次迭代,每秒60次,对我来说,这听起来并没有更快

tldr:我需要找到一种方法来检测一组50个对象和一组300个对象之间的碰撞,每秒60次。如何在不以60 fps的速度循环50*300次迭代的情况下做到这一点


我在网上找不到任何回答我问题的信息。如果我在某个地方遗漏了一些可以给出我所寻求的答案的东西,我提前表示歉意。

这是一个仅检查单个层的小示例,但我认为它演示了如何在不迭代所有对象的情况下检查碰撞

// 2d array of list of things in said square
// NOT A QUADTREE JUST DEMONSTRATING SOMETHING
let quadlayer = [];
for (let i=0;i<4;++i) {
    quadlayer[i] = [];
    for (let j=0;j<4;++j) {
        quadlayer[i][j] = [];
    }
}

function insertObject(ur_object) {
    quadlayer[ur_object.x][ur_object.y].push(ur_object);
}

function checkCollision(ur_object) {
    let other_objects = quadlayer[ur_object.x][ur_object.y];
    console.log('comparing against '+other_objects.length+' instead of '+100);
}

for (let i=0;i<10;++i) {
    for (let j=0;j<10;++j) {
        insertObject({
            x:i%4,
            y:j%4
        })
    }
}


checkCollision({x:1,y:2});
//所述方格中事物列表的2d数组
//不是四叉树,只是演示一些东西
设四层=[];

对于(让i=0;i这是一个有趣的问题……这里有另一个例子,它本质上使用了扫描线算法。(有关扫描线算法的详细解释,请参阅)

与O(n^2)的蛮力相比,扫描线算法的典型性能是O(n logn)

在这个特定的扫描线算法实现中,所有对象(食物和人)保持在队列中,每个对象在队列中有两个条目。第一个条目是
x-radius
,第二个条目是
x+radius
。也就是说,队列跟踪所有对象的左下和右上
x
边界。此外,使用函数
x按照
x
边界对队列进行排序updatePositionInQueue
,它本质上是一种插入排序

这允许
findCollisions
例程简单地遍历队列,维护一组需要相互检查的活动对象。也就是说,在
x
维度中重叠的对象将被动态添加并从活动集中移除。即,当队列条目表示左
x
bo时对于对象,该对象将添加到活动集中,当队列条目表示对象的右
x
边界时,该对象将从活动集中移除。因此,在遍历对象队列时,只需检查即将添加到活动集中的每个对象是否与小的活动对象集发生冲突具有重叠
x
边界的CT

请注意,目前的算法检查人与人、人与食物、食物与食物之间的所有碰撞

作为一个令人愉快的奖励,
updatePositionInQueue
例程允许在对象移动时调整排序队列。也就是说,如果一个人移动,他们的
x,y
位置的坐标可以在对象上更新,然后
updatePositionInQueue(this.qRight)
updatePositionInQueue(this.qLeft)
可以被调用,它将查看排序队列中的上一个和下一个对象,以移动更新的对象,直到其
x
绑定被正确排序。鉴于对象位置在帧之间不应变化太大,队列中左右
x
绑定项的移动应该最小om帧到帧

代码如下所示,它向底部随机生成对象数据,填充队列,然后运行扫描线碰撞检查和蛮力检查,以验证结果,并报告在对象到对象碰撞检查中测量的性能

var queueHead=null;
函数队列条目(paf、lor、x){
this.paf=paf;
this.leftOrRight=lor;
这个.x=x;
this.prev=null;
this.next=null;
}
函数更新位置查询(qEntry){
函数moveEntry(){
//从队列中的当前位置删除qEntry。
如果(qEntry.prev==null)queueHead=qEntry.next;
如果(qEntry.prev)qEntry.prev.next=qEntry.next;
如果(qEntry.next)qEntry.next.prev=qEntry.prev;
//将qEntry添加到队列中的新位置。
if(newLocation==null){
qEntry.prev=null;
qEntry.next=队列头;
queueHead=qEntry;
}否则{
qEntry.prev=新位置;
qEntry.next=newLocation.next;
如果(newLocation.next)newLocation.next.prev=qEntry;
newLocation.next=qEntry;
}
}
//在队列中行走,将qEntry移动到队列中
//基于x的队列的适当位置
//值。首先检查“prev”队列
//条目。。。
设newLocation=qEntry.prev;
while(newLocation&&qEntry.x