快速在数组中查找对象

对于一个碰撞检测游戏,我在考虑将环境中的对象分成不同的块,以减少需要检查的对象数量,只检查同一(和相邻的)块中的对象。然而,我的一些对象(子弹)将快速通过不同的块,因此我需要快速将这些对象从一个数组移动到另一个数组中。

我考虑使用字典而不是数组,因此可以使用唯一的键作为索引快速查找子弹并将其移动,但是我决定看看这里是否有更好的方法?

我计划在游戏中有几千个对象(包括子弹),对象本身将只是圆形和矩形,子弹将被表示为线段。

点赞
用户9922866
用户9922866

我认为你所说的“块”是指游戏世界中彼此独立、可减少开销的不同区域。如果我错了,请纠正我。

至于“块”之间子弹轨迹的问题,我建议记录子弹的起点——也就是发射子弹的地点——和子弹与物体碰撞的地点。这可以通过一些依赖于你的游戏世界坐标系的碰撞检测来实现,无论这个坐标系是什么样子。我建议创建一个 Bullet 类。这是一个快速的概念证明,可以作为模块使用 require 加载:

local Bullet = {__type = "Bullet"}

-- 这个函数可以将子弹信息作为参数,比如它的起点和口径。
function Bullet.new(start_pos_in, calibre_in)
    -- 在这个表中记录起点和终点位置,可能用一些(x,y)坐标对来表示,假设你的游戏是2D的。我只是用了一个名为“Point”的通用占位符。
    local self = {
        calibre = calibre_in,
        start_pos = start_pos_in,
        end_pos = Point.new(0, 0)
    }
    local mt = {
        __metatable = "metatable",
        __newindex = function(t, k, v)
            local e = string.format("type Bullet has no member '%s'", k)
            return error(e, 2)
        end,
        __index = self
    }
    return setmetatable(self, mt)
end

return Bullet

使用我上面的例子,可以这样实例化一个 Bullet 对象:

-- 以.50口径为例。'x''y'表示子弹在游戏世界中的起点。
local bullet = Bullet.new(Point.new(x, y), ".50")

一旦 Bullet 对象与游戏世界中的某个物体碰撞,您可以使用内部变量 end_pos 记录其碰撞点,计算其行程等。根据您的“块”系统如何工作,您可以记录子弹的“块”起点。

作为一个副注,我建议尝试实现对象池,以节省开销的子弹粒子。 (如果您有兴趣,请参阅此文章进行参考。)

2020-03-05 17:34:45