diff --git a/src/physics/arcade/SAT.js b/src/physics/arcade/SAT.js index 63570ece..b72a7261 100644 --- a/src/physics/arcade/SAT.js +++ b/src/physics/arcade/SAT.js @@ -6,33 +6,7 @@ // polygons using the Separating Axis Theorem. /** @preserve SAT.js - Version 0.2 - Copyright 2013 - Jim Riecken - released under the MIT License. https://github.com/jriecken/sat-js */ -/*global define: false, module: false*/ -/*jshint shadow:true, sub:true, forin:true, noarg:true, noempty:true, - eqeqeq:true, bitwise:true, strict:true, undef:true, - curly:true, browser:true */ - -// Create a UMD wrapper for SAT. Works in: -// -// - Plain browser via global SAT variable -// - AMD loader (like require.js) -// - Node.js -// -// The quoted properties all over the place are used so that the Closure Compiler -// does not mangle the exposed API in advanced mode. -/** - * @param {*} root - The global scope - * @param {Function} factory - Factory that creates SAT module - */ -(function (root, factory) { - "use strict"; - if (typeof define === 'function' && define['amd']) { - define(factory); - } else if (typeof exports === 'object') { - module['exports'] = factory(); - } else { - root['SAT'] = factory(); - } -}(this, function () { +var SAT = (function () { "use strict"; var SAT = {}; @@ -45,7 +19,7 @@ // Create a new Vector, optionally passing in the `x` and `y` coordinates. If // a coordinate is not specified, it will be set to `0` - /** + /** * @param {?number=} x The x position. * @param {?number=} y The y position. * @constructor @@ -118,7 +92,7 @@ this['y'] = -this['y']; return this; }; - + // Normalize this vector. (make it have length of `1`) /** @@ -132,7 +106,7 @@ } return this; }; - + // Add another vector to this one. /** * @param {Vector} other The other Vector. @@ -143,7 +117,7 @@ this['y'] += other['y']; return this; }; - + // Subtract another vector from this one. /** * @param {Vector} other The other Vector. @@ -154,7 +128,7 @@ this['y'] -= other['y']; return this; }; - + // Scale this vector. An independant scaling factor can be provided // for each axis, or a single scaling factor that will scale both `x` and `y`. /** @@ -166,9 +140,9 @@ Vector.prototype['scale'] = Vector.prototype.scale = function(x,y) { this['x'] *= x; this['y'] *= y || x; - return this; + return this; }; - + // Project this vector on to another vector. /** * @param {Vector} other The vector to project onto. @@ -180,7 +154,7 @@ this['y'] = amt * other['y']; return this; }; - + // Project this vector onto a vector of unit length. This is slightly more efficient // than `project` when dealing with unit vectors. /** @@ -193,7 +167,7 @@ this['y'] = amt * other['y']; return this; }; - + // Reflect this vector on an arbitrary axis. /** * @param {Vector} axis The vector representing the axis. @@ -207,7 +181,7 @@ this['y'] -= y; return this; }; - + // Reflect this vector on an arbitrary axis (represented by a unit vector). This is // slightly more efficient than `reflect` when dealing with an axis that is a unit vector. /** @@ -222,7 +196,7 @@ this['y'] -= y; return this; }; - + // Get the dot product of this vector and another. /** * @param {Vector} other The vector to dot this one against. @@ -231,7 +205,7 @@ Vector.prototype['dot'] = Vector.prototype.dot = function(other) { return this['x'] * other['x'] + this['y'] * other['y']; }; - + // Get the squared length of this vector. /** * @return {number} The length^2 of this vector. @@ -239,7 +213,7 @@ Vector.prototype['len2'] = Vector.prototype.len2 = function() { return this.dot(this); }; - + // Get the length of this vector. /** * @return {number} The length of this vector. @@ -247,7 +221,7 @@ Vector.prototype['len'] = Vector.prototype.len = function() { return Math.sqrt(this.len2()); }; - + // ## Circle // // Represents a circle with a position and a radius. @@ -290,7 +264,7 @@ this.recalc(); } SAT['Polygon'] = Polygon; - + // Recalculates the edges and normals of the polygon. This **must** be called // if the `points` array is modified at all and the edges or normals are to be // accessed. @@ -309,7 +283,7 @@ var points = this['points']; var len = points.length; for (var i = 0; i < len; i++) { - var p1 = points[i]; + var p1 = points[i]; var p2 = i < len - 1 ? points[i + 1] : points[0]; var e = new Vector().copy(p2).sub(p1); var n = new Vector().copy(e).perp().normalize(); @@ -418,11 +392,11 @@ var w = this['w']; var h = this['h']; return new Polygon(new Vector(pos['x'], pos['y']), [ - new Vector(), new Vector(w, 0), + new Vector(), new Vector(w, 0), new Vector(w,h), new Vector(0,h) ]); }; - + // ## Response // // An object representing the result of an intersection. Contains: @@ -433,7 +407,7 @@ // - Whether the first object is entirely inside the second, and vice versa. /** * @constructor - */ + */ function Response() { this['a'] = null; this['b'] = null; @@ -465,7 +439,7 @@ */ var T_VECTORS = []; for (var i = 0; i < 10; i++) { T_VECTORS.push(new Vector()); } - + // A pool of arrays of numbers used in calculations to avoid allocating // memory. /** @@ -498,7 +472,7 @@ } result[0] = min; result[1] = max; } - + // Check whether two convex polygons are separated by the specified // axis (must be a unit vector). /** @@ -528,8 +502,8 @@ rangeB[1] += projectedOffset; // Check if there is a gap. If there is, this is a separating axis and we can stop if (rangeA[0] > rangeB[1] || rangeB[0] > rangeA[1]) { - T_VECTORS.push(offsetV); - T_ARRAYS.push(rangeA); + T_VECTORS.push(offsetV); + T_ARRAYS.push(rangeA); T_ARRAYS.push(rangeB); return true; } @@ -540,7 +514,7 @@ if (rangeA[0] < rangeB[0]) { response['aInB'] = false; // A ends before B does. We have to pull A out of B - if (rangeA[1] < rangeB[1]) { + if (rangeA[1] < rangeB[1]) { overlap = rangeA[1] - rangeB[0]; response['bInA'] = false; // B is fully inside A. Pick the shortest way out. @@ -553,7 +527,7 @@ } else { response['bInA'] = false; // B ends before A ends. We have to push A out of B - if (rangeA[1] > rangeB[1]) { + if (rangeA[1] > rangeB[1]) { overlap = rangeA[0] - rangeB[1]; response['aInB'] = false; // A is fully inside B. Pick the shortest way out. @@ -571,14 +545,14 @@ if (overlap < 0) { response['overlapN'].reverse(); } - } + } } - T_VECTORS.push(offsetV); - T_ARRAYS.push(rangeA); + T_VECTORS.push(offsetV); + T_ARRAYS.push(rangeA); T_ARRAYS.push(rangeB); return false; } - + // Calculates which Vornoi region a point is on a line segment. // It is assumed that both the line and the point are relative to `(0,0)` // @@ -588,8 +562,8 @@ /** * @param {Vector} line The line segment. * @param {Vector} point The point. - * @return {number} LEFT_VORNOI_REGION (-1) if it is the left region, - * MIDDLE_VORNOI_REGION (0) if it is the middle region, + * @return {number} LEFT_VORNOI_REGION (-1) if it is the left region, + * MIDDLE_VORNOI_REGION (0) if it is the middle region, * RIGHT_VORNOI_REGION (1) if it is the right region. */ function vornoiRegion(line, point) { @@ -617,7 +591,7 @@ * @const */ var RIGHT_VORNOI_REGION = 1; - + // ## Collision Tests // Check if two circles collide. @@ -626,7 +600,7 @@ * @param {Circle} b The second circle. * @param {Response=} response Response object (optional) that will be populated if * the circles intersect. - * @return {boolean} true if the circles intersect, false if they don't. + * @return {boolean} true if the circles intersect, false if they don't. */ function testCircleCircle(a, b, response) { // Check if the distance between the centers of the two @@ -641,7 +615,7 @@ return false; } // They intersect. If we're calculating a response, calculate the overlap. - if (response) { + if (response) { var dist = Math.sqrt(distanceSq); response['a'] = a; response['b'] = b; @@ -655,7 +629,7 @@ return true; } SAT['testCircleCircle'] = testCircleCircle; - + // Check if a polygon and a circle collide. /** * @param {Polygon} polygon The polygon. @@ -673,30 +647,30 @@ var len = points.length; var edge = T_VECTORS.pop(); var point = T_VECTORS.pop(); - + // For each edge in the polygon: for (var i = 0; i < len; i++) { var next = i === len - 1 ? 0 : i + 1; var prev = i === 0 ? len - 1 : i - 1; var overlap = 0; var overlapN = null; - + // Get the edge. edge.copy(polygon['edges'][i]); // Calculate the center of the circle relative to the starting point of the edge. point.copy(circlePos).sub(points[i]); - + // If the distance between the center of the circle and the point // is bigger than the radius, the polygon is definitely not fully in // the circle. if (response && point.len2() > radius2) { response['aInB'] = false; } - + // Calculate which Vornoi region the center of the circle is in. var region = vornoiRegion(edge, point); // If it's the left region: - if (region === LEFT_VORNOI_REGION) { + if (region === LEFT_VORNOI_REGION) { // We need to make sure we're in the RIGHT_VORNOI_REGION of the previous edge. edge.copy(polygon['edges'][prev]); // Calculate the center of the circle relative the starting point of the previous edge @@ -707,9 +681,9 @@ var dist = point.len(); if (dist > radius) { // No intersection - T_VECTORS.push(circlePos); + T_VECTORS.push(circlePos); T_VECTORS.push(edge); - T_VECTORS.push(point); + T_VECTORS.push(point); T_VECTORS.push(point2); return false; } else if (response) { @@ -732,10 +706,10 @@ var dist = point.len(); if (dist > radius) { // No intersection - T_VECTORS.push(circlePos); - T_VECTORS.push(edge); + T_VECTORS.push(circlePos); + T_VECTORS.push(edge); T_VECTORS.push(point); - return false; + return false; } else if (response) { // It intersects, calculate the overlap. response['bInA'] = false; @@ -748,15 +722,15 @@ // Need to check if the circle is intersecting the edge, // Change the edge into its "edge normal". var normal = edge.perp().normalize(); - // Find the perpendicular distance between the center of the + // Find the perpendicular distance between the center of the // circle and the edge. var dist = point.dot(normal); var distAbs = Math.abs(dist); // If the circle is on the outside of the edge, there is no intersection. if (dist > 0 && distAbs > radius) { // No intersection - T_VECTORS.push(circlePos); - T_VECTORS.push(normal); + T_VECTORS.push(circlePos); + T_VECTORS.push(normal); T_VECTORS.push(point); return false; } else if (response) { @@ -770,28 +744,28 @@ } } } - - // If this is the smallest overlap we've seen, keep it. + + // If this is the smallest overlap we've seen, keep it. // (overlapN may be null if the circle was in the wrong Vornoi region). if (overlapN && response && Math.abs(overlap) < Math.abs(response['overlap'])) { response['overlap'] = overlap; response['overlapN'].copy(overlapN); } } - + // Calculate the final overlap vector - based on the smallest overlap. if (response) { response['a'] = polygon; response['b'] = circle; response['overlapV'].copy(response['overlapN']).scale(response['overlap']); } - T_VECTORS.push(circlePos); - T_VECTORS.push(edge); + T_VECTORS.push(circlePos); + T_VECTORS.push(edge); T_VECTORS.push(point); return true; } SAT['testPolygonCircle'] = testPolygonCircle; - + // Check if a circle and a polygon collide. // // **NOTE:** This is slightly less efficient than polygonCircle as it just @@ -820,7 +794,7 @@ return result; } SAT['testCirclePolygon'] = testCirclePolygon; - + // Checks whether polygons collide. /** * @param {Polygon} a The first polygon. @@ -859,4 +833,4 @@ SAT['testPolygonPolygon'] = testPolygonPolygon; return SAT; -})); \ No newline at end of file +})();