Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const rad = deg => deg * Math.PI / 180 + 0.001;
- const trunc = a => Math.floor(a);
- const normalizeAngle = angle => {
- const alpha = angle % 360;
- return alpha < 0
- ? alpha + 360
- : alpha;
- };
- const horz = (x, y, angle, size) => {
- if (angle === 0 || angle === 180) {
- return null;
- }
- const angleUp = angle > 0 && angle < 180;
- const y0 = trunc(y / size) * size + (angleUp ? -1 : size);
- const x0 = x + (y - y0) / Math.tan(rad(angle));
- const dy = angleUp ? -size : size;
- const dx = -dy / Math.tan(rad(angle));
- return { x0, y0, dx, dy };
- };
- const vert = (x, y, angle, size) => {
- if (angle === 90 || angle === 270) {
- return null;
- }
- const angleRight = angle < 90 || angle > 270;
- const x0 = trunc(x / size) * size + (angleRight ? size : -1);
- const y0 = y + (x - x0) * Math.tan(rad(angle));
- const dx = angleRight ? size : -size;
- const dy = -dx * Math.tan(rad(angle));
- return { x0, y0, dx, dy };
- };
- const calcDistance = (x0, x1, angle) => Math.abs((x0 - x1) / Math.cos(rad(angle)));
- export function createRaycaster(isHit, width, height) {
- const follow = ({ x0, y0, dx, dy, limit = 10 }) => {
- let i = 0;
- while (true) {
- const vx = x0 + i * dx;
- const vy = y0 + i * dy;
- if (i > limit) {
- return { x: Number.MAX_VALUE, y: Number.MAX_VALUE };
- }
- const gridX = trunc(vx / width);
- const gridY = trunc(vy / height);
- if (isHit(gridX, gridY)) {
- return { x: vx, y: vy };
- }
- i++;
- }
- };
- // x, y - unit coords
- return function raycast({ x, y, angle }) {
- const normAngle = normalizeAngle(angle);
- const pv = horz(x, y, normAngle, width);
- const ph = vert(x, y, normAngle, height);
- const crosspts = [];
- if (pv) {
- const hit = follow(pv);
- hit.vertical = true;
- hit.horizontal = false;
- crosspts.push(hit);
- }
- if (ph) {
- const hit = follow(ph);
- hit.vertical = false;
- hit.horizontal = true;
- crosspts.push(hit);
- }
- return crosspts.reduce((closest, pt) => {
- const distance = calcDistance(x, pt.x, normAngle);
- return distance < closest.distance
- ? Object.assign({}, pt, { distance })
- : closest;
- }, { x: null, y: null, distance: Number.MAX_VALUE });
- };
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement