快速教程:在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空间中使用四叉树实现碰撞检测
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书写,你可以在任何游戏开发环境中使用相同的技术和概念。
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.
一个加速的方法是减少检测数量。两个物体在屏幕相反的两边是绝对不会发生碰撞的,所以没必要检测他们之间的碰撞。由此我们引入四叉树。
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 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
The
how many objects a node can hold before it splits and
subnode.
the 2D space that the node occupies, and
In this example, the objects the quadtree will hold are
it can be whatever you want.
Next, we’ll implement the five methods of a quadtree:
and
这个四叉树很直观。MAX_OBJECT定义了一个子节点在添加了多少个对象后需要进行分裂。MAX_LEVEL定义了最深的子节点层级。LEVEL是当前节点层级(0代表顶层节点),bounds表示2D空间,nodes有四格子节点。
在这个例子中,四叉树中的对象都是矩形,但对于你自己的四叉树他可以是任意的你想要的形状。
下一步,我们会实现四叉树的5个方法:clear,split,getIndex,insert和retrieve。
The
clear方法递归清理了四叉树中所有节点中的对象。
The
parts and initializing the four subnodes with the new bounds.
split方法通过等分将节点分裂成4个子节点,然后对四格子节点用新的bounds进行初始化。
The
belongs in the quadtree by determining which node the object can fit into.
getIndex方法是一个四叉树的帮助函数。在四叉树里他决定了一个节点的归属,通过检查节点属于哪个象限。
The
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
that the given object could potentially collide with. This method is what helps to reduce the number of pairs to check collision against.
最后一个四叉树方法是retrieve方法。他返回了与指定节点可能发生碰撞的所有节点。这个方法极大的减少了碰撞检测的次数。
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
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.
注意:碰撞检测算法已经超出本文讨论的范畴。
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
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 whentwo 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 binarytree, 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.
Quadtreeclass is straightforward.
MAX_OBJECTSdefines
how many objects a node can hold before it splits and
MAX_LEVELSdefines the deepest level
subnode.
Levelis the current node level (0 being the topmost node),
boundsrepresents
the 2D space that the node occupies, and
nodesare 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。
clearmethod clears the quadtree by recursively clearing all objects from all nodes.
clear方法递归清理了四叉树中所有节点中的对象。
splitmethod 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进行初始化。
getIndexmethod 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方法是一个四叉树的帮助函数。在四叉树里他决定了一个节点的归属,通过检查节点属于哪个象限。
insertmethod 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.
一旦对象添加后,它根据当前对象是否超过最大值来决定节点是否需要被分裂。分裂操作会重复之前的过程,跨象限的节点被留在父节点,其他分配到子节点中去。
retrievemethod. 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.
现在我们有一个完整功能的四叉树方法,是时候使用它来帮助我们减少碰撞检测了。
insertmethod
for every object.
在每一帧,我们都先清除四叉树再用insert方法将对象插入其中。
一旦所有对象完成插入,你可以遍历所有对象,然后得到一个潜在碰撞对象列表。之后你可以就可以使用碰撞检测算法对列表中的每个对象进行碰撞检测。
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
相关文章推荐
- 安卓源代码修改之framework下面长按power键,修改安卓原生的关机、重启界面(一)
- C++第一次实验+1
- Cron表达式
- java运行时数据区划分
- 微信开发入门-1
- 由于SSH配置文件的不匹配,导致的Permission denied (publickey)及其解决方法
- CodeForces 622A Infinite Sequence
- 底部弹出的pop
- 简单的滑动解锁
- MySQL索引类型总结和使用技巧以及注意事项
- Eclipse配置Tomcat
- Unity3D_Align With View 和Align View to Selected 相关用法
- easyui textBox控件,监听事件不好使的解决办法
- VC2008中影响exe大小和速度的全部编译选项
- 解决 Javascript 中 atob 方法解码中文字符乱码问题
- url解析
- C 小写字母编程大写并输出
- 15. 3Sum
- centos7下基于xampp的testlink安装部署
- Django笔记 使用Celery来进行定时Batch任务