コード例 #1
0
        public void FOVTest()
        {
            var testMap = new ArrayMap <bool>(5, 5);

            foreach (Coord coord in testMap.Positions())
            {
                testMap[coord] = true;
            }

            var centre = new Coord(2, 2);

            foreach (Coord coord in new RadiusAreaProvider(centre, 2, Radius.CIRCLE).CalculatePositions())
            {
                testMap[coord] = false;
            }
            foreach (Coord coord in new RadiusAreaProvider(centre, 1, Distance.EUCLIDEAN).CalculatePositions())
            {
                testMap[coord] = true;
            }

            var resMap = new ArrayMap <bool>(5, 5);

            foreach (Coord coord in testMap.Positions())
            {
                resMap[coord] = testMap[coord];
            }

            var FOV = new FOV(resMap);

            FOV.Calculate(centre, 1, Distance.EUCLIDEAN);

            Coord[] calculated = FOV.CurrentFOV.OrderBy(p => p.X).ThenBy(p => p.Y).ToArray();
            Assert.True(calculated.SequenceEqual(new[]
                                                 { new Coord(1, 2), new Coord(2, 1), new Coord(2, 2), new Coord(2, 3), new Coord(3, 2) }));
        }
コード例 #2
0
        public static ArrayMap <T> RotateArrayMap <T>(ArrayMap <T> arrayMap, RotateType rotateType)
        {
            ArrayMap <T> newPattern = null;

            switch (rotateType)
            {
            case RotateType.DEG90:
                newPattern = new ArrayMap <T>(arrayMap.Height, arrayMap.Width);
                foreach (var pos in arrayMap.Positions())
                {
                    newPattern[pos.Y, arrayMap.Width - 1 - pos.X] = arrayMap[pos.X, pos.Y];
                }
                return(newPattern);

            case RotateType.DEG180:
                newPattern = new ArrayMap <T>(arrayMap.Width, arrayMap.Height);
                foreach (var pos in arrayMap.Positions())
                {
                    newPattern[arrayMap.Width - 1 - pos.Y, arrayMap.Height - 1 - pos.X] = arrayMap[pos.X, pos.Y];
                }
                return(newPattern);

            case RotateType.DEG270:
                newPattern = new ArrayMap <T>(arrayMap.Height, arrayMap.Width);
                foreach (var pos in arrayMap.Positions())
                {
                    newPattern[arrayMap.Height - 1 - pos.Y, pos.X] = arrayMap[pos.X, pos.Y];
                }
                return(newPattern);

            default:
                return(newPattern);
            }
        }
コード例 #3
0
        public static int[] GetStats(int height, int width, int tries, ArrayMap <bool> pattern)
        {
            StandardGenerator random = new StandardGenerator();

            var wMap = new ArrayMap <bool>(height, width);

            int[] hits = new int[tries];

            for (int i = 0; i < tries; i++)
            {
                QuickGenerators.GenerateCellularAutomataMap(wMap, random);

                var pMap = new ArrayMap <bool>(height, width);

                while (TryGetFirstPatternMatch(wMap, pMap, pattern, out Coord coord))
                {
                    foreach (var pos in pattern.Positions())
                    {
                        pMap[pos.X + coord.X, pos.Y + coord.Y] = true;
                    }

                    hits[i] += 1;
                }
            }

            return(hits);
        }
コード例 #4
0
        public static bool TryGetFirstPatternMatch(ArrayMap <bool> map, ArrayMap <bool> pMap, ArrayMap <bool> pattern, out Coord startCoord)
        {
            startCoord = new Coord();
            foreach (var pos in map.Positions())
            {
                startCoord = pos;

                var match = true;
                foreach (var patPos in pattern.Positions())
                {
                    var xShift = pos.X + patPos.X;
                    var yShift = pos.Y + patPos.Y;
                    if (map.Width <= xShift || // check map width limits
                        map.Height <= yShift || // check map height limits
                        map[xShift, yShift] != pattern[patPos.X, patPos.Y] || // check if the pattern matches here with the walk map
                        pMap[xShift, yShift] // check if the pattern map already has a pattern at this point
                        )
                    {
                        match = false;
                        break;
                    }
                }

                if (match)
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #5
0
        public static ArrayMap <bool> DecodeBase64(string name)
        {
            string[] nameArray        = name.Split('-');
            string[] patternTypeArray = nameArray[0]
                                        .Split('N')[0]
                                        .Replace("X", "")
                                        .Split('Y');
            var width  = int.Parse(patternTypeArray[0]);
            var height = int.Parse(patternTypeArray[1]);

            //Debug.Log($"{name} X:{width} Y:{height}");

            byte[] array = Convert.FromBase64String(nameArray[1]);

            BitArray bitArray = new BitArray(Convert.FromBase64String(nameArray[1]));

            ArrayMap <bool> tMap = new ArrayMap <bool>(width, height);

            foreach (var pos in tMap.Positions())
            {
                //Debug.Log($"{(pos.Y * tMap.Width) + pos.X}");

                tMap[pos.X, pos.Y] = bitArray[(pos.Y * tMap.Width) + pos.X];
            }

            return(tMap);
        }
コード例 #6
0
ファイル: MapViewTests.cs プロジェクト: rwindegger/GoRogue
        public static TimeSpan TimeForLambdaTranslationMap1ParamAccess(int mapWidth, int mapHeight, int iterations)
        {
            var s = new Stopwatch();

            var map = new ArrayMap <int>(mapWidth, mapHeight);

            foreach (var pos in map.Positions())
            {
                map[pos] = pos.ToIndex(mapWidth);
            }

            var lambdaTranslationMap = new LambdaTranslationMap <int, double>(map, i => i / 100.0);

            // For caching
            double val;

            foreach (var pos in lambdaTranslationMap.Positions())
            {
                val = lambdaTranslationMap[pos];
            }

            s.Start();
            for (int i = 0; i < iterations; i++)
            {
                foreach (var pos in lambdaTranslationMap.Positions())
                {
                    val = lambdaTranslationMap[pos];
                }
            }
            s.Stop();

            return(s.Elapsed);
        }
コード例 #7
0
        static ArrayMap <bool> RandomArray(int seed, int width, int height)
        {
            random.Seed = (uint)seed;
            var result = new ArrayMap <bool>(width, height);

            foreach (var pos in result.Positions())
            {
                result[pos] = random.NextBoolean();
            }
            return(result);
        }
コード例 #8
0
        private static ISettableMapView <double> TestResMap(int width, int height)
        {
            var map = new ArrayMap <double>(width, height);

            foreach (var pos in map.Positions())
            {
                map[pos] = SingletonRandom.DefaultRNG.NextDouble();
            }

            return(map);
        }
コード例 #9
0
        public void DecodeBase64Test()
        {
            ArrayMap <bool> arrayMap1 = ArrayMapHelper.DecodeBase64("X4Y4N000-AAA=");

            Assert.Equal(4, arrayMap1.Width);
            Assert.Equal(4, arrayMap1.Height);
            foreach (var pos in arrayMap1.Positions())
            {
                Assert.False(arrayMap1[pos]);
            }
        }
コード例 #10
0
        //todo temp for prototype
        private CombatMap GenerateTerrain()
        {
            var terrainMap = new ArrayMap <bool>(MapWidth, MapHeight);

            QuickGenerators.GenerateRectangleMap(terrainMap);

            var map = new CombatMap(terrainMap.Width, terrainMap.Height);

            var biome = FindObjectOfType <TravelManager>().CurrentBiome;

            var tStore = FindObjectOfType <TerrainStore>();

            var tileWeights = tStore.GetTileTypeWeights(biome);

            foreach (var position in terrainMap.Positions())
            {
                var selection = tileWeights.First().Key;

                var totalWeight = tileWeights.Values.Sum();

                var roll = Random.Range(0, totalWeight);

                foreach (var tType in tileWeights.OrderByDescending(t => t.Value))
                {
                    var weightedValue = tType.Value;

                    if (roll >= weightedValue)
                    {
                        roll -= weightedValue;
                    }
                    else
                    {
                        selection = tType.Key;
                        break;
                    }
                }

                Tile tile;
                if (IsWallTile(selection))
                {
                    tile = tStore.GetWallTile(biome, selection, position, MapWidth, MapHeight);
                }
                else
                {
                    tile = TerrainStore.GetFloorTile(biome, selection, position, MapWidth, MapHeight);
                }

                map.SetTerrain(tile);
            }

            return(map);
        }
コード例 #11
0
        public Map(IGenerator dungeonRandom, int width, int height, Adventure adventure, bool useTestMap = false)
        {
            Width     = width;
            Height    = height;
            Adventure = adventure;

            var wMap = new ArrayMap <bool>(width, height);

            // creating map here
            if (useTestMap)
            {
                TestMap(wMap);
            }
            else
            {
                //QuickGenerators.GenerateRandomRoomsMap(wMap, dungeonRandom, 15, 5, 15, 50);
                QuickGenerators.GenerateCellularAutomataMap(wMap, dungeonRandom);
            }

            WalkabilityMap = wMap;
            ExplorationMap = new ArrayMap <int>(width, height);
            EntityMap      = new ArrayMap <AdventureEntityContainer>(width, height);
            TileMap        = new ArrayMap <Tile>(width, height);
            Entities       = new List <AdventureEntity>();
            var resMap = new ArrayMap <bool>(width, height);

            foreach (var pos in wMap.Positions())
            {
                // build up Entity Map, not necessary and really slow on big maps
                //EntityMap[i,j] = new AdventureEntityContainer();

                if (wMap[pos.X, pos.Y])
                {
                    //ExplorationMap[i, j] = 1;
                    _walkableTiles++;
                    resMap[pos.X, pos.Y]  = true;
                    TileMap[pos.X, pos.Y] = new StoneTile(this, new Coord(pos.X, pos.Y));
                }
                else
                {
                    //ExplorationMap[i, j] = -9;
                    resMap[pos.X, pos.Y]  = false;
                    TileMap[pos.X, pos.Y] = new StoneWall(this, new Coord(pos.X, pos.Y));
                }
            }

            FovMap = new FOV(resMap);

            Locations = CreateMapLocations(wMap, 9);

            ExpectedFovNum = new int[width, height];
        }
コード例 #12
0
        public override void _Ready()
        {
            var terrain = new ArrayMap <bool>(40, 40);

            MapHelper.TileMap = this;
            MapHelper.FogMap  = GetParent().GetNode <TileMap>("FogMap");

            QuickGenerators.GenerateCellularAutomataMap(terrain);

            var map = new GoRogue.GameFramework.Map(
                width: terrain.Width,
                height: terrain.Height,
                numberOfEntityLayers: 1,
                distanceMeasurement: Distance.CHEBYSHEV
                );

            foreach (var pos in terrain.Positions())
            {
                MapHelper.FogMap.SetCell(pos.X, pos.Y, 0);
                if (terrain[pos])
                {
                    SetCell(pos.X, pos.Y, 0);
                    map.SetTerrain(TerrainFactory.Floor(pos));
                    MapHelper.EmptyTiles.Add(new Vector2(pos.X, pos.Y));
                }
                else // Wall
                {
                    map.SetTerrain(TerrainFactory.Wall(pos));
                    SetCell(pos.X, pos.Y, 1);
                }
            }

            var playerScene = GD.Load <PackedScene>("res://entities/Player.tscn");
            var player      = playerScene.Instance() as Player;

            map.AddEntity(player);
            MapHelper.TileMap.AddChild(player);

            var enemyScene = GD.Load <PackedScene>("res://entities/Enemy.tscn");

            foreach (var e in Enumerable.Range(0, 10))
            {
                var enemy = enemyScene.Instance() as Enemy;
                map.AddEntity(enemy);
                MapHelper.TileMap.AddChild(enemy);
            }

            MapHelper.CurrentMap = map;

            GD.Print("Number of entities: " + MapHelper.CurrentMap.Entities.Count);
            GD.Print("Number of children: " + GetChildCount());
        }
コード例 #13
0
ファイル: FleeMap.cs プロジェクト: HorriganFrank/GoRogue
        /// <summary>
        /// Constructor. Takes a goal map where in all goals are treated as threats to be avoided,
        /// and a magnitude to use (defaulting to 1.2).
        /// </summary>
        /// <param name="baseMap">The underlying goal map to use.</param>
        /// <param name="magnitude">Magnitude to multiply by during calculation.</param>
        public FleeMap(GoalMap baseMap, double magnitude = 1.2)
        {
            _baseMap  = baseMap ?? throw new ArgumentNullException(nameof(baseMap));
            Magnitude = magnitude;
            _goalMap  = new ArrayMap <double?>(baseMap.Width, baseMap.Height);
            _nodes    = new ArrayMap <PositionNode>(baseMap.Width, baseMap.Height);
            foreach (var pos in _nodes.Positions())
            {
                _nodes[pos] = new PositionNode(pos);
            }

            _baseMap.Updated += Update;
        }
コード例 #14
0
        public static string EncodeBase64(ArrayMap <bool> tMap, int i = 0)
        {
            bool[] boolArray = new bool[tMap.Width * tMap.Height];
            foreach (var pos in tMap.Positions())
            {
                boolArray[(pos.Y * tMap.Width) + pos.X] = tMap[pos.X, pos.Y];
            }
            BitArray bitArray = new BitArray(boolArray);

            var bits = BitArrayToByteArray(bitArray);

            return($"X{tMap.Width}Y{tMap.Height}N{i.ToString("000")}-{Convert.ToBase64String(bits)}");
        }
コード例 #15
0
        public List <Coord> GetCoords <T>(ArrayMap <T> map, Coord coord, Func <T, bool> validate)
        {
            var coords = new List <Coord>();

            foreach (var position in map.Positions())
            {
                if (validate(map[position.X, position.Y]) && (coord.X != position.X || coord.Y != position.Y))
                {
                    coords.Add(new Coord(position.X, position.Y));
                }
            }

            return(coords);
        }
コード例 #16
0
ファイル: MapViewTests.cs プロジェクト: rwindegger/GoRogue
        public void ApplyOverlayTest()
        {
            var map = new ArrayMap <bool>(100, 100);

            QuickGenerators.GenerateCellularAutomataMap(map);

            var duplicateMap = new ArrayMap <bool>(map.Width, map.Height);

            duplicateMap.ApplyOverlay(map);

            foreach (var pos in map.Positions())
            {
                Assert.AreEqual(map[pos], duplicateMap[pos]);
            }
        }
コード例 #17
0
ファイル: MapViewTests.cs プロジェクト: rwindegger/GoRogue
        public void UnboundedViewportTest()
        {
            const int MAP_WIDTH         = 100;
            const int MAP_HEIGHT        = 100;
            var       map               = new ArrayMap <int>(MAP_WIDTH, MAP_HEIGHT);
            var       unboundedViewport = new UnboundedViewport <int>(map, 1);

            foreach (var pos in map.Positions())
            {
                Assert.AreEqual(0, unboundedViewport[pos]);
            }

            unboundedViewport.ViewArea = unboundedViewport.ViewArea.Translate(5, 5);

            foreach (var pos in unboundedViewport.Positions())
            {
                if (pos.X < MAP_WIDTH - 5 && pos.Y < MAP_HEIGHT - 5)
                {
                    Assert.AreEqual(0, unboundedViewport[pos]);
                }
                else
                {
                    Assert.AreEqual(1, unboundedViewport[pos]);
                }
            }

            unboundedViewport.ViewArea = unboundedViewport.ViewArea.WithSize(5, 5);

            foreach (var pos in unboundedViewport.Positions())
            {
                Assert.AreEqual(0, unboundedViewport[pos]);
            }

            unboundedViewport.ViewArea = unboundedViewport.ViewArea.WithPosition(MAP_WIDTH - 1, MAP_HEIGHT - 1);

            foreach (var pos in unboundedViewport.Positions())
            {
                if (pos.X == 0 && pos.Y == 0)
                {
                    Assert.AreEqual(0, unboundedViewport[pos]);
                }
                else
                {
                    Assert.AreEqual(1, unboundedViewport[pos]);
                }
            }
        }
コード例 #18
0
        private void RemoveLandmassByVoronoiNoise(ArrayMap <bool> rawOverworldMap)
        {
            bool  remove  = false;
            float remover = 0.0f;

            foreach (var p in rawOverworldMap.Positions())
            {
                if (rawOverworldMap[p] == false)
                {
                    remover = voronoiNoiseMap[p.X, p.Y];
                    remove  = true;
                }
                if ((remove == true) && (voronoiNoiseMap[p.X, p.Y] == remover) && (rawOverworldMap[p] == true))
                {
                    rawOverworldMap[p] = false;
                }
            }
        }
コード例 #19
0
    public void GenerateMap()
    {
        var tempMap = new ArrayMap <bool>(50, 50);

        //QuickGenerators.GenerateRectangleMap(tempMap);
        QuickGenerators.GenerateRandomRoomsMap(tempMap, 20, 5, 12);
        Map = new Map(50, 50, 1, Distance.CHEBYSHEV);

        Map.ObjectMoved += OnObjectMoved;

        foreach (var position in tempMap.Positions())
        {
            if (tempMap[position])
            {
                Map.SetTerrain(new FloorTerrain(position));
            }
            else
            {
                Map.SetTerrain(new WallTerrain(position));
            }
        }

        // instance a player
        var playerInstance = GD.Load <PackedScene>("res://Characters/Player/Player.tscn").Instance() as Player;

        GetTree().Root.GetNode("Game").AddChild(playerInstance);
        playerInstance.Position        = Map.WalkabilityView.RandomPosition(true);
        playerInstance.Moved          += OnPlayerMoved;
        GameController.Instance.Player = playerInstance;
        AddCharacter(playerInstance);

        // generate monsters
        for (var i = 0; i < _numMonsters; ++i)
        {
            var skeleman = GD.Load <PackedScene>("res://Characters/Monsters/Skeleman.tscn").Instance() as Monster;
            GetTree().Root.GetNode("Game").AddChild(skeleman);
            skeleman.Position = Map.WalkabilityView.RandomPosition(true);
            AddCharacter(skeleman);
            Monsters.Add(skeleman);
        }

        Map.CalculateFOV(playerInstance.Position, playerInstance.FOVRadius, Radius.DIAMOND);
        Draw();
    }
コード例 #20
0
        /// <summary>
        /// Generates the areas. Floor tiles will be set to true in the provided map, and wall tiles
        /// will be set to false.
        /// </summary>
        /// <param name="map">The map to fill with values when generate is called.</param>
        /// <param name="rng">
        /// The RNG to use to initially fill the map. If null is specified, the default RNG is used.
        /// </param>
        /// <param name="fillProbability">
        /// Represents the percent chance that a given cell will be a floor cell when the map is
        /// initially randomly filled. Recommended to be in range [40, 60] (40 is used in the
        /// roguebasin article).
        /// </param>
        /// <param name="totalIterations">
        /// Total number of times the cellular automata-based smoothing algorithm is executed.
        /// Recommended to be in range [2, 10] (7 is used on roguebasin article).
        /// </param>
        /// <param name="cutoffBigAreaFill">
        /// Total number of times the cellular automata smoothing variation that is more likely to
        /// result in "breaking up" large areas will be run before switching to the more standard
        /// nearest neighbors version. Recommended to be in range [2, 7] (4 is used in roguebasin article).
        /// </param>
        static public void Generate(ISettableMapView <bool> map, IGenerator rng = null, int fillProbability = 40, int totalIterations = 7, int cutoffBigAreaFill = 4)
        {
            if (rng == null)
            {
                rng = SingletonRandom.DefaultRNG;
            }

            // We must allocate a new one to avoid messing up other map gen features that happened on
            // the original
            var tempMap = new ArrayMap <bool>(map.Width, map.Height);

            tempMap.ApplyOverlay(map);

            // Sets each cell so as of this point, tempMap is in a clean state
            randomlyFillCells(tempMap, rng, fillProbability);

            for (int i = 0; i < totalIterations; i++)
            {
                if (i < cutoffBigAreaFill)
                {
                    cellAutoBigAreaAlgo(tempMap);
                }
                else
                {
                    cellAutoNearestNeighborsAlgo(tempMap);
                }
            }

            // Ensure it's enclosed before we try to connect, so we can't possibly connect a path
            // that ruins the enclosure. Doing this before connection ensures that filling it can't
            // kill the path to an area.
            fillToRectangle(tempMap);

            // Set rooms to true, but do NOT enforce where walls (false values) are -- this is done
            // by making sure the blank slate passed in is all false.
            foreach (var pos in tempMap.Positions())
            {
                if (tempMap[pos])
                {
                    map[pos] = true;
                }
            }
        }
コード例 #21
0
        public static TestGameMap CreateDungeonMap(int width, int height)
        {
            var map     = new TestGameMap(width, height);
            var terrain = new ArrayMap <bool>(width, height);

            QuickGenerators.GenerateRectangleMap(terrain);

            foreach (var pos in terrain.Positions())
            {
                if (terrain[pos])
                {
                    map.SetTerrain(TerrainFactory.Floor(pos));
                }
                else
                {
                    map.SetTerrain(TerrainFactory.Wall(pos));
                }
            }

            return(map);
        }
コード例 #22
0
        public void ApplyTerrainOverlayTranslation()
        {
            var grMap = new ArrayMap <bool>(10, 10);

            QuickGenerators.GenerateRectangleMap(grMap);

            var map = new Map(grMap.Width, grMap.Height, 1, Distance.CHEBYSHEV);

            map.ApplyTerrainOverlay(grMap, (pos, b) => b ? new GameObject(pos, 0, null, true, true, true) : new GameObject(pos, 0, null, true, false, false));

            // If any value is null this fails due to NullReferenceException: otherwise, we assert the right value got set
            foreach (var pos in grMap.Positions())
            {
                if (grMap[pos])
                {
                    Assert.IsTrue(map.GetTerrain(pos).IsWalkable == true);
                }
                else
                {
                    Assert.IsTrue(map.GetTerrain(pos).IsWalkable == false);
                }
            }
        }
コード例 #23
0
ファイル: PathingTests.cs プロジェクト: HorriganFrank/GoRogue
        public void ManualGoalMapTest()
        {
            var map = new ArrayMap <bool>(MAP_WIDTH, MAP_HEIGHT);

            RectangleMapGenerator.Generate(map);

            var stateMap = new ArrayMap <GoalState>(map.Width, map.Height);

            foreach (var pos in stateMap.Positions())
            {
                stateMap[pos] = map[pos] ? GoalState.Clear : GoalState.Obstacle;
            }

            stateMap[MAP_WIDTH / 2, MAP_WIDTH / 2]          = GoalState.Goal;
            stateMap[MAP_WIDTH / 2 + 5, MAP_HEIGHT / 2 + 5] = GoalState.Goal;

            var goalMap = new GoalMap(stateMap, Distance.EUCLIDEAN);

            goalMap.Update();

            Assert.AreEqual(null, goalMap[0, 0]);

            Console.Write(goalMap.ToString(5, "0.00"));
        }
コード例 #24
0
        private List <Rectangle> CreateMapLocations(ArrayMap <bool> wMap, int minLocationSize)
        {
            var rectangles = new List <Rectangle>();

            foreach (var pos in wMap.Positions())
            {
                if (!wMap[pos.X, pos.Y])
                {
                    continue;
                }

                var       width          = 2;
                var       height         = 2;
                var       rectangle      = new Rectangle(pos.X, pos.Y, width, height);
                Rectangle legitRectangle = rectangle;
                while (rectangle.Positions().All(p => wMap[p.X, p.Y]))
                {
                    legitRectangle = rectangle;
                    rectangle      = rectangle.ChangeSize(++width, ++height);
                }

                if (legitRectangle.Positions().All(p => wMap[p.X, p.Y]))
                {
                    rectangles.Add(legitRectangle);
                }
            }

            //for (var i = 0; i < wMap.Width; i++)
            //{
            //    for (var j = 0; j < wMap.Height; j++)
            //    {
            //        if (!wMap[i, j]) continue;

            //        var width = 2;
            //        var height = 2;
            //        var rectangle = new Rectangle(i, j, width, height);
            //        Rectangle legitRectangle = rectangle;
            //        while (rectangle.Positions().All(p => wMap[p.X, p.Y]))
            //        {
            //            legitRectangle = rectangle;
            //            rectangle = rectangle.ChangeSize(++width, ++height);
            //        }

            //        if (legitRectangle.Positions().All(p => wMap[p.X, p.Y]))
            //        {
            //            rectangles.Add(legitRectangle);
            //        }
            //    }
            //}

            var orderedRectangles = rectangles.Where(p => p.Positions().Count() >= minLocationSize).OrderByDescending(p => p.Positions().Count()).ToList();

            for (var i = 0; i < orderedRectangles.Count - 1; i++)
            {
                for (var j = i + 1; j < orderedRectangles.Count; j++)
                {
                    if (Rectangle.GetUnion(orderedRectangles[i], orderedRectangles[j]) == orderedRectangles[i] || !Rectangle.GetIntersection(orderedRectangles[i], orderedRectangles[j]).IsEmpty)
                    {
                        orderedRectangles[j] = Rectangle.EMPTY;
                    }
                }
            }

            return(orderedRectangles.Where(p => !p.IsEmpty).Take(20).ToList());
        }
コード例 #25
0
        private void AssignBiomes(ArrayMap <bool> rawOverworldMap, OverworldTile[] OverWorld)
        {
            foreach (var pos in rawOverworldMap.Positions())
            {
                OverworldTile tile = null;
                int           glyph;
                calculatedBiome = DefineBiomeAt(pos);
                if (rawOverworldMap[pos]) // land tiles
                {
                    Color fgd          = Color.White;
                    Color bgd          = Color.DarkGray;
                    var   fgdColdBiome = new Color(53, 79, 0);
                    var   bkgColdBiome = new Color(141, 182, 0);
                    var   bkgTempBiome = new Color(46, 110, 18);
                    var   fgdTempBiome = new Color(00, 68, 00);
                    var   bkgWarmBiome = new Color(45, 136, 45);
                    var   fgdWarmBiome = new Color(0, 68, 0);
                    switch (calculatedBiome)
                    {
                    case Biome.Cold | Biome.Arid:
                        fgd   = fgdColdBiome; //AzureMist
                        bgd   = bkgColdBiome; // Apple Green
                        glyph = 44;           // ','
                        break;

                    case Biome.Cold | Biome.SemiArid:
                        fgd   = fgdColdBiome;
                        bgd   = bkgColdBiome; // Apple Green
                        glyph = 46;           // '.'
                        break;

                    case Biome.Cold | Biome.SemiHumid:
                        fgd   = fgdColdBiome;
                        bgd   = bkgColdBiome;
                        glyph = 15;     // '☼'
                        break;

                    case Biome.Cold | Biome.Humid:
                        fgd   = fgdColdBiome;
                        bgd   = bkgColdBiome;
                        glyph = 42;     // '*'
                        break;

                    case Biome.Temperate | Biome.Arid:
                        fgd   = new Color(121, 182, 0);
                        bgd   = bkgTempBiome;
                        glyph = 15;     // '☼'
                        break;

                    case Biome.Temperate | Biome.SemiArid:
                        fgd   = fgdTempBiome;
                        bgd   = bkgTempBiome;
                        glyph = 6;     // '♠'
                        break;

                    case Biome.Temperate | Biome.SemiHumid:
                        fgd   = fgdTempBiome;
                        bgd   = bkgTempBiome;
                        glyph = 6;     // '♠'
                        break;

                    case Biome.Temperate | Biome.Humid:
                        fgd   = fgdTempBiome;
                        bgd   = bkgTempBiome;
                        glyph = 5;     // '♣'
                        break;

                    case Biome.Warm | Biome.Arid:
                        fgd   = fgdWarmBiome;
                        bgd   = bkgWarmBiome;
                        glyph = 44;     // ','
                        break;

                    case Biome.Warm | Biome.SemiArid:
                        fgd   = fgdWarmBiome;
                        bgd   = bkgWarmBiome;
                        glyph = 46;     // '.'
                        break;

                    case Biome.Warm | Biome.SemiHumid:
                        fgd   = fgdWarmBiome;
                        bgd   = bkgWarmBiome;
                        glyph = 6;     // '♠'
                        break;

                    case Biome.Warm | Biome.Humid:
                        fgd   = fgdWarmBiome;
                        bgd   = bkgWarmBiome;
                        glyph = 5;     // '♣'
                        break;

                    default:
                        glyph = 63;     // '?'
                        break;
                    }
                    tile = new OverworldTile($"Land - {glyph}", pos, glyph)
                    {
                        ZoneNoise     = voronoiNoiseMap[pos.X, pos.Y],
                        RainNoise     = rainNoise[pos.X, pos.Y],
                        Biome         = calculatedBiome,
                        Foreground    = fgd,
                        Background    = bgd,
                        IsWalkable    = true,
                        IsTransparent = true
                    };
                }
                else if (rawOverworldMap[pos] == false) // air tiles
                {
                    glyph = 126;                        // '~'
                    var bkg = new Color(93, 138, 168);
                    var fgd = Color.Aquamarine;
                    tile = new OverworldTile($"Air - {glyph}", pos, glyph)
                    {
                        ZoneNoise     = voronoiNoiseMap[pos.X, pos.Y],
                        RainNoise     = rainNoise[pos.X, pos.Y],
                        Biome         = calculatedBiome,
                        Foreground    = fgd,
                        Background    = bkg,
                        IsWalkable    = false,
                        IsTransparent = true
                    };
                }
                if (tile != null)
                {
                    OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)] = tile;
                    //if (voronoiNoiseMap[pos.X, pos.Y] >= (voronoiNoiseMap.Data.Max() - HotSpotLowerLimit))
                    //{
                    //    if (rainNoise[pos.X, pos.Y] > 0.5)
                    //        riverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                    //}
                    bool candidate = rainNoise[pos.X, pos.Y] > MinPersp && (voronoiNoiseMap[pos.X, pos.Y] >= (voronoiNoiseMap.Data.Max() - HotSpotLowerLimit));
                    switch (tile.Biome)
                    {
                    case Biome.Cold | Biome.SemiHumid:
                        if (candidate)
                        {
                            RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                        }
                        break;

                    case Biome.Cold | Biome.Humid:
                        if (candidate)
                        {
                            RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                        }
                        break;

                    case Biome.Temperate | Biome.SemiHumid:
                        if (candidate)
                        {
                            RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                        }
                        break;

                    case Biome.Temperate | Biome.Humid:
                        if (candidate)
                        {
                            RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                        }
                        break;

                    case Biome.Warm | Biome.SemiHumid:
                        if (candidate)
                        {
                            RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                        }
                        break;

                    case Biome.Warm | Biome.Humid:
                        if (candidate)
                        {
                            RiverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                        }
                        break;

                    default:
                        break;
                    }
                    //if (tile.Biome == Biome.Humid || tile.Biome == Biome.SemiHumid)
                    //{
                    //    riverCandidates.Add(OverWorld[Coord.ToIndex(pos.X, pos.Y, Width)]);
                    //}
                }
                else
                {
                    new Exception($"{tile.ID} is null.");
                }
            }
        }
コード例 #26
0
        public void FOVSenseMapEquivalency()
        {
            ArrayMap <bool> map = new ArrayMap <bool>(100, 100);

            QuickGenerators.GenerateRectangleMap(map);

            var positions = Enumerable.Range(0, 100).Select(x => map.RandomPosition(true)).ToList();

            // Make 2-layer thick walls to verify wall-lighting is working properly
            foreach (var pos in map.Positions())
            {
                if (pos.X == 1 || pos.Y == 1 || pos.X == map.Width - 2 || pos.Y == map.Height - 2)
                {
                    map[pos] = false;
                }
            }

            var fov         = new FOV(map);
            var senseMap    = new SenseMap(new LambdaTranslationMap <bool, double>(map, x => x ? 0.0 : 1.0));
            var senseSource = new SenseSource(SourceType.SHADOW, map.RandomPosition(true), 5, Distance.EUCLIDEAN);

            senseMap.AddSenseSource(senseSource);


            foreach (var curPos in positions)
            {
                if (!map[curPos])
                {
                    continue;
                }

                senseSource.Position = curPos;
                fov.Calculate(senseSource.Position, senseSource.Radius, senseSource.DistanceCalc);
                senseMap.Calculate();

                foreach (var pos in map.Positions())
                {
                    bool success = fov.BooleanFOV[pos] == (senseMap[pos] > 0.0 ? true : false);

                    if (!success)
                    {
                        Console.WriteLine($"Failed on pos {pos} with source at {senseSource.Position}.");
                        Console.WriteLine($"FOV: {fov[pos]}, SenseMap: {senseMap[pos]}");
                        Console.WriteLine($"Distance between source and fail point: {Distance.EUCLIDEAN.Calculate(senseSource.Position, pos)}, source radius: {senseSource.Radius}");
                    }

                    Assert.AreEqual(true, success);
                }
            }


            var degreesList = Enumerable.Range(0, 360).ToList();

            degreesList.FisherYatesShuffle();
            var spanList = Enumerable.Range(1, 359).ToList();

            spanList.FisherYatesShuffle();

            var degrees = degreesList.Take(30).ToList();
            var spans   = spanList.Take(30).ToList();

            senseSource.IsAngleRestricted = true;
            // Test angle-based shadowcasting
            foreach (var curPos in positions.Take(1))
            {
                if (!map[curPos])
                {
                    continue;
                }

                foreach (var degree in degrees)
                {
                    foreach (var span in spans)
                    {
                        senseSource.Angle = degree;
                        senseSource.Span  = span;

                        senseSource.Position = curPos;
                        fov.Calculate(senseSource.Position, senseSource.Radius, senseSource.DistanceCalc, senseSource.Angle, senseSource.Span);
                        senseMap.Calculate();

                        foreach (var pos in map.Positions())
                        {
                            bool success = fov.BooleanFOV[pos] == (senseMap[pos] > 0.0 ? true : false);

                            if (!success)
                            {
                                Console.WriteLine($"Failed on pos {pos} with source at {senseSource.Position}, angle: {senseSource.Angle}, span: {senseSource.Span}.");
                                Console.WriteLine($"FOV: {fov[pos]}, SenseMap: {senseMap[pos]}");
                                Console.WriteLine($"Distance between source and fail point: {Distance.EUCLIDEAN.Calculate(senseSource.Position, pos)}, source radius: {senseSource.Radius}");
                            }

                            Assert.AreEqual(true, success);
                        }
                    }
                }
            }
        }