Advertisement
Guest User

Untitled

a guest
Oct 25th, 2016
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const rad = deg => deg * Math.PI / 180 + 0.001;
  2. const trunc = a => Math.floor(a);
  3. const normalizeAngle = angle => {
  4.     const alpha = angle % 360;
  5.     return alpha < 0
  6.         ? alpha + 360
  7.         : alpha;
  8. };
  9.  
  10. const horz = (x, y, angle, size) => {
  11.     if (angle === 0 || angle === 180) {
  12.         return null;
  13.     }
  14.  
  15.     const angleUp = angle > 0 && angle < 180;
  16.  
  17.     const y0 = trunc(y / size) * size + (angleUp ? -1 : size);
  18.     const x0 = x + (y - y0) / Math.tan(rad(angle));
  19.  
  20.     const dy = angleUp ? -size : size;
  21.     const dx = -dy / Math.tan(rad(angle));
  22.  
  23.     return { x0, y0, dx, dy };
  24. };
  25.  
  26. const vert = (x, y, angle, size) => {
  27.     if (angle === 90 || angle === 270) {
  28.         return null;
  29.     }
  30.  
  31.     const angleRight = angle < 90 || angle > 270;
  32.  
  33.     const x0 = trunc(x / size) * size + (angleRight ? size : -1);
  34.     const y0 = y + (x - x0) * Math.tan(rad(angle));
  35.  
  36.     const dx = angleRight ? size : -size;
  37.     const dy = -dx * Math.tan(rad(angle));
  38.  
  39.     return { x0, y0, dx, dy };
  40. };
  41.  
  42.  
  43. const calcDistance = (x0, x1, angle) => Math.abs((x0 - x1) / Math.cos(rad(angle)));
  44.  
  45. export function createRaycaster(isHit, width, height) {
  46.  
  47.     const follow = ({ x0, y0, dx, dy, limit = 10 }) => {
  48.         let i = 0;
  49.  
  50.         while (true) {
  51.             const vx = x0 + i * dx;
  52.             const vy = y0 + i * dy;
  53.  
  54.             if (i > limit) {
  55.                 return { x: Number.MAX_VALUE, y: Number.MAX_VALUE };
  56.             }
  57.  
  58.             const gridX = trunc(vx / width);
  59.             const gridY = trunc(vy / height);
  60.  
  61.             if (isHit(gridX, gridY)) {
  62.                 return { x: vx, y: vy };
  63.             }
  64.  
  65.             i++;
  66.         }
  67.     };
  68.  
  69.     // x, y - unit coords
  70.     return function raycast({ x, y, angle }) {
  71.         const normAngle = normalizeAngle(angle);
  72.         const pv = horz(x, y, normAngle, width);
  73.         const ph = vert(x, y, normAngle, height);
  74.  
  75.         const crosspts = [];
  76.  
  77.         if (pv) {
  78.             const hit = follow(pv);
  79.             hit.vertical = true;
  80.             hit.horizontal = false;
  81.             crosspts.push(hit);
  82.         }
  83.  
  84.         if (ph) {
  85.             const hit = follow(ph);
  86.             hit.vertical = false;
  87.             hit.horizontal = true;
  88.             crosspts.push(hit);
  89.         }
  90.  
  91.         return crosspts.reduce((closest, pt) => {
  92.             const distance = calcDistance(x, pt.x, normAngle);
  93.  
  94.             return distance < closest.distance
  95.                 ? Object.assign({}, pt, { distance })
  96.                 : closest;
  97.         }, { x: null, y: null, distance: Number.MAX_VALUE });
  98.     };
  99. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement