Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[Help] Rotate token on move

I was perusing the forums here for something that would allow me to have my players' tokens rotate on move, so their LOS would slowly change based on where they last were located in relation to where they are at present.  Now please note, I am by no means a code junkie - at best I am an apprentice.  I came across this  topic and it seems to be what I would like to have happen, but the code is incomplete.  I haven't the slightest idea how to complete the timing process myself or make the changes suggested in the followups.  My inquiry is, is there anyone that could complete the code so it could be used publicly?  
Did you contact Warlock?
Hey Patrick. I've been working on learning the API so I took a crack at this. My approach is similar to what Warlock was doing but I ended up with a lot more code :) Also I know JavaScript but my math isn't so great. I needed to go and review a bunch of trig and stuff to do this. At this point my solution works but feels a bit convoluted. If anyone has any tips for how I can simplify it I'm all ears! (function() {   // Start Config   var rotateOnMove = {       // The direction tokens face when initially added to map. Options are "up" or "down"       defaultOrientation: 'down',       // The animation frequency in ms. Increasing will make animation slower and may help performance.       animationSpeed: 50,       // The degrees to rotate per animation step. Decreasing will make animation slower and smoother but may hurt performance.       turnRate: 20   }, // End Config   _2PI = 2 * Math.PI;   rotateOnMove._rotatingTokens = [];   on("change:graphic", function(obj, prev) {     var line, oldAngle, newAngle, angleDelta, otherAngleDelta, direction;     // Sanity check inputs     try {       if (!validNumber(obj.get('left')) || !validNumber(obj.get('top')) ||           !validNumber(prev.left) || !validNumber(prev.top) ||           !validNumber(obj.get('rotation'))) {         log('Error: Bad environment state.');         return;       }     } catch(e) {         log('Error: ' + e.message);         return;     }     // Return if token isn't on the objects layer or its already rotating     if (_.contains(rotateOnMove._rotatingTokens, obj.id) ||         (obj.get('layer') !== 'objects')) {       return;     }     // Calculate the starting and ending angles     oldAngle = translateAngle(toRadians(obj.get('rotation')));     line = translateLine([       [ Math.round(prev.left), Math.round(prev.top) ],       [ Math.round(obj.get('left')), Math.round(obj.get('top')) ]     ]);     if (_.isEqual(line[0], line[1])) return; // Points are the same so token didn't move     newAngle = getAngleOfLine(line);     // Calculate the difference of the angles along the closest rotation direction     angleDelta = getAngleDifference(Math.abs(newAngle), Math.abs(oldAngle));     otherAngleDelta = _2PI - angleDelta;     if (angleDelta < otherAngleDelta) {       direction = 1;     } else {       direction = -1;       angleDelta = otherAngleDelta;     }     (function doRotate(current, turnRate, progress) {       var intervalHandle = setInterval(rotate, rotateOnMove.animationSpeed);       function complete() {         clearInterval(intervalHandle);         rotateOnMove._rotatingTokens = _.without(rotateOnMove._rotatingTokens, obj.id);       }       function rotate() {         progress += turnRate;         current += turnRate;         if (Math.abs(progress) < Math.abs(angleDelta)) {           obj.set('rotation', toDegrees(translateAngle(current)));         } else {           obj.set('rotation', toDegrees(translateAngle(newAngle)));           complete();         }       }     })(oldAngle, toRadians(rotateOnMove.turnRate) * direction, 0);     // Track that this token's rotation is in progress     rotateOnMove._rotatingTokens.push(obj.id);   });   // Convert to trig quad space by flipping coords and reversing original Y   // to account for 0,0 being top left   function translateLine(line) {     return [       translatePoint(line[0]),       translatePoint(line[1])     ];   }   // Note: Flip values to account for translation to trig quad.   // Reverse original Y to account for top left as 0, 0   function translatePoint(point) {     return [point[1] * - 1, point[0]];   }   function getAngleOfLine(line) {     var deltaX = line[1][0] - line[0][0],         deltaY = line[1][1] - line[0][1];     // Points are the same     if (deltaX === 0 && deltaY === 0) {       return null;     }     return (Math.atan2(deltaY, deltaX) + _2PI) % _2PI;   }   function getAngleDifference(angle1, angle2) {     var diff = angle1 - angle2;     return diff > 0 && diff < 2 * Math.PI ?         diff : (_2PI + diff) % _2PI; // Handle rollover   }   function validNumber(num) {     return _.isNumber(num) && !_.isNaN(num);   }   function toDegrees(angle) {     return Math.round(angle * (180 / Math.PI));   }   function toRadians(angle) {     return angle * (Math.PI / 180);   }   // Accomodate different default token orientations   function translateAngle(angle) {     return rotateOnMove.defaultOrientation === 'up' ?         angle : (angle + Math.PI) % _2PI;   } })();
Hey, yeah I had contacted Warlock, and hadn't heard anything back.   Matt, nice code.  I appreciate it bud!