Skip to content

Instantly share code, notes, and snippets.

@milani
Created March 16, 2011 21:15
Show Gist options
  • Save milani/873320 to your computer and use it in GitHub Desktop.
Save milani/873320 to your computer and use it in GitHub Desktop.
Collision detection with javascript using interval tree
// Collision detection with javascript using semi-interval tree.
// Add elements using insert function, then check collision using hasCollision.
var collisionTree = {
LEFT: 1,
RIGHT: 0,
INTERSECT: 2,
nodes:null,
margin: 1,
init: function(margin){
this.nodes = new Array();
if(margin!=undefined) this.margin = margin;
},
insert: function(element){
var node = {
position:{
top: parseInt(element.style.top),
right: parseInt(element.style.left) + parseInt(element.style.width),
bottom: parseInt(element.style.top) + parseInt(element.style.height),
left: parseInt(element.style.left),
},
divisor: parseInt(element.style.left),
id: element.id,
left: null,
right: null,
};
if(this.nodes.length == 0){
this.nodes.push(node);
}else{
this.nodes[0] = this._pushDown(this.nodes[0],node);
}
},
hasCollision: function(element){
if(this.nodes.length == 0) return false;
var node = {
position:{
top: parseInt(element.style.top),
right: parseInt(element.style.left) + parseInt(element.style.width),
bottom: parseInt(element.style.top) + parseInt(element.style.height),
left: parseInt(element.style.left),
},
};
return this._testCollision(this.nodes[0],node);
},
debug: function(){
//console.log(this.nodes);
this.traverseTree(this.nodes[0]);
},
_testCollision: function(root,node){
if(this._checkCollision(root,node)){
return true;
}else{
var result = this._test(root.divisor,node);
switch(result){
case this.LEFT:
if(root.left == null)
return false;
else
return this._testCollision(root.left,node);
break;
case this.RIGHT:
if(root.right == null)
return false;
else
return this._testCollision(root.right,node);
break;
case this.INTERSECT:
var newNodes = this._splice(node,root.divisor);
var hasCollision = false;
if(root.right == null)
hasCollision = false;
else
hasCollision = this._testCollision(root.right,newNodes.right);
if(hasCollision) return true;
if(root.left == null)
hasCollision = false;
else
hasCollision = this._testCollision(root.left,newNodes.left);
return hasCollision;
break;
}
}
},
_checkCollision: function(node1,node2){
var pos1 = node1.position;
var pos2 = node2.position;
return ( (pos1.left - this.margin) <= (pos2.right + this.margin) &&
(pos1.right + this.margin) >= (pos2.left - this.margin) &&
(pos1.top - this.margin) <= (pos2.bottom + this.margin) &&
(pos1.bottom + this.margin) >= (pos2.top - this.margin)
);
},
_pushDown: function(root,node){
var result = this._test(root.divisor,node);
switch(result){
case this.LEFT:
if(root.left == null)
root.left = node;
else
root.left = this._pushDown(root.left,node);
break;
case this.RIGHT:
if(root.right == null)
root.right = node;
else
root.right = this._pushDown(root.right,node);
break;
case this.INTERSECT:
var newNodes = this._splice(node,root.divisor);
if(root.right == null)
root.right = newNodes.right;
else
root.right = this._pushDown(root.right,newNodes.right);
if(root.left == null)
root.left = newNodes.left;
else
root.left = this._pushDown(root.left,newNodes.left);
break;
}
return root;
},
_test: function(divisor,newNode){
if( newNode.position.left < divisor && divisor < newNode.position.right ){
return this.INTERSECT;
}else if(divisor <= newNode.position.left) {
return this.RIGHT;
}else{
return this.LEFT;
}
},
_splice: function(node,divisor){
var nodes = {
left:{
position:{
left: node.position.left,
top: node.position.top,
right: divisor,
bottom: node.position.bottom,
},
id: node.id+'-left',
divisor: node.position.left,
left: null,
right: null,
},
right:{
position:{
left: divisor,
top: node.position.top,
bottom: node.position.bottom,
right: node.position.right,
},
id: node.id+'-right',
divisor: divisor,
left: null,
right: null,
}
};
return nodes;
},
_traverseTree: function(root){
if(root == null) return;
var newElem = document.createElement('div');
$(newElem).addClass('itemd').width(root.position.right-root.position.left+'px').height(root.position.bottom-root.position.top+'px').attr('id',root.id);
$(newElem).appendTo('.debug');
var sep1 = document.createElement('div');
$(sep1).addClass('clearfix');
$(sep1).appendTo('.debug');
this.traverseTree(root.left);
this.traverseTree(root.right);
var sep = document.createElement('div');
$(sep).addClass('clearfix');
$(sep).appendTo('.debug');
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment