Skip to content

Instantly share code, notes, and snippets.

@yetanotherportfolio
Created August 19, 2012 17:57
Show Gist options
  • Save yetanotherportfolio/3396752 to your computer and use it in GitHub Desktop.
Save yetanotherportfolio/3396752 to your computer and use it in GitHub Desktop.
javscript collision detection with rotated rect and such
//code inspired by http://www.ragestorm.net/tutorial?id=22
var Vect = function(x, y)
{
this.x = x || 0;
this.y = y || 0;
}
var Rect = function(pos, size, angle)
{
this.pos = pos || new Vect();
this.size = size || new Vect();
this.angle = angle || 0;
};
function AddVectors2D(v1, v2)
{
v1.x += v2.x;
v1.y += v2.y;
}
function SubVectors2D(v1, v2)
{
v1.x -= v2.x;
v1.y -= v2.y;
}
function RotateVector2DClockwise(v, ang)
{
var t,
cosa = Math.cos(ang),
sina = Math.sin(ang);
t = v.x;
v.x = t*cosa + v.y*sina;
v.y = -t*sina + v.y*cosa;
}
function toRadian(angle)
{
return angle * Math.PI /180;
}
/**
* int RotRectsCollision(Rect * rr1, Rect * rr2)
*/
function RotRectsCollision(rr1, rr2)
{
var A = new Vect();// vertices of the rotated rr2
var B = new Vect();
var C = new Vect();// center of rr2
var BL = new Vect();// vertices of rr2 (bottom-left, top-right)
var TR = new Vect();
var ang = toRadian(rr1.angle - rr2.angle); // orientation of rotated rr1
var cosa = Math.cos(ang); // precalculated trigonometic -
var sina = Math.sin(ang); // - values for repeated use
var t, x, a; // temporary variables for various uses
var dx; // deltaX for linear equations
var ext1, ext2; // min/max vertical values
// move rr2 to make rr1 cannonic
C.x = rr2.pos.x;
C.y = rr2.pos.y;
SubVectors2D(C, rr1.pos);
// rotate rr2 clockwise by rr2.angle to make rr2 axis-aligned
RotateVector2DClockwise(C, toRadian(rr2.angle));
// calculate vertices of (moved and axis-aligned := 'ma') rr2
BL = TR = C;
SubVectors2D(BL, rr2.size);
AddVectors2D(TR, rr2.size);
// calculate vertices of (rotated := 'r') rr1
A.x = -rr1.size.y*sina;
B.x = A.x;
t = rr1.size.x*cosa;
A.x += t;
B.x -= t;
A.y = rr1.size.y*cosa;
B.y = A.y;
t = rr1.size.x*sina;
A.y += t;
B.y -= t;
t = sina*cosa;
// verify that A is vertical min/max, B is horizontal min/max
if (t < 0)
{
t = A.x;
A.x = B.x;
B.x = t;
t = A.y;
A.y = B.y;
B.y = t;
}
// verify that B is horizontal minimum (leftest-vertex)
if (sina < 0)
{
B.x = -B.x;
B.y = -B.y;
}
// if rr2(ma) isn't in the horizontal range of
// colliding with rr1(r), collision is impossible
if (B.x > TR.x || B.x > -BL.x)
return 0;
// if rr1(r) is axis-aligned, vertical min/max are easy to get
if (t == 0)
{
ext1 = A.y;
ext2 = -ext1;
}
// else, find vertical min/max in the range [BL.x, TR.x]
else
{
x = BL.x-A.x;
a = TR.x-A.x;
ext1 = A.y;
// if the first vertical min/max isn't in (BL.x, TR.x), then
// find the vertical min/max on BL.x or on TR.x
if (a*x > 0)
{
dx = A.x;
if (x < 0)
{
dx -= B.x;
ext1 -= B.y;
x = a;
}
else
{
dx += B.x;
ext1 += B.y;
}
ext1 *= x;
ext1 /= dx;
ext1 += A.y;
}
x = BL.x+A.x;
a = TR.x+A.x;
ext2 = -A.y;
// if the second vertical min/max isn't in (BL.x, TR.x), then
// find the local vertical min/max on BL.x or on TR.x
if (a*x > 0)
{
dx = -A.x;
if (x < 0)
{
dx -= B.x;
ext2 -= B.y;
x = a;
}
else
{
dx += B.x;
ext2 += B.y;
}
ext2 *= x;
ext2 /= dx;
ext2 -= A.y;
}
}
// check whether rr2(ma) is in the vertical range of colliding with rr1(r)
// (for the horizontal range of rr2)
return !((ext1 < BL.y && ext2 < BL.y) ||
(ext1 > TR.y && ext2 > TR.y));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment