// Returns normVectord vector function normVector(v) { var length = v[0] * v[0] + v[1] * v[1]; // square length will do return [v[0] / length, v[1] / length]; } // Find minimum and maximum projections of each vertex on the axis function project(v, axis) { var min = Infinity; var max = -Infinity; for (var i = 0, len = v.length; i < len; i++) { var vertex = v[i]; // dot product var projection = vertex[0] * axis[0] + vertex[1] * axis[1]; if (projection < min) min = projection; if (projection > max) max = projection; } return [min, max]; } // Axes for which we'll test stuff. // Two for each box, because testing for parallel axes isn't needed function getPerpendicularAxes(v1, v2) { const axes = new Array(4); let a, b, n, tmp; a = v1[1], b = v1[0]; n = normVector([a[0] - b[0], a[1] - b[1]]); // normalize tmp = n[0]; n[0] = - n[1]; n[1] = tmp; // perpendicular vector axes[0] = n; a = v1[2]; b = v1[1]; n = normVector([a[0] - b[0], a[1] - b[1]]); // normalize tmp = n[0]; n[0] = - n[1]; n[1] = tmp; // perpendicular vector axes[1] = n; a = v2[1]; b = v2[0]; n = normVector([a[0] - b[0], a[1] - b[1]]); // normalize tmp = n[0]; n[0] = - n[1]; n[1] = tmp; // perpendicular vector axes[2] = n; a = v2[2]; b = v2[1]; n = normVector([a[0] - b[0], a[1] - b[1]]); // normalize tmp = n[0]; n[0] = - n[1]; n[1] = tmp; // perpendicular vector axes[3] = n; return axes; } // Separating Axis Theorem (SAT) collision test // Minimum Translation Vector (MTV) is returned for the first Oriented Bounding Box (OBB) function testCollision(v1, v2) { var axes = getPerpendicularAxes(v1, v2); // we need to find the minimal overlap and axis on which it happens var minOverlap = Infinity; for (var a = 0, aa = axes.length; a < aa; a++) { var axis = axes[a]; var p1 = project(v1, axis); var p2 = project(v2, axis); var overlap = (p1[0] <= p2[1] && p1[1] >= p2[0]) ? Math.min(p1[1], p2[1]) - Math.max(p1[0], p2[0]) : 0; if (overlap === 0) return false; // shapes are not overlapping // else if (overlap < minOverlap) minOverlap = overlap; } return true; }