Skip to content

Instantly share code, notes, and snippets.

@LaudemPax
Created March 16, 2013 02:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LaudemPax/5174704 to your computer and use it in GitHub Desktop.
Save LaudemPax/5174704 to your computer and use it in GitHub Desktop.
My Quadtree
public class Quadtree {
//maximum entities in each sector
private int MAX_ENT = 10;
//maximum number of levels
private int MAX_LEVELS = 5;
private int level;
private Array<Entity> collideEntities;
private Rectangle bounds;
private Quadtree[] nodes;
public Quadtree(int pLevel, Rectangle pBounds) {
level = pLevel;
collideEntities = new Array<Entity>();
bounds = pBounds;
nodes = new Quadtree[4];
}
/*
* Clears the Quadtree
*/
public void clear(){
collideEntities.clear();
for(int i = 0; i < nodes.length;i++){
if(nodes[i] != null){
nodes[i].clear();
nodes[i] = null;
}
}
}
/*
* Splits the node into 4 sub-nodes
*/
private void split(){
int subWidth = (int)(bounds.getWidth() / 2);
int subHeight = (int)(bounds.getHeight() / 2);
int x = (int)bounds.getX();
int y = (int)bounds.getY();
nodes[0] = new Quadtree(level+1, new Rectangle(x + subWidth, y, subWidth, subHeight));
nodes[1] = new Quadtree(level+1, new Rectangle(x, y, subWidth, subHeight));
nodes[2] = new Quadtree(level+1, new Rectangle(x, y + subHeight, subWidth, subHeight));
nodes[3] = new Quadtree(level+1, new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight));
}
/*
* Determine which node the object belongs to. -1 means
* object cannot completely fit within a child node and is part
* of the parent node
*/
private int getIndex(Entity e){
int index = -1;
double verticalMidpoint = bounds.getX() + (bounds.getWidth() / 2);
double horizontalMidpoint = bounds.getY() + (bounds.getHeight() / 2);
//takes into account the inverted y of libgdx
boolean topQuadrant = (e.hitBox.y > horizontalMidpoint);
boolean bottomQuadrant = (e.hitBox.y < horizontalMidpoint && e.hitBox.y + e.hitBox.getHeight() < horizontalMidpoint);
//checks if in the right quadrant...
if(e.hitBox.x > verticalMidpoint)
//places in top right
if(topQuadrant){
index = 1;
//places in bottom right
}else if(bottomQuadrant){
index = 3;
}
//checks if in the left quadrant...
if(e.hitBox.x < verticalMidpoint && e.hitBox.x + e.hitBox.getWidth() < verticalMidpoint )
//places in top left
if(topQuadrant){
index = 0;
//places in top right
}else if(bottomQuadrant){
index = 2;
}
return index;
}
/*
* Determine which node the object belongs to. -1 means
* object cannot completely fit within a child node and is part
* of the parent node but this time takes a rectangle as an
* argument
*/
private int getIndex(Rectangle rect){
int index = -1;
double verticalMidpoint = bounds.getX() + (bounds.getWidth() / 2);
double horizontalMidpoint = bounds.getY() + (bounds.getHeight() / 2);
//takes into account the inverted y of libgdx
boolean topQuadrant = (rect.y > horizontalMidpoint);
boolean bottomQuadrant = (rect.y < horizontalMidpoint && rect.y + rect.getHeight() < horizontalMidpoint);
//checks if in the right quadrant...
if(rect.x > verticalMidpoint)
//places in top right
if(topQuadrant){
index = 1;
//places in bottom right
}else if(bottomQuadrant){
index = 3;
}
//checks if in the left quadrant...
if(rect.x < verticalMidpoint && rect.x + rect.getWidth() < verticalMidpoint )
//places in top left
if(topQuadrant){
index = 0;
//places in top right
}else if(bottomQuadrant){
index = 2;
}
return index;
}
public void insert(Entity e){
if (nodes[0] != null) {
int index = getIndex(e);
if (index != -1) {
nodes[index].insert(e);
return;
}
}
collideEntities.add(e);
if(collideEntities.size > MAX_ENT && level < MAX_LEVELS){
if (nodes[0] == null) {
split();
}
int i = 0;
while (i < collideEntities.size) {
int index = getIndex(collideEntities.get(i));
if (index != -1) {
nodes[index].insert(collideEntities.removeIndex(i));
}else{i++;}
}
}
}
public Array<Entity> retrieve(Array<Entity> returnEntities, Entity e){
int index = getIndex(e);
if (index != -1 && nodes[0] != null) {
nodes[index].retrieve(returnEntities, e);
}
returnEntities.addAll(collideEntities);
return returnEntities;
}
public Array<Entity> retrieve(Array<Entity> returnEntities, Rectangle rect){
int index = getIndex(rect);
if (index != -1 && nodes[0] != null) {
nodes[index].retrieve(returnEntities, rect);
}
returnEntities.addAll(collideEntities);
return returnEntities;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment