Last active
August 29, 2015 14:13
-
-
Save Cazra/348653571dffc16e87b9 to your computer and use it in GitHub Desktop.
Roll20 Token Collisions
This file contains 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
/** | |
* A small library for testing collisions between moving tokens in Roll20. | |
* | |
* Requires: | |
* Vector Math https://gist.github.com/Cazra/348653571dffc16e87b9 | |
*/ | |
var TokenCollisions = (function() { | |
/** | |
* Returns the first token, from some list of tokens, that a token has | |
* collided with during its last movement. | |
* @param {Graphic} token The token that moved | |
* @param {Graphic[]} otherTokens The list of tokens we are testing collisions with. | |
* @return {Graphic || false} If the token collided with another token, the first token that | |
* it would collide with during its movement is returned. Otherwise it returns false. | |
*/ | |
var getFirstCollision = function(token, otherTokens) { | |
// Get all the points for the movement. | |
var movePts = _getAllPointsDuringMovement(token); | |
// Check each segment of movement to see if we triggered a trap. | |
for(var i = 0; i < movePts.length-1; i++) { | |
var p1 = movePts[i]; | |
var p2 = movePts[i+1]; | |
// If we encountered a trap, we're done. | |
var collidedToken = _getFirstCollisionInWaypoint(token, otherTokens, p1, p2); | |
if(collidedToken) { | |
return collidedToken; | |
} | |
} | |
return false | |
}; | |
/** | |
* Returns the list of tokens, from some list of tokens, that a token has | |
* collided with during its last movement. | |
* @param {Graphic} token The token that moved | |
* @param {Graphic[]} otherTokens The tokens we're checking collisions with. | |
* @return {Graphic[]} | |
*/ | |
var getCollisions = function(token, otherTokens) { | |
// Get all the points for the movement. | |
var movePts = _getAllPointsDuringMovement(token); | |
var collisions = []; | |
// Check each segment of movement to see if we triggered a trap. | |
for(var i = 0; i < movePts.length-1; i++) { | |
var p1 = movePts[i]; | |
var p2 = movePts[i+1]; | |
// If we encountered a trap, we're done. | |
var newCollisions = _getCollisionsInWaypoint(token, otherTokens, p1, p2); | |
collisions = collisions.concat(newCollisions); | |
} | |
return collisions | |
}; | |
/** | |
* @private | |
* Gets the list of all points traversed during a token's movement, including | |
* its current position at the end of the movement. | |
* @param {Graphic} token | |
* @return {vec2[]} | |
*/ | |
var _getAllPointsDuringMovement = function(token) { | |
var results = []; | |
var moveCoords = token.get("lastmove").split(","); | |
for(var i=0; i < moveCoords.length; i++) { | |
moveCoords[i] = parseInt(moveCoords[i]); | |
} | |
moveCoords.push(parseInt(token.get("left"))); | |
moveCoords.push(parseInt(token.get("top"))); | |
for(var i=0; i <= moveCoords.length - 2; i+=2) { | |
var x = moveCoords[i]; | |
var y = moveCoords[i+1]; | |
results.push([x, y]); | |
} | |
return results; | |
}; | |
/** | |
* @private | |
* Checks if a token collided with another token during its movement between two points. | |
* @param {Graphic} token | |
* @param {vec2} startPt | |
* @param {vec2} endPt | |
* @return {Graphic || false} The first other token that token collided with in its movement. If there was no collision, return false. | |
*/ | |
var _getFirstCollisionInWaypoint = function(token, otherTokens, startPt, endPt) { | |
var collisions = _getCollisionsInWaypoint(token, otherTokens, startPt, endPt); | |
if(collisions.length > 0) { | |
return _getNearestTokenToPoint(startPt, collisions); | |
} | |
else { | |
return false; | |
} | |
}; | |
/** | |
* @private | |
* For some token, this gets the list of tokens it collided with during its | |
* movement between two points, from some list of other tokens. | |
* @param {Graphic} token | |
* @param {Graphic[]} otherTokens | |
* @param {vec2} startPt | |
* @param {vec2} endPt | |
* @return {Graphic[]} | |
*/ | |
var _getCollisionsInWaypoint = function(token, otherTokens, startPt, endPt) { | |
var result = []; | |
for(var i in otherTokens) { | |
var other = otherTokens[i]; | |
if(_checkCollisionInWaypoint(token, other, startPt, endPt)) { | |
result.push(other); | |
} | |
} | |
return result; | |
}; | |
/** | |
* @private | |
* Checks if a token collides with the other token during its movement between | |
* two points. | |
* @param {Graphic} token The moving token | |
* @param {Graphic} other | |
* @param {vec2} startPt | |
* @param {vec2} endPt | |
* @return {Boolean} true iff there was a collision. | |
*/ | |
var _checkCollisionInWaypoint = function(token, other, startPt, endPt) { | |
var otherPt = _getTokenPt(other); | |
// We assume that all tokens are circular, therefore width = diameter. | |
var thresholdDist = (parseInt(other.get("width")) + parseInt(token.get("width")))/2; | |
// Don't count the other token if our movement already started in it. | |
if(Math.round(vecLength(vec(startPt, otherPt))) >= thresholdDist) { | |
// Figure out the closest distance we came to the other token during | |
// the movement. | |
var dist = Math.round(ptSegDist(otherPt, startPt, endPt)); | |
if(dist < thresholdDist) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
/** | |
* @private | |
* Returns the token nearest to the specified point | |
* out of some list of tokens. | |
* @param {vec2} pt | |
* @param {Graphic[]} tokens | |
* @return {Graphic} | |
*/ | |
var _getNearestTokenToPoint = function(pt, tokens) { | |
var result = null; | |
var bestDist = -1; | |
for(var i in tokens) { | |
var token = tokens[i]; | |
var tokenPt = _getTokenPt(token); | |
var dist = vecLength(vec(pt, tokenPt)); | |
if(bestDist === -1 || dist < bestDist) { | |
result = token; | |
bestDist = dist; | |
} | |
} | |
return result; | |
}; | |
/** | |
* @private | |
* Gets the position of a token. | |
* @param {Graphic} token | |
* @return {vec2} | |
*/ | |
var _getTokenPt = function(token) { | |
var x = token.get("left"); | |
var y = token.get("top"); | |
return [x, y]; | |
}; | |
return { | |
getFirstCollision: getFirstCollision, | |
getCollisions: getCollisions | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment