我正在开发一个Java模拟,其中对象在2D网格中移动。网格中的每个单元格只能由一个单元格占据,并且对象通过从一个单元格移动到另一个单元格来移动。
这比理论上更具理论性,但有没有人有关于如何与此网格进行冲突处理的想法?是否有人用于处理网格状世界中的碰撞的算法?
请注意,我不是在谈论碰撞检测,因为这是微不足道的,因为对象从一个单元格移动到另一个单元格。我正在谈论碰撞处理,这可能会非常复杂。
Ex:对象A希望移动到与对象B相同的位置,并且对象C希望移动到对象B的当前位置。由于每个单元格只能包含一个对象,如果对象A能够移动到所需的位置,这将导致对象B保持静止,从而导致对象C也保持静止。
可以想象,这可能会产生更长的需要处理的碰撞链。
是否有人使用过可以帮助解决这个问题的算法或方法?如果搜索结果没有使用碰撞 detection 算法,则几乎不可能搜索此问题。
编辑:所有对象在同一时间移动。我想限制必须保持静止的对象数量,所以我更喜欢先处理具有较长碰撞链的对象(如本例中的对象B)。
答案 0 :(得分:1)
根据与OP的讨论,对象应以最大化所有移动对象的数量的方式移动。
带有引用的对象形成树林。如果对象A
引用B
对象占用的单元格,我们可能会说B
是树中A
的父。因此,对象对应于节点,引用对应于树中的边。每棵树的根中都会有一些空单元格(所以当空单元格对应一个节点时实际上就是这种情况)。树没有公共节点。
在继续前进之前,我们必须承认可能存在周期的情况。像这样:
[A] -> [B]
^ v or [A] <=> [B]
[D] <- [C]
可以轻松识别这些周期。某些对象可能直接或间接地引用循环对象,也形成树。循环只能在树的根中发生。
让我们说我们建造了所有树木。现在问题是我们如何解决冲突?请记住,我们希望最大化移动节点的数量。冲突对应于具有多于1个孩子的节点。
在 cycle-root 树中,除了仅移动循环对象而不移动树中的任何其他对象外,我们没有任何其他选项。很明显,我们不能采取另一种方式。
首先,在 empty-cell-root 树中,我们必须决定将哪个根子项放在根空单元格上。然后我们将有一个新的空单元格,我们将不得不采取相同的决定。依此类推,直到 leaf 节点。为了最大化移动节点的数量,我们必须将最长的链从根到某个叶子并移动其节点。所有其他节点都不移动。这可以通过使用一些递归函数遍历树并为每个节点计算以下函数 f 来轻松完成 f leaf = 0 和 f node = MAX(f child1 ,f child2 ,...)+ 1 。因此,上述决定是选择具有最大 f 的子节点。
*
/|\
A B C The optimal move path is * <- C <- E <- H
/ /|\
D E F G
/
H
答案 1 :(得分:0)
提前“检查”/“下一步”将导致难以计算甚至爆炸。
相反,你可以(并行)使用检查“哪个粒子可以移动到这个位置?”在每个细胞上。为此,您需要在每个单元格中具有速度矢量的速度图。然后向后跟随该向量,找到一个单元格。如果有粒子,请将其送到牢房。
这样就不会发生冲突,因为每个单元只执行一次操作。只需从负速度矢量的终点获得最接近的单元格。
计算起来有点棘手,因为速度可能无法完全落在细胞中心。对于运动/宏观效果的平等,需要概率(如果它非常靠近角落而不是中心)。
因此,仅在细胞指数上存在竞争条件,并且移动的随机性(或粒子拾取取决于与细胞中心的距离)可以容忍
在量子物理学中,粒子可以跳过墙壁的其他部分,静止不动(即使它不应该),并做一些对经典物理学来说不自然的事情。因此,如果分辨率很高,并且速度不高于地图大小,它应该看起来很自然,尤其是当多个细胞竞争从另一个细胞中获取粒子时的随机性。
多次通过:
检查Gauss-Seidel(https://en.wikipedia.org/wiki/Gauss%E2%80%93Seidel_method)方法以解决许多线性方程式。
计算是在细胞而不是粒子上进行的,因此地图边界将是防弹的,并且计算可以在所有核心之间平均分配。
示例:
粒子A下降
粒子B向右走
他们正处于碰撞过程中
求解速度图平衡状态(Gauss-Seidel)
现在粒子A的单元格具有向下+向右的速度
与B
相同 好像他们碰撞了但是他们还在他们的牢房里。用它们的细胞速度移动它们会使它们看起来像碰撞一样。