您的位置:首页 > 其它

快速教程:在2D空间中使用四叉树实现碰撞检测

2016-03-14 16:33 831 查看
翻译自:http://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space--gamedev-374

Quick Tip: Use Quadtrees to Detect Likely Collisions in 2D Space

快速教程:在2D空间中使用四叉树实现碰撞检测


Many games require the use of collision detection algorithms to determine when two objects have collided, but these algorithms are often expensive operations and can greatly
slow down a game. In this article we'll learn about quadtrees, and how we can use them to speed up collision detection by skipping pairs of objects that are too far apart to collide.




许多游戏需要使用碰撞检测算法来决定两个物体什么时候发生碰撞,但是这些算法很消耗CPU,可能会大幅度降低游戏速度。所以在这篇文章中,我们就来学习有关四叉树的知识,以及我们如何使用它们来跳过一些因为太远不可能会碰到的物体,从而加快碰撞检测的速度。

Note: Although this tutorial is written using Java, you should be able to use the same techniques and concepts in almost any game development environment.

注意:尽管本文使用java书写,你可以在任何游戏开发环境中使用相同的技术和概念。


Introduction


引言

Collision detection is an essential part of most video games. Both in 2D and 3D games, detecting when
two objects have collided is important as poor collision detection can lead to some very interesting results:

碰撞检测是大部分游戏的关键部分。不论在2D还是3D游戏中,检测两个物体是否发生碰撞都十分的重要,糟糕的碰撞检测会导致一些奇异的结果:

However, collision detection is also a very expensive operation. Let’s say there are 100 objects that need to be checked for collision. Comparing each pair of objects requires 10,000 operations - that’s a lot of checks!

然而,碰撞检测也是一种异常耗费的操作。对于100个需要进行碰撞检测的物体而言,你需要执行10000次碰撞检测操作。真的很多!

One way to speed things up is to reduce the number of checks that have to be made. Two objects that are at opposite ends of the screen can not possibly collide, so there is no need to check for a collision between them. This is where a quadtree comes into play.

一个加速的方法是减少检测数量。两个物体在屏幕相反的两边是绝对不会发生碰撞的,所以没必要检测他们之间的碰撞。由此我们引入四叉树。


What Is a Quadtree?


什么是四叉树

A quadtree is a data structure used to divide a 2D region into more manageable parts. It's an extended binary
tree, but instead of two child nodes it has four.

四叉树是一种划分2D区域 为多个可管理部分的数据结构。他是二叉树的拓展,将2个子节点替换为了4个子节点。

In the images below, each image is a visual representation of the 2D space and the red squares represent objects. For the purposes of this article, subnodes will be labelled counter-clockwise as follows:

在下图中,每张图片展示了一个2D空间,红色的四边形代表对象,子节点将会以逆时针的方式进行编号:



A quadtree starts as a single node. Objects added to the quadtree are added to the single node.

四叉树由一个节点开始,对象会被添加到这个节点上。



When more objects are added to the quadtree, it will eventually split into four subnodes. Each object will then be put into one of these subnodes according to where it lies in the 2D space. Any object that cannot fully fit inside a node’s boundary will be placed
in the parent node.

当更多的节点添加到四叉树时,它最终会分裂成4个节点。每个对象根据其在2D空间中的位置,划分为子节点的一部分。任何不能完全归于某个子节点的对象会被放在根节点(最终做拆分,拆分到对应象限。比如同时处于2,3象限,就将其拆分到2,3象限中)



Each subnode can continue subdividing as more objects are added.

当更多对象加入时,每个子节点可以继续划分。



As you can see, each node only contains a few objects. We know then that, for instance, the objects in the top-left node cannot be colliding with the objects in the bottom-right node, so we don't need to run an expensive collision detection algorithm between
such pairs.

如你所见,每个节点只包含了一些对象。如你所知,左上节点中的对象不会与右下节点中的对象发生碰撞。所以我们无需对不同象限中的对象进行碰撞检测。

Take a look at this JavaScript example to see a quadtree in action.

看下JS例子中四叉树的实现。


Implementing a Quadtree


实现一颗四叉树

Implementing a quadtree is fairly simple. The following code is written in Java, but the same techniques can be used for most other programming languages. I’ll comment after each code snippet.

实现一个四叉树还是很简单的。以下代码用Java书写,也可用其他编程进行实现。

We’ll start off by creating the main Quadtree class. Below is the code for
Quadtree.java.


The
Quadtree
class is straightforward.
MAX_OBJECTS
defines
how many objects a node can hold before it splits and
MAX_LEVELS
defines the deepest level
subnode.
Level
is the current node level (0 being the topmost node),
bounds
represents
the 2D space that the node occupies, and
nodes
are the four subnodes.

In this example, the objects the quadtree will hold are
Rectangles
, but for your own quadtree
it can be whatever you want.

Next, we’ll implement the five methods of a quadtree:
clear
,
split
,
getIndex
,
insert
,
and
retrieve
.

这个四叉树很直观。MAX_OBJECT定义了一个子节点在添加了多少个对象后需要进行分裂。MAX_LEVEL定义了最深的子节点层级。LEVEL是当前节点层级(0代表顶层节点),bounds表示2D空间,nodes有四格子节点。

在这个例子中,四叉树中的对象都是矩形,但对于你自己的四叉树他可以是任意的你想要的形状。

下一步,我们会实现四叉树的5个方法:clear,split,getIndex,insert和retrieve。

The
clear
method clears the quadtree by recursively clearing all objects from all nodes.

clear方法递归清理了四叉树中所有节点中的对象。

The
split
method splits the node into four subnodes by dividing the node into four equal
parts and initializing the four subnodes with the new bounds.

split方法通过等分将节点分裂成4个子节点,然后对四格子节点用新的bounds进行初始化。

The
getIndex
method is a helper function of the quadtree. It determines where an object
belongs in the quadtree by determining which node the object can fit into.

getIndex方法是一个四叉树的帮助函数。在四叉树里他决定了一个节点的归属,通过检查节点属于哪个象限。

The
insert
method is where everything comes together. The method first determines whether
the node has any child nodes and tries to add the object there. If there are no child nodes or the object doesn’t fit in a child node, it adds the object to the parent node.

insert方法将对象插入四叉树中。这个方法首先决定节点是否有子节点,然后尝试添加对象。如果没有子节点或者对象跨节点,则将其加入父节点。

Once the object is added, it determines whether the node needs to split by checking if the current number of objects exceeds the max allowed objects. Splitting will cause the node to insert any object that can fit in a child node to be added to the child node;
otherwise the object will stay in the parent node.

一旦对象添加后,它根据当前对象是否超过最大值来决定节点是否需要被分裂。分裂操作会重复之前的过程,跨象限的节点被留在父节点,其他分配到子节点中去。

The final method of the quadtree is the
retrieve
method. It returns all objects in all nodes
that the given object could potentially collide with. This method is what helps to reduce the number of pairs to check collision against.

最后一个四叉树方法是retrieve方法。他返回了与指定节点可能发生碰撞的所有节点。这个方法极大的减少了碰撞检测的次数。


Using This for 2D Collision Detection


在2D碰撞检测中使用这种方法

Now that we have a fully functional quadtree, it’s time to use it to help reduce the checks needed for collision detection.

In a typical game, you’ll start by creating the quadtree and passing the bounds of the screen.

现在我们有一个完整功能的四叉树方法,是时候使用它来帮助我们减少碰撞检测了。

At every frame, you’ll insert all objects into the quadtree by first clearing the quadtree then using the
insert
method
for every object.

在每一帧,我们都先清除四叉树再用insert方法将对象插入其中。

Once all objects have been inserted, you’ll go through each object and retrieve a list of objects it could possibly collide with. You'll then check for collisions between each object in the list and the initial object, using a collision detection algorithm.

一旦所有对象完成插入,你可以遍历所有对象,然后得到一个潜在碰撞对象列表。之后你可以就可以使用碰撞检测算法对列表中的每个对象进行碰撞检测。

Note: Collision detection algorithms are beyond the scope of this tutorial. See
this article for an example.

注意:碰撞检测算法已经超出本文讨论的范畴。


Conclusion


结论

Collision detection can be an expensive operation and can slow down the performance of your game. Quadtrees are one way you can help speed up collision detection and keep your game running at top speeds.

碰撞检测是一种耗时的操作,可能会导致游戏性能的损失。四叉树是一种可以加速碰撞检测保证游戏流畅运行的方法。

Related Posts

Make Your Game Pop With Particle
Effects and Quadtrees
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: