用于查找范围内的对象而不遍历所有其他对象的算法?

时间:2019-03-04 20:33:17

标签: algorithm collision-detection

背景

我刚开始制作游戏,它的对象应该能够通过“声音”彼此交流(不一定是真实声音,可以是模拟声音,但应该表现得像声音)。

这意味着他们只有在听觉范围内才能互相通信。

问题:

是否存在某种聪明的方法来测试另一个对象是否在听觉范围内而无需遍历所有其他对象?(当很多其他对象出现时,它的效率会非常低下)

注意:在听觉范围内可以有多个对象,因此,将听觉范围内的所有对象都添加到一个数组(或列表,尚未决定)中以进行通信。 / p>

数据

当前该对象具有这些属性(可以根据需要更改)。

Object {
    id = self.id,
    x = self.x,
    y = self.y,
    hearing_max_range = random_range(10, 20), // eg: 10
    can_hear_other = []; // append: other.id when in other in range
}

1 个答案:

答案 0 :(得分:1)

您可以研究一些聪明的数据结构,例如四叉树或kd树,但是对于固定范围查询的问题,仅使用简单的装箱并不会太糟糕。我将以类似python的伪代码介绍通用算法。

首先构造您的垃圾箱:

from collections import defaultdict

def make_bin(game_objects, bin_size):
    object_bins = defaultdict(list)
    for obj in game_objects:
        object_bins[(obj.x//bin_size, obj.y//bin_size)].append(obj)

然后根据需要查询:

def find_neighbors(game_object, object_bins, bin_size):
    x_idx = game_object.x // bin_size
    y_idx = game_object.y // bin_size
    for x_bin in range(x_idx - 1, x_idx + 2):
        for y_bin in range(y_idx - 1, y_idx + 2):
            for obj in object_bins[(x_bin, y_bin)]:
                if (obj.x - game_object.x)**2 + (obj.y - game_object.y)**2 <= bin_size**2:
                    yield obj