Skip to content

Commit

Permalink
1.2.0: store objects on leaf nodes only
Browse files Browse the repository at this point in the history
  • Loading branch information
timohausmann committed Mar 2, 2020
1 parent eed2028 commit f85c65b
Show file tree
Hide file tree
Showing 9 changed files with 554 additions and 104 deletions.
32 changes: 25 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# quadtree-js

This is a JavaScript Quadtree implementation of the Java Methods described on [gamedevelopment.tutsplus.com by Steven Lambert](https://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space--gamedev-374):
This is a JavaScript Quadtree implementation based on the Java Methods described on [gamedevelopment.tutsplus.com by Steven Lambert](https://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space--gamedev-374):

> 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. 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.
Please read the tutorial for a better understanding.
This implementation can store and retrieve rectangles in a recursive 2D Quadtree. Every Quadtree node can hold a maximum of number objects before it splits into four subnodes. Objects are only stored on leaf nodes (the lowest level). If an object overlaps into multiple leaf nodes, a reference to the object is stored in each node.

## Demos

* [Simple Demo](http://timohausmann.de/quadtree.js/simple.html) – add static objects and see the Quadtree split
* [Dynamic Demo](http://timohausmann.de/quadtree.js/dynamic.html) – continuously track moving objects
* [Benchmark v1.2](http://timohausmann.de/quadtree.js/test-10000-1.2.0.html) - Performance test with 10.000 objects
* [Benchmark v1.1.3](http://timohausmann.de/quadtree.js/test-10000-1.1.3.html) - Performance test with 10.000 objects (old implementation)

## Install

Expand Down Expand Up @@ -45,14 +47,15 @@ var myTree = new Quadtree({

> MAX_OBJECTS defines how many objects a node can hold before it splits and MAX_LEVELS defines the deepest level subnode.
If you want to specify max_objects and max_levels on your own, you can pass them as a 2nd and 3rd argument
If you want to specify `max_objects` and `max_levels` on your own, you can pass them as a 2nd and 3rd argument. Increasing `max_levels` may have an impact on performance depending on your objects. Using a low value for `max_levels` increases the Quadtree performance but will most likely return more candidates.

<pre>
var myTree = new Quadtree({
x: 0,
y: 0,
width: 800,
height: 600
}, 5, 8);
}, 15, 6);
</pre>

Insert an element in the Quadtree
Expand All @@ -65,7 +68,7 @@ myTree.insert({
});
</pre>

Retrieve elements that "collide" with the given bounds
Retrieve elements from nodes that intersect with the given bounds
<pre>
var elements = myTree.retrieve({
x: 150,
Expand All @@ -82,5 +85,20 @@ myTree.clear();

Check out the examples for more information.

There is an alternative [quadtree-js hitman branch](https://github.com/timohausmann/quadtree-js/tree/hitman) available that allows you to update and remove single objects.
This can be handy when most of the objects in your Quadtree are static.
## Browser Support

This library is supported in all modern browsers beginning from IE9 and above.

## Changelog

### 1.2.0

This implementation now stores objects exclusively on leaf nodes and thus differs from the tutorial it's based on. Objects, that overlap into multiple subnodes are now referenced in each matching subnode instead of their parent node. This drastically reduces the collision candidates. Prior to 1.2.0, overlapping objects were stored in parent nodes.

### 1.1.3

Support for npm and `module.exports`

## Update single objects

There is a (currently deprecated) [quadtree-js hitman branch](https://github.com/timohausmann/quadtree-js/tree/hitman) available that allows you to update and remove single objects. This may be handy when most of the objects in your Quadtree are static. Please raise an issue if you want to see this feature maintained in future releases.
6 changes: 3 additions & 3 deletions examples/dynamic.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!doctype html>
<html>
<head>
<title>Quadtree-js</title>
<title>quadtree-js Dynamic Demo</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
Expand Down Expand Up @@ -107,12 +107,12 @@ <h1><a href="https://github.com/timohausmann/quadtree-js">quadtree-js</a> <small
}
</pre>

<p>
<!--p>
When you deal mostly with static objects, rewriting the whole tree each loop may seems like an overkill.
</p>
<p>
If you have the urge to update or remove single objects without affecting the whole quadtree, you may check out the <a href="https://github.com/timohausmann/quadtree-js/tree/hitman">quadtree-js hitman branch</a>.
</p>
</p-->

<p>
<a href="https://github.com/timohausmann/quadtree-js">quadtree-js at github</a>
Expand Down
52 changes: 31 additions & 21 deletions examples/simple.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!doctype html>
<html>
<head>
<title>Quadtree-js</title>
<title>quadtree-js Simple Demo</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
Expand All @@ -16,8 +16,9 @@ <h1><a href="https://github.com/timohausmann/quadtree-js">quadtree-js</a> <small

<div class="ctrl">
<div class="ctrl-left">
<button id="btn_add">add random object</button>
<button id="btn_add_10">add 10 objects</button>
<button id="btn_add">add small object</button>
<button id="btn_add_big">add big object</button>
<button id="btn_add_10">add 10 small objects</button>
<button id="btn_clear">clear tree</button>
</div>

Expand All @@ -31,7 +32,7 @@ <h1><a href="https://github.com/timohausmann/quadtree-js">quadtree-js</a> <small
This quadtree starts off empty. Feel free to add elements to the quadtree.
</p>
<p>
After adding five objects to the quadtree it should split, because we initially set max_objects to 4.
After adding five objects to the quadtree it will split, because we initially set max_objects to 4.
</p>
<pre>
var myTree = new Quadtree({
Expand Down Expand Up @@ -184,25 +185,23 @@ <h1><a href="https://github.com/timohausmann/quadtree-js">quadtree-js</a> <small
/*
* add a random object to our simulation
*/
var handleAdd = function() {

var grid = 8,
gridh = myTree.bounds.width/grid,
gridv = myTree.bounds.height/grid;

var rndObj = {
x : randMinMax(0, gridh, true)*grid,
y : randMinMax(0, gridv, true)*grid,
width : randMinMax(1, 4, true)*grid,
height : randMinMax(1, 4, true)*grid,
check : false
};
var handleAdd = function( rect ) {

if(!rect) {
rect = {
x : randMinMax(0, myTree.bounds.width-32),
y : randMinMax(0, myTree.bounds.height-32),
width : randMinMax(4, 32, true),
height : randMinMax(4, 32, true),
check : false
};
}

//store object in our array
myObjects.push( rndObj );
myObjects.push( rect );

//insert object in our quadtree
myTree.insert( rndObj );
myTree.insert( rect );

//update total counter
updateTotal();
Expand Down Expand Up @@ -307,7 +306,7 @@ <h1><a href="https://github.com/timohausmann/quadtree-js">quadtree-js</a> <small

//retrieve all objects in the bounds of the hero
candidates = myTree.retrieve( myCursor );

//flag retrieved objects
for( i=0;i<candidates.length;i=i+1 ) {
candidates[ i ].check = true;
Expand Down Expand Up @@ -344,7 +343,18 @@ <h1><a href="https://github.com/timohausmann/quadtree-js">quadtree-js</a> <small
document.getElementById('canvas').addEventListener('mouseout', handleMouseout);

//set eventListener for buttons
document.getElementById('btn_add').addEventListener('click', handleAdd);
document.getElementById('btn_add').addEventListener('click', function() {
handleAdd();
});
document.getElementById('btn_add_big').addEventListener('click', function() {
handleAdd({
x : randMinMax(0, myTree.bounds.width/2),
y : randMinMax(0, myTree.bounds.height/2),
width : randMinMax(myTree.bounds.height/4, myTree.bounds.height/2, true),
height : randMinMax(myTree.bounds.height/4, myTree.bounds.height/2, true),
check : false
});
});
document.getElementById('btn_add_10').addEventListener('click', function() {
for(var i=0;i<10;i++) { handleAdd() };
});
Expand Down
Loading

0 comments on commit f85c65b

Please sign in to comment.