Example #1
0
        public static void Calculate(IntVector2 viewerLocation, int visionRange, Grid2D <bool> visibilityMap, IntSize2 mapSize,
                                     Func <IntVector2, bool> blockerDelegate)
        {
            visibilityMap.Clear();

            if (blockerDelegate(viewerLocation) == true)
            {
                return;
            }

            visibilityMap[0, 0] = true;

            SCRData data = new SCRData()
            {
                ViewerLocation     = viewerLocation,
                VisionRange        = visionRange,
                VisionRangeSquared = (visionRange + 1) * (visionRange + 1),                     // +1 to get a bit bigger view area
                VisibilityMap      = visibilityMap,
                MapSize            = mapSize,
                BlockerDelegate    = blockerDelegate,
            };

            for (int octant = 0; octant < 8; ++octant)
            {
                Calculate(ref data, 1, octant, 0.0, 1.0, 1);
            }
        }
Example #2
0
		public static void Calculate(IntVector2 viewerLocation, int visionRange, Grid2D<bool> visibilityMap, IntSize2 mapSize,
			Func<IntVector2, bool> blockerDelegate)
		{
			visibilityMap.Clear();

			if (blockerDelegate(viewerLocation) == true)
				return;

			visibilityMap[0, 0] = true;

			SCRData data = new SCRData()
			{
				ViewerLocation = viewerLocation,
				VisionRange = visionRange,
				VisionRangeSquared = (visionRange + 1) * (visionRange + 1),	// +1 to get a bit bigger view area
				VisibilityMap = visibilityMap,
				MapSize = mapSize,
				BlockerDelegate = blockerDelegate,
			};

			for (int octant = 0; octant < 8; ++octant)
				Calculate(ref data, 1, octant, 0.0, 1.0, 1);
		}
Example #3
0
        static void Calculate(ref SCRData data, int startColumn, int octant, double startSlope, double endSlope, int id)
        {
            //Debug.Print("{4}{0}: Calc, start col {3}, slope {1} -> {2}", id, startSlope, endSlope, startColumn, new string(' ', (id - 1) * 4));

            if (startSlope > endSlope)
            {
                return;
            }

            int maxX;

            switch (octant)
            {
            case 0:
            case 7:
                maxX = Math.Min(data.VisionRange, data.MapSize.Width - data.ViewerLocation.X - 1);
                break;

            case 1:
            case 2:
                maxX = Math.Min(data.VisionRange, data.MapSize.Height - data.ViewerLocation.Y - 1);
                break;

            case 3:
            case 4:
                maxX = Math.Min(data.VisionRange, data.ViewerLocation.X);
                break;

            case 5:
            case 6:
                maxX = Math.Min(data.VisionRange, data.ViewerLocation.Y);
                break;

            default:
                throw new Exception();
            }

            for (int x = startColumn; x <= maxX; ++x)
            {
                bool   currentlyBlocked = false;
                double newStart         = 0;

                int lowY  = MyMath.RoundTowards(startSlope * x);
                int highY = MyMath.RoundAway(endSlope * x);

                switch (octant)
                {
                case 0:
                case 3:
                    highY = Math.Min(highY, data.MapSize.Height - data.ViewerLocation.Y - 1);
                    break;

                case 1:
                case 6:
                    highY = Math.Min(highY, data.MapSize.Width - data.ViewerLocation.X - 1);
                    break;

                case 7:
                case 4:
                    highY = Math.Min(highY, data.ViewerLocation.Y);
                    break;

                case 2:
                case 5:
                    highY = Math.Min(highY, data.ViewerLocation.X);
                    break;

                default:
                    throw new Exception();
                }

                //Debug.Print("{0}{1}: col {2} lowY {3}, highY {4}", new string(' ', (id - 1) * 4), id, x, lowY, highY);

                for (int y = lowY; y <= highY; ++y)
                {
                    IntVector2 translatedLocation = OctantTranslate(new IntVector2(x, y), octant);
                    IntVector2 mapLocation        = translatedLocation.Offset(data.ViewerLocation.X, data.ViewerLocation.Y);

                    Debug.Assert(data.MapSize.Contains(mapLocation));

                    if (x * x + y * y > data.VisionRangeSquared)
                    {
                        data.VisibilityMap[translatedLocation] = false;
                        continue;
                    }

                    double lowerSlope = (y - 0.5) / (x + 0.5);
                    double upperSlope = (y + 0.5) / (x - 0.5);

#if PERMISSIVE
                    if (upperSlope < startSlope || lowerSlope > endSlope)
                    {
                        //Debug.Print("{0}{1}: {2},{3}   center {4:F2} ouside arc", new string(' ', (id - 1) * 4), id, x, y, centerSlope);
                        continue;
                    }

                    bool tileBlocked = data.BlockerDelegate(mapLocation);
#elif MEDIUM_STRICT
                    double centerSlope = (double)y / x;

                    bool tileBlocked = data.BlockerDelegate(mapLocation);

                    if (!tileBlocked && (centerSlope < startSlope || centerSlope > endSlope))
                    {
                        //Debug.Print("{0}{1}: {2},{3}   center {4:F2} ouside arc", new string(' ', (id - 1) * 4), id, x, y, centerSlope);
                        continue;
                    }
#else
#error no mode defined
#endif
                    //Debug.Print("{0}{1}: {2},{3}   center {4:F2} visible", new string(' ', (id - 1) * 4), id, x, y, centerSlope);

                    data.VisibilityMap[translatedLocation] = true;

                    if (currentlyBlocked)
                    {
                        if (tileBlocked)
                        {
                            newStart = upperSlope;
                            continue;
                        }
                        else
                        {
                            currentlyBlocked = false;
                            startSlope       = newStart;
                            //Debug.Print("{0}{1}: {2},{3}  new startSlope {4:F2}", new string(' ', (id - 1) * 4), id, x, y, startSlope);
                        }
                    }
                    else
                    {
                        if (tileBlocked)
                        {
                            currentlyBlocked = true;
                            newStart         = upperSlope;

                            Calculate(ref data, x + 1, octant, startSlope, lowerSlope, id + 1);
                        }
                    }
                }

                if (currentlyBlocked)
                {
                    break;
                }
            }
        }
Example #4
0
		static void Calculate(ref SCRData data, int startColumn, int octant, double startSlope, double endSlope, int id)
		{
			//Debug.Print("{4}{0}: Calc, start col {3}, slope {1} -> {2}", id, startSlope, endSlope, startColumn, new string(' ', (id - 1) * 4));

			if (startSlope > endSlope)
				return;

			int maxX;

			switch (octant)
			{
				case 0:
				case 7:
					maxX = Math.Min(data.VisionRange, data.MapSize.Width - data.ViewerLocation.X - 1);
					break;

				case 1:
				case 2:
					maxX = Math.Min(data.VisionRange, data.MapSize.Height - data.ViewerLocation.Y - 1);
					break;

				case 3:
				case 4:
					maxX = Math.Min(data.VisionRange, data.ViewerLocation.X);
					break;

				case 5:
				case 6:
					maxX = Math.Min(data.VisionRange, data.ViewerLocation.Y);
					break;

				default:
					throw new Exception();
			}

			for (int x = startColumn; x <= maxX; ++x)
			{
				bool currentlyBlocked = false;
				double newStart = 0;

				int lowY = MyMath.RoundTowards(startSlope * x);
				int highY = MyMath.RoundAway(endSlope * x);

				switch (octant)
				{
					case 0:
					case 3:
						highY = Math.Min(highY, data.MapSize.Height - data.ViewerLocation.Y - 1);
						break;

					case 1:
					case 6:
						highY = Math.Min(highY, data.MapSize.Width - data.ViewerLocation.X - 1);
						break;

					case 7:
					case 4:
						highY = Math.Min(highY, data.ViewerLocation.Y);
						break;

					case 2:
					case 5:
						highY = Math.Min(highY, data.ViewerLocation.X);
						break;

					default:
						throw new Exception();
				}

				//Debug.Print("{0}{1}: col {2} lowY {3}, highY {4}", new string(' ', (id - 1) * 4), id, x, lowY, highY);

				for (int y = lowY; y <= highY; ++y)
				{
					IntVector2 translatedLocation = OctantTranslate(new IntVector2(x, y), octant);
					IntVector2 mapLocation = translatedLocation.Offset(data.ViewerLocation.X, data.ViewerLocation.Y);

					Debug.Assert(data.MapSize.Contains(mapLocation));

					if (x * x + y * y > data.VisionRangeSquared)
					{
						data.VisibilityMap[translatedLocation] = false;
						continue;
					}

					double lowerSlope = (y - 0.5) / (x + 0.5);
					double upperSlope = (y + 0.5) / (x - 0.5);

#if PERMISSIVE
					if (upperSlope < startSlope || lowerSlope > endSlope)
					{
						//Debug.Print("{0}{1}: {2},{3}   center {4:F2} ouside arc", new string(' ', (id - 1) * 4), id, x, y, centerSlope);
						continue;
					}

					bool tileBlocked = data.BlockerDelegate(mapLocation);
#elif MEDIUM_STRICT
					double centerSlope = (double)y / x;

					bool tileBlocked = data.BlockerDelegate(mapLocation);

					if (!tileBlocked && (centerSlope < startSlope || centerSlope > endSlope))
					{
						//Debug.Print("{0}{1}: {2},{3}   center {4:F2} ouside arc", new string(' ', (id - 1) * 4), id, x, y, centerSlope);
						continue;
					}
#else
#error no mode defined
#endif
					//Debug.Print("{0}{1}: {2},{3}   center {4:F2} visible", new string(' ', (id - 1) * 4), id, x, y, centerSlope);

					data.VisibilityMap[translatedLocation] = true;

					if (currentlyBlocked)
					{
						if (tileBlocked)
						{
							newStart = upperSlope;
							continue;
						}
						else
						{
							currentlyBlocked = false;
							startSlope = newStart;
							//Debug.Print("{0}{1}: {2},{3}  new startSlope {4:F2}", new string(' ', (id - 1) * 4), id, x, y, startSlope);
						}
					}
					else
					{
						if (tileBlocked)
						{
							currentlyBlocked = true;
							newStart = upperSlope;

							Calculate(ref data, x + 1, octant, startSlope, lowerSlope, id + 1);
						}
					}
				}

				if (currentlyBlocked)
					break;
			}
		}