# SAT.js

## About

SAT.js is a simple JavaScript library for performing collision detection (and projection-based collision response) of simple 2D shapes. It uses the Separating Axis Theorem (hence the name)

It supports detecting collisions between:

- Circles (using Voronoi Regions.)
- Convex Polygons (and simple Axis-Aligned Boxes, which are of course, convex polygons.)

It also supports checking whether a point is inside a circle or polygon.

It's released under the MIT license.

Current version: `0.8.0`

.

Nicely compresses with the Google Closure Compiler in **Advanced** mode to about 6KB (2KB gzipped)

To use it in node.js, you can run `npm install sat`

and then use it with `var SAT = require('sat');`

## Classes

SAT.js contains the following JavaScript classes:

### SAT.Vector (aliased as SAT.V)

This is a simple 2D vector/point class. It is created by calling:

`// Create the vector (10,10) - If (x,y) not specified, defaults to (0,0).var v = 10 10`

It has the following properties:

`x`

- The x-coordinate of the Vector.`y`

- The y-coordinate of the Vector.

It contains the following methods:

`copy(other)`

- Copy the value of another Vector to this one.`clone()`

- Return a new vector with the same coordinates as this one.`perp()`

- Change this vector to be perpendicular to what it was before.`rotate(angle)`

- Rotate this vector counter-clockwise by the specified number of radians.`reverse()`

- Reverse this Vector.`normalize()`

- Make the Vector unit-lengthed.`add(other)`

- Add another Vector to this one.`sub(other)`

- Subtract another Vector from this one.`scale(x,y)`

- Scale this Vector in the X and Y directions.`project(other)`

- Project this Vector onto another one.`projectN(other)`

- Project this Vector onto a unit Vector.`reflect(axis)`

- Reflect this Vector on an arbitrary axis Vector.`reflectN(axis)`

- Reflect this Vector on an arbitrary axis unit Vector.`dot(other)`

- Get the dot product of this Vector and another.`len2()`

- Get the length squared of this Vector.`len()`

- Get the length of this Vector

### SAT.Circle

This is a simple circle with a center position and a radius. It is created by calling:

`// Create a circle whose center is (10,10) with radius of 20var c = 1010 20;`

It has the following properties:

`pos`

- A Vector representing the center of the circle.`r`

- The radius of the circle`offset`

- Offset of center of circle from`pos`

.

It has the following methods:

`setOffset(offset)`

- Set the current offset

### SAT.Polygon

This is a **convex** polygon, whose points are specified in a counter-clockwise fashion. It is created by calling:

`// Create a triangle at (0,0)var p = 1000 5075;`

Note: The points are counter-clockwise *with respect to the coordinate system*. If you directly draw the points on a screen that has the origin at the top-left corner it will *appear* visually that the points are being specified clockwise. This is just because of the inversion of the Y-axis when being displayed.

You can create a line segment by creating a `Polygon`

that contains only 2 points.

Any identical consecutive points will be combined. (this can happen if you convert a `Box`

with zero width or height into a `Polygon`

)

It has the following properties:

`pos`

- The position of the polygon (all points are relative to this).`points`

- Array of vectors representing the original points of the polygon.`angle`

- Angle to rotate the polgon (affects`calcPoints`

)`offset`

- Translation to apply to the polygon before the`angle`

rotation (affects`calcPoints`

)`calcPoints`

- (Calculated) The collision polygon - effectively`points`

with`angle`

and`offset`

applied.`edges`

- (Calculated) Array of Vectors representing the edges of the calculated polygon`normals`

- (Calculated) Array of Vectors representing the edge normals of the calculated polygon (perpendiculars)

You should *not* manually change any of the properties except `pos`

- use the `setPoints`

, `setAngle`

, and `setOffset`

methods to ensure that the calculated properties are updated correctly.

It has the following methods:

`setPoints(points)`

- Set the original points`setAngle(angle)`

- Set the current rotation angle (in radians)`setOffset(offset)`

- Set the current offset`rotate(angle)`

- Rotate the original points of this polygon counter-clockwise (around its local coordinate system) by the specified number of radians. The`angle`

rotation will be applied on top of this rotation.`translate(x, y)`

- Translate the original points of this polygon (relative to the local coordinate system) by the specified amounts. The`offset`

translation will be applied on top of this translation.`getAABB()`

- Compute the axis-aligned bounding box. Returns a new Polygon every time it is called. Is performed based on the`calcPoints`

.`getCentroid()`

- Compute the Centroid of the polygon. Is performed based on the`calcPoints`

.

### SAT.Box

This is a simple Box with a position, width, and height. It is created by calling:

`// Create a box at (10,10) with width 20 and height 40.var b = 1010 20 40;`

It has the following properties:

`pos`

- The bottom-left coordinate of the box (i.e the smallest`x`

value and the smallest`y`

value).`w`

- The width of the box.`h`

- The height of the box.

It has the following methods:

`toPolygon()`

- Returns a new Polygon whose edges are the edges of the box.

### SAT.Response

This is the object representing the result of a collision between two objects. It just has a simple `new Response()`

constructor.

It has the following properties:

`a`

- The first object in the collision.`b`

- The second object in the collison.`overlap`

- Magnitude of the overlap on the shortest colliding axis.`overlapN`

- The shortest colliding axis (unit-vector)`overlapV`

- The overlap vector (i.e.`overlapN.scale(overlap, overlap)`

). If this vector is subtracted from the position of`a`

,`a`

and`b`

will no longer be colliding.`aInB`

- Whether the first object is completely inside the second.`bInA`

- Whether the second object is completely inside the first.

It has the following methods:

`clear()`

- Clear the response so that it is ready to be reused for another collision test.

Note: The `clear`

ed value for a `Response`

has what may seem to be strange looking values:

` a: null b: null overlap: 17976931348623157e+308 overlapV: overlapN: aInB: true bInA: true`

These just make calculating the response simpler in the collision tests. If the collision test functions return `false`

the values that are in the response should not be examined, and `clear()`

should be called before using it for another collision test.

## Collision Tests

SAT.js contains the following collision tests:

`SAT.pointInCircle(p, c)`

Checks whether a given point is inside the specified circle.

`SAT.pointInPolygon(p, poly)`

Checks whether a given point is inside a specified convex polygon.

`SAT.testCircleCircle(a, b, response)`

Tests for a collision between two `Circle`

s, `a`

, and `b`

. If a response is to be calculated in the event of collision, pass in a `clear`

ed `Response`

object.

Returns `true`

if the circles collide, `false`

otherwise.

If it returns `false`

you should not use any values that are in the `response`

(if one is passed in)

`SAT.testPolygonCircle(polygon, circle, response)`

Tests for a collision between a `Polygon`

and a `Circle`

. If a response is to be calculated in the event of a collision, pass in a `clear`

ed `Response`

object.

Returns `true`

if there is a collision, `false`

otherwise.

If it returns `false`

you should not use any values that are in the `response`

(if one is passed in)

`SAT.testCirclePolygon(circle, polygon, response)`

The same thing as `SAT.testPolygonCircle`

, but in the other direction.

Returns `true`

if there is a collision, `false`

otherwise.

If it returns `false`

you should not use any values that are in the `response`

(if one is passed in)

*Note: This is slightly slower than SAT.testPolygonCircle as it just calls that and reverses the result*

`SAT.testPolygonPolygon(a, b, response)`

Tests whether two polygons `a`

and `b`

collide. If a response is to be calculated in the event of collision, pass in a `clear`

ed `Response`

object.

Returns `true`

if there is a collision, `false`

otherwise.

If it returns `false`

you should not use any values that are in the `response`

(if one is passed in)

*Note: If you want to detect a collision between Boxes, use the toPolygon() method*

## Examples

Test two circles

`var V = SATVector;var C = SATCircle; var circle1 = 00 20;var circle2 = 300 20;var response = ;var collided = SAT; // collided => true// response.overlap => 10// response.overlapV => (10, 0)`

Test a circle and a polygon

`var V = SATVector;var C = SATCircle;var P = SATPolygon; var circle = 5050 20;// A squarevar polygon = 00 00 400 4040 040;var response = ;var collided = SAT; // collided => true// response.overlap ~> 5.86// response.overlapV ~> (4.14, 4.14) - i.e. on a diagonal`

Test two polygons

`var V = SATVector;var P = SATPolygon; // A squarevar polygon1 = 00 00 400 4040 040;// A trianglevar polygon2 = 300 00 30 0 0 30;var response = ;var collided = SAT; // collided => true// response.overlap => 10// response.overlapV => (10, 0)`

No collision between two Boxes

`var V = SATVector;var B = SATBox; var box1 = 00 20 20;var box2 = 100100 20 20;var collided = SAT; // collided => false`

Hit testing a circle and polygon

`var V = SATVector;var C = SATCircle;var P = SATPolygon; var triangle = 300 00 30 0 0 30;var circle = 100100 20; SAT; // falseSAT; // trueSAT; // falseSAT; // true`

## Tests

To run the tests from your console:

```
npm install
npm run test
```