Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Collision detection on pixel level
function collisionDetection() {
/*
* private function initialize()
*
* Initializes the object
*
*/
this.initialize = function() {}
/*
* public function hitTest()
*
* Checks if two objects collide. First with box-model detection
* and then on a per-pixel detection.
*
* Both source and target objects are expected to look like this:
*
* {
* x: (Number) current x position,
* y: (Number) current y position,
* width: (Number) object height,
* height: (Number) object width,
* pixelmap: (Object) pixel map object generated from buildPixelMap()
* }
*
* @param source (Object) The source object
* @param target (Object) The target object
*
* @return boolean, true on collision
*
*/
this.hitTest = function( source, target ) {
var hit = false;
var start = new Date().getTime();
if( this.boxHitTest( source, target ) ) {
if( this.pixelHitTest( source, target ) ) {
hit = true;
}
}
var end = new Date().getTime();
if( hit == true ){
//console.log( 'detection took: ' + (end - start) + 'ms' );
}
return hit;
}
/*
* private function boxHitTest()
*
* Checks if two objects collide with box-model detection.
*
* Both source and target objects are expected to look like this:
*
* {
* x: (Number) current x position,
* y: (Number) current y position,
* width: (Number) object height,
* height: (Number) object width
* }
*
* @param source (Object) The source object
* @param target (Object) The target object
*
* @return boolean, true on collision
*
*/
this.boxHitTest = function( source, target ) {
return !(
( ( source.y + source.height ) < ( target.y ) ) ||
( source.y > ( target.y + target.height ) ) ||
( ( source.x + source.width ) < target.x ) ||
( source.x > ( target.x + target.width ) )
);
}
/*
* private function pixelHitTest()
*
* Checks if two objects collide on a per-pixel detection.
*
* Both source and target objects are expected to look like this:
*
* {
* x: (Number) current x position,
* y: (Number) current y position,
* width: (Number) object height,
* height: (Number) object width,
* height: (Number) object width,
* pixelmap: (Object) pixel map object generated from buildPixelMap()
* }
*
* @param source (Object) The source object
* @param target (Object) The target object
*
* @return boolean, true on collision
*
*/
this.pixelHitTest = function( source, target ) {
var top = parseInt( Math.max( source.y, target.y ) );
var bottom = parseInt( Math.min(source.y+source.height, target.y+target.height) );
var left = parseInt( Math.max(source.x, target.x) );
var right = parseInt( Math.min(source.x+source.width, target.x+target.width) );
for (var y = top; y < bottom; y++)
{
for (var x = left; x < right; x++)
{
var pixel1 = source.pixelMap.data[ (x - source.x) +"_"+ (y - source.y) ];
var pixel2 = target.pixelMap.data[ (x - target.x) +"_"+ (y - target.y) ];
if( !pixel1 || !pixel2 ) {
continue;
};
if (pixel1.pixelData[3] == 255 && pixel2.pixelData[3] == 255)
{
return true;
}
}
}
return false;
}
/*
* public function buildPixelMap()
*
* Creates a pixel map on a canvas image. Everything
* with a opacity above 0 is treated as a collision point.
* Lower resolution (higher number) will generate a faster
* but less accurate map.
*
*
* @param source (Object) The canvas object
* @param resolution (int)(DEPRECATED!) The resolution of the map
*
* @return object, a pixelMap object
*
*/
this.buildPixelMap = function( source ) {
var resolution = 1;
var ctx = source.getContext("2d");
var pixelMap = [];
for( var y = 0; y < source.height; y++) {
for( var x = 0; x < source.width; x++ ) {
var dataRowColOffset = y+"_"+x;//((y * source.width) + x);
var pixel = ctx.getImageData(x,y,resolution,resolution);
var pixelData = pixel.data;
pixelMap[dataRowColOffset] = { x:x, y:y, pixelData: pixelData };
}
}
return {
data: pixelMap,
resolution: resolution
};
}
// Initialize the collider
this.initialize();
// Return our outward facing interface.
return {
hitTest: this.hitTest.bind( this ),
buildPixelMap: this.buildPixelMap.bind( this )
};
};
@onderaltintas

This comment has been minimized.

Copy link

@onderaltintas onderaltintas commented Jan 12, 2018

This is great. Thank you.

@Sv443

This comment has been minimized.

Copy link

@Sv443 Sv443 commented Oct 19, 2018

Can you please tell us how to use this class? I don't really understand it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment