/// <summary> /// Raycasts a given <c>Ray</c> in this maze. /// </summary> /// <param name="ray">The <c>Ray</c> to cast.</param> /// <param name="radius">The radius of the thing casting the ray.</param> public void Raycast(ref Ray ray, double radius) { if (Math.Abs(ray.Magnitude) < Double.Epsilon) { ray.Velocity = 0; return; } var gridCoords = new CoordI(ray.Origin); double len = 0; double ax; double ay; var walled = false; var south = ray.GoingSouth(); var east = ray.GoingEast(); if ((south && !east) || (!south && east)) { ax = 1.0 / Math.Cos(Consts.QuarterTurn - ray.Angle % Consts.QuarterTurn); ay = 1.0 / Math.Cos(ray.Angle % Consts.QuarterTurn); } else { ax = 1.0 / Math.Cos(ray.Angle % Consts.QuarterTurn); ay = 1.0 / Math.Cos(Consts.QuarterTurn - ray.Angle % Consts.QuarterTurn); } var testCoord = ray.Origin - gridCoords; var testSpace = new CoordD(1,1) - testCoord; if (_walls.test_wall(gridCoords, 2) && testSpace.X < radius) ray.Origin.X -= radius - testSpace.X; else if (_walls.test_wall(gridCoords, 3) && testSpace.Y < radius) ray.Origin.Y -= radius - testSpace.Y; else if (_walls.test_wall(gridCoords, 0) && testCoord.X < radius) ray.Origin.X += radius - testCoord.X; else if (_walls.test_wall(gridCoords, 1) && testCoord.Y < radius) ray.Origin.Y += radius - testCoord.Y; while (len < ray.Magnitude && !walled) { var gridSpace = ray.Origin.ByAngle(ray.Angle, len) - gridCoords; var cellSpace = new CoordD(1,1) - gridSpace; gridSpace.Abs(); cellSpace.Abs(); var hx = (east ? cellSpace.X : gridSpace.X) * ax; var hy = (south ? cellSpace.Y : gridSpace.Y) * ay; if (hx < hy) len += (east ? Math.Max(0, cellSpace.X - radius) : Math.Max(0, gridSpace.X - radius)) * ax; else len += (south ? Math.Max(0, cellSpace.Y - radius) : Math.Max(0, gridSpace.Y - radius)) * ay; var dir = hx < hy ? 0 : 1; if ((hx < hy && east) || (hx >= hy && south)) dir += 2; walled = !_walls.InBounds(gridCoords, dir) || _walls.test_wall(gridCoords, dir); if (walled) continue; switch (dir) { case 0: gridCoords.X -= 1; break; case 1: gridCoords.Y -= 1; break; case 2: gridCoords.X += 1; break; case 3: gridCoords.Y += 1; break; } } ray.Velocity = Math.Min(len, ray.Magnitude) / ray.Magnitude; }