Created
September 11, 2015 14:53
-
-
Save joar/73e966bae7ae1bd32814 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Collision handler. Use with d3.quadtree.visit | |
| * @param n Node | |
| * @param responseCoefficient How much of the overlap should be eliminated | |
| * each step. Range: 0..1 | |
| * @param state Optional state object to insert debug information into. | |
| * @returns {Function} | |
| */ | |
| export function collide(n, {responseCoefficient=1, debugLines=null}) { | |
| let nx = getExtent(n) // Node extent | |
| return function collide_inner (quad, x1, y1, x2, y2) { | |
| let p = quad.point // Point | |
| debugLines = collide_cleanupDebugLines(debugLines) | |
| // Abort if point is null or point and node are the same | |
| if (!p || p === n) { | |
| return | |
| } | |
| let collision = overlap(n, p) | |
| let averageWidth = (n.width + p.width) / 2, | |
| averageHeight = (n.height + p.height) / 2 | |
| if (collision !== undefined) { | |
| let {tx, ty, th} = getCollisionTriangle(n, p) | |
| let toNode = angle(getCenter(p), getCenter(n)), | |
| toPoint = toNode + Math.PI / 2 | |
| let overlap | |
| if (collision == UP || collision == DOWN) { | |
| overlap = averageHeight - Math.abs(ty) | |
| } else { | |
| overlap = averageWidth - Math.abs(tx) | |
| } | |
| // The distance each object should move away. | |
| let response = overlap / 2 | |
| if (n.fixed || p.fixed) { | |
| response = overlap | |
| } | |
| // Take COLLISION_RESPONSE into account. | |
| response *= responseCoefficient | |
| let nodePos = getPoint( | |
| n, | |
| collision, | |
| response | |
| ) | |
| let pointPos = getPoint( | |
| p, | |
| collision + Math.PI, | |
| response | |
| ) | |
| debugLines = collide_addDebugLine( | |
| debugLines, | |
| n, p, | |
| collision, | |
| response) | |
| if (!n.fixed) { | |
| n.x = nodePos.x | |
| n.y = nodePos.y | |
| } | |
| if (!p.fixed) { | |
| p.x = pointPos.x | |
| p.y = pointPos.y | |
| } | |
| } | |
| return x1 > nx.x2 || x2 < nx.x1 || y1 > nx.y2 || y2 < nx.y1; | |
| } | |
| } | |
| /** | |
| * Check if two rectangles overlap and return the side of the rectangle that | |
| * overlaps. | |
| * @param a | |
| * @param b | |
| * @returns {*} The face of {a} that is hitting {b} in radians. 0 = right | |
| */ | |
| function overlap(a, b) { | |
| let bCenter = getCenter(a), | |
| aCenter = getCenter(b), | |
| averageWidth = (a.width + b.width) / 2, | |
| averageHeight = (a.height + b.height) / 2, | |
| deltaX = bCenter.x - aCenter.x, | |
| deltaY = bCenter.y - aCenter.y | |
| if (Math.abs(deltaX) <= averageWidth && Math.abs(deltaY) <= averageHeight) { | |
| // Collision | |
| let wy = averageWidth * deltaY, | |
| hx = averageHeight * deltaX | |
| if (wy > hx) { | |
| if (wy > -hx) { | |
| return DOWN | |
| } else { | |
| return LEFT | |
| } | |
| } else { | |
| if (wy > -hx) { | |
| return RIGHT | |
| } else { | |
| return UP | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment