Comparing version 0.7.1 to 0.8.0
# Changelog | ||
## 0.8.0 (Sept 7, 2019) | ||
- Combine consecutive duplicate points in polygons to remove zero-length edges. (Fixes #55) | ||
- Add the ability to set an offset for circles - thanks [funnisimo](https://github.com/funnisimo)! | ||
## 0.7.1 (May 23, 2018) | ||
@@ -4,0 +9,0 @@ |
{ | ||
"name": "sat", | ||
"description": "Library for performing 2D collision detection", | ||
"version": "0.7.1", | ||
"version": "0.8.0", | ||
"author": "Jim Riecken <jriecken@gmail.com>", | ||
@@ -11,6 +11,3 @@ "keywords": [ | ||
], | ||
"license": { | ||
"type": "MIT", | ||
"url": "http://github.com/jriecken/sat-js/raw/master/LICENSE" | ||
}, | ||
"license": "MIT", | ||
"repository": { | ||
@@ -17,0 +14,0 @@ "type": "git", |
@@ -19,3 +19,3 @@ # SAT.js | ||
Current version: `0.7.1`. [Annotated source code](http://jriecken.github.io/sat-js/docs/SAT.html) is available. | ||
Current version: `0.8.0`. | ||
@@ -74,3 +74,8 @@ Nicely compresses with the [Google Closure Compiler](https://developers.google.com/closure/compiler/) in **Advanced** mode to about 6KB (2KB gzipped) | ||
- `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 | ||
@@ -90,4 +95,6 @@ | ||
You can create a line segment by creating a `Polygon` that contains only 2 ppoints. | ||
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: | ||
@@ -151,2 +158,18 @@ | ||
Note: The `clear`ed value for a `Response` has what may seem to be strange looking values: | ||
```javascript | ||
{ | ||
a: null, | ||
b: null, | ||
overlap: 1.7976931348623157e+308, | ||
overlapV: Vector(0, 0), | ||
overlapN: Vector(0, 0), | ||
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 | ||
@@ -166,12 +189,16 @@ | ||
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 cleared `Response` object. | ||
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 cleared `Response` object. | ||
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)` | ||
@@ -183,12 +210,16 @@ | ||
*NOTE: This is slightly slower than `SAT.testPolygonCircle` as it just calls that and reverses the result* | ||
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 cleared `Response` object. | ||
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. | ||
*NOTE: If you want to detect a collision between `Box`es, use the `toPolygon()` method* | ||
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 `Box`es, use the `toPolygon()` method* | ||
## Examples | ||
@@ -278,7 +309,5 @@ | ||
SAT.pointInCircle(new V(110,110), circle); // true | ||
``` | ||
Tests | ||
----- | ||
## Tests | ||
@@ -288,5 +317,4 @@ To run the tests from your console: | ||
``` | ||
mocha | ||
npm install | ||
npm run test | ||
``` | ||
To install `mocha` you will need to have run `npm install` after cloning the repo. |
53
SAT.js
@@ -1,2 +0,2 @@ | ||
// Version 0.7.1 - Copyright 2012 - 2018 - Jim Riecken <jimr@jimr.ca> | ||
// Version 0.8.0 - Copyright 2012 - 2018 - Jim Riecken <jimr@jimr.ca> | ||
// | ||
@@ -7,3 +7,3 @@ // Released under the MIT License - https://github.com/jriecken/sat-js | ||
// polygons using the Separating Axis Theorem. | ||
/** @preserve SAT.js - Version 0.7.1 - Copyright 2012 - 2018 - Jim Riecken <jimr@jimr.ca> - released under the MIT License. https://github.com/jriecken/sat-js */ | ||
/** @preserve SAT.js - Version 0.8.0 - Copyright 2012 - 2018 - Jim Riecken <jimr@jimr.ca> - released under the MIT License. https://github.com/jriecken/sat-js */ | ||
@@ -153,3 +153,3 @@ /*global define: false, module: false*/ | ||
// Scale this vector. An independant scaling factor can be provided | ||
// Scale this vector. An independent scaling factor can be provided | ||
// for each axis, or a single scaling factor that will scale both `x` and `y`. | ||
@@ -262,2 +262,3 @@ /** | ||
this['r'] = r || 0; | ||
this['offset'] = new Vector(); | ||
} | ||
@@ -274,6 +275,16 @@ SAT['Circle'] = Circle; | ||
var r = this['r']; | ||
var corner = this["pos"].clone().sub(new Vector(r, r)); | ||
var corner = this['pos'].clone().add(this['offset']).sub(new Vector(r, r)); | ||
return new Box(corner, r*2, r*2).toPolygon(); | ||
}; | ||
// Set the current offset to apply to the radius. | ||
/** | ||
* @param {Vector} offset The new offset vector. | ||
* @return {Circle} This for chaining. | ||
*/ | ||
Circle.prototype['setOffset'] = Circle.prototype.setOffset = function(offset) { | ||
this['offset'] = offset; | ||
return this; | ||
}; | ||
// ## Polygon | ||
@@ -294,3 +305,3 @@ // | ||
* points are relative to this one) | ||
* @param {Array.<Vector>=} points An array of vectors representing the points in the polygon, | ||
* @param {Array<Vector>=} points An array of vectors representing the points in the polygon, | ||
* in counter-clockwise order. | ||
@@ -307,3 +318,3 @@ * @constructor | ||
// Set the points of the polygon. | ||
// Set the points of the polygon. Any consecutive duplicate points will be combined. | ||
// | ||
@@ -315,3 +326,3 @@ // Note: The points are counter-clockwise *with respect to the coordinate system*. | ||
/** | ||
* @param {Array.<Vector>=} points An array of vectors representing the points in the polygon, | ||
* @param {Array<Vector>=} points An array of vectors representing the points in the polygon, | ||
* in counter-clockwise order. | ||
@@ -330,2 +341,10 @@ * @return {Polygon} This for chaining. | ||
for (i = 0; i < points.length; i++) { | ||
// Remove consecutive duplicate points | ||
var p1 = points[i]; | ||
var p2 = i < points.length - 1 ? points[i + 1] : points[0]; | ||
if (p1 !== p2 && p1.x === p2.x && p1.y === p2.y) { | ||
points.splice(i, 1); | ||
i -= 1; | ||
continue; | ||
} | ||
calcPoints.push(new Vector()); | ||
@@ -475,3 +494,3 @@ edges.push(new Vector()); | ||
} | ||
return new Box(this["pos"].clone().add(new Vector(xMin, yMin)), xMax - xMin, yMax - yMin).toPolygon(); | ||
return new Box(this['pos'].clone().add(new Vector(xMin, yMin)), xMax - xMin, yMax - yMin).toPolygon(); | ||
}; | ||
@@ -582,3 +601,3 @@ | ||
/** | ||
* @type {Array.<Vector>} | ||
* @type {Array<Vector>} | ||
*/ | ||
@@ -591,3 +610,3 @@ var T_VECTORS = []; | ||
/** | ||
* @type {Array.<Array.<number>>} | ||
* @type {Array<Array<number>>} | ||
*/ | ||
@@ -615,5 +634,5 @@ var T_ARRAYS = []; | ||
/** | ||
* @param {Array.<Vector>} points The points to flatten. | ||
* @param {Array<Vector>} points The points to flatten. | ||
* @param {Vector} normal The unit vector axis to flatten on. | ||
* @param {Array.<number>} result An array. After calling this function, | ||
* @param {Array<number>} result An array. After calling this function, | ||
* result[0] will be the minimum value, | ||
@@ -640,4 +659,4 @@ * result[1] will be the maximum value. | ||
* @param {Vector} bPos The position of the second polygon. | ||
* @param {Array.<Vector>} aPoints The points in the first polygon. | ||
* @param {Array.<Vector>} bPoints The points in the second polygon. | ||
* @param {Array<Vector>} aPoints The points in the first polygon. | ||
* @param {Array<Vector>} bPoints The points in the second polygon. | ||
* @param {Vector} axis The axis (unit sized) to test against. The points of both polygons | ||
@@ -765,3 +784,3 @@ * will be projected onto this axis. | ||
function pointInCircle(p, c) { | ||
var differenceV = T_VECTORS.pop().copy(p).sub(c['pos']); | ||
var differenceV = T_VECTORS.pop().copy(p).sub(c['pos']).sub(c['offset']); | ||
var radiusSq = c['r'] * c['r']; | ||
@@ -803,3 +822,3 @@ var distanceSq = differenceV.len2(); | ||
// circles is greater than their combined radius. | ||
var differenceV = T_VECTORS.pop().copy(b['pos']).sub(a['pos']); | ||
var differenceV = T_VECTORS.pop().copy(b['pos']).add(b['offset']).sub(a['pos']).sub(a['offset']); | ||
var totalRadius = a['r'] + b['r']; | ||
@@ -839,3 +858,3 @@ var totalRadiusSq = totalRadius * totalRadius; | ||
// Get the position of the circle relative to the polygon. | ||
var circlePos = T_VECTORS.pop().copy(circle['pos']).sub(polygon['pos']); | ||
var circlePos = T_VECTORS.pop().copy(circle['pos']).add(circle['offset']).sub(polygon['pos']); | ||
var radius = circle['r']; | ||
@@ -842,0 +861,0 @@ var radius2 = radius * radius; |
@@ -63,2 +63,6 @@ var SAT = require('..'); | ||
assert( response.overlapV.x == 10 && response.overlapV.y === 0); | ||
circle1.offset = new V(-10, -10); | ||
collided = SAT.testCircleCircle(circle1, circle2, response); | ||
assert( !collided ); | ||
}); | ||
@@ -86,4 +90,34 @@ | ||
); | ||
circle.offset = new V(10, 10); | ||
collided = SAT.testPolygonCircle(polygon, circle, response); | ||
assert(!collided); | ||
}); | ||
it('testPolygonCircle - line - not collide', function () { | ||
var V = SAT.Vector; | ||
var C = SAT.Circle; | ||
var B = SAT.Box; | ||
var circle = new C(new V(50,50), 20); | ||
var polygon = new B(new V(1000,1000), 100, 0).toPolygon(); | ||
var response = new SAT.Response(); | ||
var collided = SAT.testPolygonCircle(polygon, circle, response); | ||
assert(!collided); | ||
}) | ||
it('testPolygonCircle - line - collide', function () { | ||
var V = SAT.Vector; | ||
var C = SAT.Circle; | ||
var B = SAT.Box; | ||
var circle = new C(new V(50,50), 20); | ||
var polygon = new B(new V(50,50), 100, 0).toPolygon(); | ||
var response = new SAT.Response(); | ||
var collided = SAT.testPolygonCircle(polygon, circle, response); | ||
assert(collided); | ||
assert(response.overlap.toFixed(2) == "20.00"); | ||
}) | ||
it("testPolygonPolygon", function() { | ||
@@ -130,2 +164,5 @@ var V = SAT.Vector; | ||
assert(SAT.pointInCircle(new V(110,110), circle)); // true | ||
circle.offset = new V(-10, -10); | ||
assert(!SAT.pointInCircle(new V(110,110), circle)); // false | ||
}); | ||
@@ -132,0 +169,0 @@ |
1293
313
68441
9