コード例 #1
0
        /// <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;
        }