コード例 #1
0
        public static Vector2 InsideUnitCircle(this System.Random rand)
        {
            var angle = rand.NextFloat() * Mathf.PI * 2f;
            var dist  = rand.NextFloat().Sqrt();

            return(new Vector2(Mathf.Cos(angle) * dist, Mathf.Sin(angle) * dist));
        }
コード例 #2
0
        public static Vector3 NextVector2D(this Random random, Vector3 origin, float distance)
        {
            var doubleDistance = distance * 2;

            return(origin + new Vector3(
                       random.NextFloat(doubleDistance) - distance,
                       random.NextFloat(doubleDistance) - distance,
                       0));
        }
コード例 #3
0
        private Vector2 GetRandomInCircle(Vector2 center, float min, float max, System.Random random)
        {
            bool isPosX = random.Next(0, 2) == 0;
            bool isPosY = random.Next(0, 2) == 0;

            float x = isPosX ? random.NextFloat(center.x + min, center.x + max) :
                      random.NextFloat(center.x - min, center.x - max);
            float y = isPosY ? random.NextFloat(center.y + min, center.y + max) :
                      random.NextFloat(center.y - min, center.y - max);

            return(new Vector2(x, y));
        }
コード例 #4
0
        public static void GetNoiseMap(
            float[][] map, int dx = 0, int dy            = 0,
            int octaves           = 1, float persistance = 0.5f, float lacunarity = 2.0f,
            float sx = 1.0f, float sy                    = 1.0f, int seed = 0
            )
        {
            var random = new Random(seed);

            var width  = map.GetWidth();
            var height = map.GetHeight();

            var pmin = 0.0f;
            var pmax = 1.0f;

            for (uint i = 1; i < octaves; ++i)
            {
                var ppow = Mathx.Pow(persistance, i);
                pmin += ppow * 0.25f;
                pmax += ppow * 0.75f;
            }

            var rdx = random.NextFloat(-99999.0f, +99999.0f);
            var rdy = random.NextFloat(-99999.0f, +99999.0f);

            var fx = 1.0f / (sx * width);
            var fy = 1.0f / (sy * height);

            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    float amplitude = 1.0f;
                    float frequency = 1.0f;
                    float value     = 0.0f;

                    for (int i = 0; i < octaves; ++i)
                    {
                        float sampleX = ((x - dx) * fx) * frequency + rdx;
                        float sampleY = ((y - dy) * fy) * frequency + rdy;

                        float pv = Mathf.PerlinNoise(sampleX, sampleY);
                        value += pv * amplitude;

                        amplitude *= persistance;
                        frequency *= lacunarity;
                    }

                    map[x][y] = Mathf.SmoothStep(pmin, pmax, value);
                }
            }
        }
コード例 #5
0
ファイル: RandomExt.cs プロジェクト: tsani/tanks
        /**
         * \brief
         * Computes a random value from the standard normal distribution,
         * using sampling from a uniform distribution.
         */
        public static float NextGaussianDouble(this System.Random r)
        {
            float u, v, S;

            do
            {
                u = 2.0f * r.NextFloat() - 1.0f;
                v = 2.0f * r.NextFloat() - 1.0f;
                S = u * u + v * v;
            }while (S >= 1.0f);

            float fac = Mathf.Sqrt(-2.0f * Mathf.Log(S) / S);

            return(u * fac);
        }
コード例 #6
0
        public static Vector3 PointOnSphere(this Random random, float radius = 1f)
        {
            var x = random.NextFloat();
            var y = random.NextFloat();
            var z = random.NextFloat();

            if (x == 0 && y == 0 && z == 0)
            {
                return(Vector3.forward * radius);
            }

            var lenInv = 1f / Mathf.Sqrt(x * x + y * y + z * z);

            return(new Vector3(x * lenInv, y * lenInv, z * lenInv) * radius);
        }
コード例 #7
0
        void AddNextRoomNode(IsaacRoomFactory roomFactory,
                             Queue <LevelGrowthNode> queue, HashSet <IntVector> visited, int maxRooms,
                             IsaacRoom parentRoom, int direction, float probability)
        {
            if (random.NextFloat() > probability)
            {
                return;
            }
            if (rooms.Count >= maxRooms)
            {
                return;
            }

            var nextPosition = parentRoom.position + directions[direction];

            if (!visited.Contains(nextPosition))
            {
                var nextRoom = roomFactory.CreateRoom(nextPosition);
                rooms.Add(nextRoom);
                var nextNode = new LevelGrowthNode();
                nextNode.room          = nextRoom;
                nextNode.moveDirection = direction;
                queue.Enqueue(nextNode);
                visited.Add(nextPosition);

                // Create a door between the two rooms
                ConnectRoomsWithDoors(parentRoom, nextRoom);
            }
            else
            {
                // See if we can connect to the other room
                // first make sure we don't already have a connection between the two
                var nextRoom = GetRoomAt(nextPosition);
                if (!ContainsDoorBetween(parentRoom.roomId, nextRoom.roomId))
                {
                    float loopTest = random.NextFloat();
                    if (loopTest < isaacConfig.cycleProbability)
                    {
                        // Connect the two rooms together
                        if (nextRoom != null)
                        {
                            // Create a door between the two rooms
                            ConnectRoomsWithDoors(parentRoom, nextRoom);
                        }
                    }
                }
            }
        }
コード例 #8
0
ファイル: BSPDungeonBuilder.cs プロジェクト: kabirules/Kenny
        /// <summary>
        /// This function assumes that the cell is big enough to split.
        /// Make sure to call CanSplit function before calling this
        /// </summary>
        public void Split(float splitRatio, System.Random random)
        {
            if (bounds.Width == bounds.Length)
            {
                horizontalSplit = random.NextFloat() < 0.5f;
            }
            else
            {
                horizontalSplit = (bounds.Width > bounds.Length);
            }

            int totalSize = horizontalSplit ? bounds.Width : bounds.Length;

            int left  = Mathf.RoundToInt(totalSize * splitRatio);
            int right = totalSize - left;

            var child0 = new BSPNodeObject();

            child0.parent        = this;
            child0.padding       = padding;
            child0.depthFromRoot = depthFromRoot + 1;

            var child1 = new BSPNodeObject();

            child1.parent        = this;
            child1.padding       = padding;
            child1.depthFromRoot = depthFromRoot + 1;

            var loc0  = bounds.Location;
            var size0 = bounds.Size;

            var loc1  = bounds.Location;
            var size1 = bounds.Size;

            if (horizontalSplit)
            {
                size0.x = left;

                loc1.x += left;
                size1.x = right;
            }
            else
            {
                size0.z = left;

                loc1.z += left;
                size1.z = right;
            }

            child0.bounds = new Rectangle(loc0, size0);
            child1.bounds = new Rectangle(loc1, size1);

            children = new BSPNodeObject[] { child0, child1 };
        }
コード例 #9
0
        public async UniTask <int[, ]> Spawn(int mapWidth = 22, int mapLength = 22, float fillRatio = 10f)
        {
            System.Random prng = new System.Random(seed.GetHashCode());
            this.transform.DestroyChildrenImmediate();
            var map = new int[mapWidth, mapLength];

            mapObjects = new List <MapObject>();
            map.Fill(1);


            for (int i = 0; i < mapWidth; i++)
            {
                for (int j = 0; j < mapLength; j++)
                {
                    //outerWall
                    if (i == 0 || j == 0 || i == mapWidth - 1 || j == mapLength - 1)
                    {
                        map[i, j] = 0;
                        var wall = Instantiate(outerWallPrefab);
                        wall.transform.position = new Vector3(i, 1f, j);
                        wall.transform.parent   = this.transform;
                        var mapObejct = wall.GetComponent <MapObject>();
                        mapObjects.Add(mapObejct);
                        mapObejct.InitObject();
                    }

                    else
                    {
                        var ground = Instantiate(groundBlockPrefab);
                        ground.transform.position = new Vector3(i, 0f, j);
                        ground.transform.parent   = this.transform;
                        var mapObejct = ground.GetComponent <MapObject>();
                        mapObjects.Add(mapObejct);


                        mapObejct.InitObject();
                        //Obstacle
                        if (prng.NextFloat(0f, 100f) < fillRatio && (CharacterManager.Instance.initialLocation.X != i && CharacterManager.Instance.initialLocation.Y != j))
                        {
                            map[i, j] = 0;
                            var obstacle = Instantiate(obstaclePrefab, new Vector3(i, 1f, j), Quaternion.identity);
                            obstacle.transform.parent = this.transform;
                            var mapObejcts = obstacle.GetComponent <MapObject>();
                            mapObejcts.height = Random.Range(1, 4);
                            mapObjects.Add(mapObejcts);
                            mapObejcts.InitObject();
                        }
                    }
                }
            }
            "Map Spawn Complete".Log();
            return(map);
        }
コード例 #10
0
        public static Tuple <Tuple <float, float>, Tuple <Tuple <float, float>, Tuple <Tuple <float, float>, Unit> > > MakeRandomBody()
        {
            const double             maxValue = 50.0;
            __opComma <float, float> fst;
            unit unit;
            __opComma <Tuple <float, float>, Unit> acceleration = new __opComma <Tuple <float, float>, Unit>();

            fst                 = new __opComma <float, float>();
            unit                = new unit();
            fst.__arg0          = r.NextFloat(maxValue);
            fst.__arg1          = r.NextFloat(maxValue);
            acceleration.__arg0 = fst;
            acceleration.__arg1 = unit;
            __opComma <Tuple <float, float>, Tuple <Tuple <float, float>, Unit> > velocity = new __opComma <Tuple <float, float>, Tuple <Tuple <float, float>, Unit> >();

            fst             = new __opComma <float, float>();
            fst.__arg0      = r.NextFloat(maxValue);
            fst.__arg1      = r.NextFloat(maxValue);
            velocity.__arg0 = fst;
            velocity.__arg1 = acceleration;
            __opComma <Tuple <float, float>, Tuple <Tuple <float, float>, Tuple <Tuple <float, float>, Unit> > > position = new __opComma <Tuple <float, float>, Tuple <Tuple <float, float>, Tuple <Tuple <float, float>, Unit> > >();

            fst             = new __opComma <float, float>();
            fst.__arg0      = r.NextFloat(maxValue);
            fst.__arg1      = r.NextFloat(maxValue);
            position.__arg0 = fst;
            position.__arg1 = velocity;
            return(position);
        }
コード例 #11
0
        public static void GetRandomMap(bool[][] map, float fill = 0.5f, int seed = 0)
        {
            var random = new Random(seed);

            var width  = map.GetWidth();
            var height = map.GetHeight();

            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    var rv = random.NextFloat();
                    map[x][y] = rv < fill;
                }
            }
        }
コード例 #12
0
        protected override void Process()
        {
            output = new EntityCollection();

            foreach (KeyValuePair <Coordinate, HashSet <string> > chunk in entities.AllChunks)
            {
                System.Random RNG = graph.ChunkRandoms[chunk.Key];
                foreach (string entityID in chunk.Value)
                {
                    if (!entities.TryGetEntity(entityID, out IEntity entity))
                    {
                        continue;
                    }
                    if (RNG.NextFloat(0, 1) > sampler.SamplePosition(entity.Position))
                    {
                        output.AddEntity(entity);
                    }
                }
            }
        }
コード例 #13
0
        public static void Shuffle <T>(IList <T> list, System.Random rd)
        {
            if (list.Count <= 1)
            {
                return;
            }
            int currentIndex = list.Count;
            int randomIndex  = 0;
            T   temporaryValue;

            while (currentIndex > 0)
            {
                randomIndex = Mathf.FloorToInt(rd.NextFloat() * currentIndex);
                currentIndex--;
                temporaryValue = list[currentIndex];
                if (list.Count <= randomIndex)
                {
                    continue;                            // for weird situations on shutdown or so.
                }
                list[currentIndex] = list[randomIndex];
                list[randomIndex]  = temporaryValue;
            }
        }
コード例 #14
0
        void GenerateLevelLayout()
        {
            var tiles = new List <MarioTile> ();

            marioModel.levelWidth = random.Next(marioConfig.minLength, marioConfig.maxLength);

            bool addingGap             = false;
            int  targetGapDistance     = 0;
            int  currentGapDistance    = 0;
            int  currentNonGapDistance = 0;

            int y = 0;

            for (int x = 0; x < marioModel.levelWidth; x++)
            {
                var position = new IntVector(x, y, 0);

                if (!addingGap)
                {
                    if (x >= 2)
                    {
                        bool changeHeight = random.NextFloat() < marioConfig.heightVariationProbablity;
                        if (changeHeight)
                        {
                            bool moveUp = random.NextFloat() < 0.5f;
                            y += moveUp ? 1 : -1;
                        }
                    }

                    // Create a tile here

                    var tile = new MarioTile();
                    tile.position = position;
                    tile.tileType = MarioTileType.Ground;
                    tiles.Add(tile);

                    currentNonGapDistance++;

                    if (currentNonGapDistance >= marioConfig.minNonGap)
                    {
                        // Check if we need to add a gap
                        addingGap = random.NextFloat() < marioConfig.gapProbability;
                        if (addingGap)
                        {
                            currentGapDistance = 0;
                            targetGapDistance  = random.Next(marioConfig.minGap, marioConfig.maxGap);
                        }
                    }
                }
                else
                {
                    bool corridor = targetGapDistance > marioConfig.maxJumpTileDistance;
                    // We are adding a gap
                    var tile = new MarioTile();
                    tile.position = position;
                    tile.tileType = corridor ? MarioTileType.Corridor : MarioTileType.Gap;
                    tiles.Add(tile);

                    currentGapDistance++;
                    if (currentGapDistance >= targetGapDistance)
                    {
                        addingGap             = false;
                        currentNonGapDistance = 0;
                    }
                }
            }

            marioModel.tiles = tiles.ToArray();
        }
コード例 #15
0
 private float getRandomPs()
 {
     return(r.NextFloat(rMin, rMax));
 }
コード例 #16
0
        /// <summary>
        /// Generate a layout and save it in the model
        /// </summary>
        void GenerateCityLayout()
        {
            var roadGraphSettings = new RoadGraphBuilderSettings();

            roadGraphSettings.interNodeDistance = cityConfig.interNodeDistance;
            var roadGraphBuilder = new RoadGraphBuilder(roadGraphSettings);

            float startRadius = cityConfig.startRadius;
            float endRadius   = cityConfig.endRadius;
            var   center      = Vector3.zero;

            float mainRoadStrength  = cityConfig.mainRoadStrength;
            float sideRoadStrength  = cityConfig.sideRoadStrength;
            float interRingDistance = (endRadius - startRadius) / (cityConfig.numRings - 1);

            // Draw the city rings
            {
                float ringRadius = startRadius;
                for (int r = 0; r < cityConfig.numRings; r++)
                {
                    roadGraphBuilder.CreateCircle(center, ringRadius, mainRoadStrength);
                    if (r < cityConfig.numRings - 1)
                    {
                        float ringLaneRadius = ringRadius + interRingDistance / 2.0f;
                        roadGraphBuilder.CreateCircle(center, ringLaneRadius, sideRoadStrength);
                    }
                    ringRadius += interRingDistance;
                }
            }

            // Draw the ray lanes ejecting out from the center
            float interRayAngle = Mathf.PI * 2 / cityConfig.numRays;

            for (int i = 0; i < cityConfig.numRays; i++)
            {
                float ringRadius          = startRadius;
                int   mainSegmentToRemove = random.Next() % (cityConfig.numRings - 1);
                for (int r = 0; r < cityConfig.numRings - 1; r++)
                {
                    float nextRingRadius = ringRadius + interRingDistance;

                    bool bDrawMainSegment = (r != mainSegmentToRemove);

                    if (bDrawMainSegment)
                    {
                        float angle         = i * interRayAngle;
                        var   direction     = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle));
                        float midRingRadius = ringRadius + (nextRingRadius - ringRadius) / 2.0f;

                        var start = center + direction * ringRadius;
                        var end   = center + direction * midRingRadius;
                        roadGraphBuilder.CreateLine(start, end, mainRoadStrength);

                        start = center + direction * midRingRadius;
                        end   = center + direction * nextRingRadius;
                        roadGraphBuilder.CreateLine(start, end, mainRoadStrength);
                    }

                    // Draw the side segments
                    {
                        float interSideRayAngle     = interRayAngle / (r + 2);
                        float sideRayAngle          = i * interRayAngle;
                        float interSideRingDistance = interRingDistance / 2.0f;
                        for (int si = 0; si <= r; si++)
                        {
                            sideRayAngle += interSideRayAngle;
                            for (int t = 0; t < 2; t++)
                            {
                                bool bRemoveSideSegment = (random.NextFloat() < cityConfig.sideRoadRemovalProbability);
                                if (!bRemoveSideSegment)
                                {
                                    float perimeter          = Mathf.PI * 2 * ringRadius;
                                    float angleRandomization = cityConfig.randomSideLaneOffsetAngle * Mathf.Deg2Rad / perimeter;
                                    float randomValue        = random.NextFloat() * 2 - 1;
                                    float randomizedAngle    = sideRayAngle + angleRandomization * randomValue;
                                    float laneStartRadius    = ringRadius + interSideRingDistance * t;
                                    float laneEndRadius      = ringRadius + interSideRingDistance * (t + 1);

                                    var direction = new Vector3(Mathf.Cos(randomizedAngle), 0, Mathf.Sin(randomizedAngle));
                                    var start     = center + direction * laneStartRadius;
                                    var end       = center + direction * laneEndRadius;
                                    roadGraphBuilder.CreateLine(start, end, sideRoadStrength);
                                }
                            }
                        }
                    }

                    ringRadius = nextRingRadius;
                }
            }

            cityModel.roadGraph = roadGraphBuilder.BakeRoadGraph();

            var layoutBuilder = new RoadLayoutBuilder(cityModel.roadGraph, cityConfig.roadMesh);

            layoutBuilder.RoadBlockLayoutBuilt += LayoutBuilder_RoadBlockLayoutBuilt;

            cityModel.layoutGraph = layoutBuilder.BakeLayoutGraph();
        }
コード例 #17
0
 public static float NextFloat(this Random random, float min, float max)
 {
     return(min + (max - min) * random.NextFloat());
 }
コード例 #18
0
        /// <summary>
        /// Generate a layout and save it in the model
        /// </summary>
        void GenerateCityLayout()
        {
            var width  = random.Range(demoConfig.minSize, demoConfig.maxSize);
            var length = random.Range(demoConfig.minSize, demoConfig.maxSize);

            demoModel.CityWidth  = width;
            demoModel.CityHeight = length;

            demoModel.Cells = new SimpleCityCell[width, length];

            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = new SimpleCityCell();
                    cell.Position         = new IntVector(x, 0, z);
                    cell.CellType         = SimpleCityCellType.House;
                    cell.Rotation         = GetRandomRotation();
                    demoModel.Cells[x, z] = cell;
                }
            }


            // Build a road network by removing some houses
            // First build roads along the edge of the map
            for (int x = 0; x < width; x++)
            {
                MakeRoad(x, 0);
                MakeRoad(x, length - 1);
            }
            for (int z = 0; z < length; z++)
            {
                MakeRoad(0, z);
                MakeRoad(width - 1, z);
            }

            // Create roads in-between
            for (int x = GetRandomBlockSize() + 1; x < width; x += GetRandomBlockSize() + 1)
            {
                if (width - x <= 2)
                {
                    continue;
                }
                for (int z = 0; z < length; z++)
                {
                    MakeRoad(x, z);
                }
            }
            for (int z = GetRandomBlockSize() + 1; z < length; z += GetRandomBlockSize() + 1)
            {
                if (length - z <= 2)
                {
                    continue;
                }
                for (int x = 0; x < width; x++)
                {
                    MakeRoad(x, z);
                }
            }

            // Insert 2x houses (bigger houses)
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    if (CanContainBiggerHouse(x, z))
                    {
                        if (random.NextFloat() < demoConfig.biggerHouseProbability)
                        {
                            InsertBiggerHouse(x, z);
                        }
                    }
                }
            }

            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = demoModel.Cells[x, z];
                    if (cell.CellType == SimpleCityCellType.House)
                    {
                        FaceHouseTowardsRoad(cell);
                    }
                }
            }


            // Create padding cells

            var padding     = demoConfig.cityWallPadding;
            var paddedCells = new List <SimpleCityCell>();

            for (int p = 1; p <= padding; p++)
            {
                var currentPadding = p;

                var sx = -currentPadding;
                var sz = -currentPadding;
                var ex = width + currentPadding - 1;
                var ez = length + currentPadding - 1;

                // Fill it with city wall padding marker
                for (int x = sx; x < ex; x++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(x, sz, cellType));
                    paddedCells.Add(CreateCell(x, ez, cellType));
                }

                for (int z = sz; z < ez; z++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(sx, z, cellType));
                    paddedCells.Add(CreateCell(ex, z, cellType));
                }
            }
            demoModel.WallPaddingCells = paddedCells.ToArray();
        }
コード例 #19
0
        public void Generate(ValueStore keyStore)
        {
            Reset ();

            if (park == null) return;

            var seed = 0;
            // Generate a random seed.
            foreach (char c in keyStore.Seed) {
                seed += (int)c;
            }

            _waterRandom = new SRandom(seed);
            _treeRandom = new SRandom(seed);

            for (var z = 0; z <= park.zSize; z++)
            {
                for (var x = 0; x <= park.xSize; x++)
                {
                    // Calculate height of terrain patch based on perlin noise.
                    var y = (Mathf.PerlinNoise(x/(park.xSize* keyStore.PlainScale) + seed, z/(park.zSize*keyStore.PlainScale) + seed)*
                        (1 + keyStore.DitchRatio)) -
                        (float)keyStore.DitchRatio;
                    if (y < 0 && keyStore.DitchRatio != 0)
                        y /= keyStore.DitchRatio;

                    y = y*(y < 0 ? keyStore.MaxDepth : (float)keyStore.MaxHeight);
                    y = y > 0 ? Mathf.FloorToInt(y) : Mathf.CeilToInt(y);

                    // Generate terrain type for the terrain patch based on perlin noise.
                    if (keyStore.GenerateTerrainType)
                    {
                        var patch = park.getTerrain(x, z);
                        if (patch != null)
                        {
                            var types = ScriptableSingleton<AssetManager>.Instance.terrainTypes.Length;
                            var terrainTypeIndex = Mathf.PerlinNoise(x/(park.xSize*keyStore.TerrainScale ) + seed,
                                z/(park.xSize*keyStore.TerrainScale) + seed);

                            patch.TerrainType = Mathf.FloorToInt(Mathf.Abs(terrainTypeIndex - 0.5f)*types);
                        }
                    }

                    // Limit heights near road.
                    var roadWidth = Mathf.Max(MIN_ROAD_WIDTH, keyStore.EntranceClearance);
                    if (x < roadWidth)
                        continue;

                    y = Mathf.Clamp(y, roadWidth - x, x - roadWidth);

                    // Limit heights near entrance.
                    var distanceToEntrance = Vector3.Distance(park.parkEntrances.First().transform.position,
                        new Vector3(x, GROUND_HEIGHT, z));

                    if (distanceToEntrance < roadWidth)
                        continue;

                    // If this location should be raised, change the hight of the patch and the ones around.
                    if (y != 0)
                        for (var cornerIndex = 0; cornerIndex < 4; cornerIndex++)
                        {
                            var ox = cornerIndex == 1 || cornerIndex == 2 ? 1 : 0;
                            var oz = cornerIndex == 2 || cornerIndex == 3 ? 1 : 0;

                            var patch = park.getTerrain(x - ox, z - oz);

                            if (patch != null)
                            {
                                var current = patch.h[cornerIndex] - DEF_HEIGHT;
                                patch.smoothChangeHeight(park, cornerIndex, y - current);
                            }
                        }
                }
            }

            // Randomly flood the map.
            for (var i = 0; i < keyStore.FloodRounds; i++)
            {
                var x = Mathf.RoundToInt(_waterRandom.NextFloat(keyStore.EntranceClearance, park.xSize));
                var z = Mathf.RoundToInt(_waterRandom.NextFloat(0, park.zSize));

                var patch = park.getTerrain(x, z);
                if (patch == null || patch.hasWater() || patch.getLowestHeight() >= GROUND_HEIGHT) continue;

                WaterFlooding.flood(new Vector3(x,   GROUND_HEIGHT -  WATTER_OFFSET, z));
            }

            // Randomly spawn a forrest.
            for (var i = 0; i < keyStore.TreeCount; i++)
            {
                var x = Mathf.RoundToInt(_treeRandom.NextFloat(keyStore.EntranceClearance, park.xSize -PARK_FENCE_OFFSET));
                var z = Mathf.RoundToInt(_treeRandom.NextFloat(PARK_FENCE_OFFSET, park.zSize - PARK_FENCE_OFFSET));

                var patch = park.getTerrain(x, z);
                if (patch == null || patch.hasWater()) continue;

                var y = patch.getHeighestHeight();
                if (y != patch.getLowestHeight()) continue;

                TreeEntity fir = null;
                foreach (var o in ScriptableSingleton<AssetManager>.Instance.getDecoObjects())
                    if (o.getName().StartsWith("Fir") && o is TreeEntity) fir = o as TreeEntity;

                if (fir != null)
                {
                    var tree = ConfigWindow.Instantiate(fir);
                    tree.transform.position = new Vector3(x, y, z);
                    tree.transform.forward = Vector3.forward;
                    tree.Initialize();
                    tree.startAnimateSpawn(Vector3.zero);
                }
            }
        }
コード例 #20
0
        // This is called by the builders that do not support theming
        public override void BuildNonThemedDungeon(DungeonSceneProvider sceneProvider)
        {
            random = new System.Random((int)config.Seed);
            propSockets.Clear();

            // We know that the dungeon prefab would have the appropriate config and models attached to it
            // Cast and save it for future reference
            snapConfig = config as SnapConfig;
            snapModel  = model as SnapModel;

            if (snapConfig == null)
            {
                Debug.LogError("No snap config script found in dungeon game object");
                return;
            }

            if (snapModel == null)
            {
                Debug.LogError("No snap model script found in dungeon game object");
                return;
            }

            // Generate the module info list
            var ModuleInfos = new List <ModuleInfo>();
            {
                var RegisteredModuleList = new List <GameObject>();
                RegisteredModuleList.AddRange(snapConfig.Modules);
                RegisteredModuleList.AddRange(snapConfig.StartModules);
                RegisteredModuleList.AddRange(snapConfig.EndModules);
                RegisteredModuleList.AddRange(snapConfig.BranchEndModules);
                var RegisteredModules = new HashSet <GameObject>(RegisteredModuleList);

                foreach (var RegisteredModule in RegisteredModules)
                {
                    var moduleInfo = GenerateModuleInfo(RegisteredModule);
                    ModuleInfos.Add(moduleInfo);
                }
            }


            var StartNode = new ModuleGrowthNode();

            StartNode.IncomingModuleDoorIndex = -1;
            StartNode.startNode       = true;
            StartNode.ModuleTransform = Matrix4x4.identity;

            var OccupiedBounds = new List <Bounds>();

            var LayoutBuildState = new SnapLayoutBuildState();

            LayoutBuildState.ModuleInfoList = ModuleInfos;

            // Build the main branch
            ModuleBuildNode BuildNode = BuildLayoutRecursive(StartNode, OccupiedBounds, 1, snapConfig.MainBranchSize, true, false, LayoutBuildState);

            // Build the side branches
            {
                var MainBranchNodes = new List <ModuleBuildNode>();

                // Grab the nodes in the main branch
                {
                    ModuleBuildNode BranchNode = BuildNode;
                    while (BranchNode != null)
                    {
                        BranchNode.bMainBranch = true;
                        MainBranchNodes.Add(BranchNode);

                        // Move forward
                        if (BranchNode.Extensions.Count == 0)
                        {
                            break;
                        }

                        BranchNode = BranchNode.Extensions[0];
                    }
                }


                // Iterate through the nodes in the main branch and start branching out
                for (int i = 0; i < MainBranchNodes.Count; i++)
                {
                    ModuleBuildNode BranchStartNode = MainBranchNodes[i];
                    ModuleBuildNode BranchNextNode  = i + 1 < MainBranchNodes.Count ? MainBranchNodes[i + 1] : null;

                    ModuleInfo BranchModule      = BranchStartNode.Module;
                    int        IncomingDoorIndex = BranchStartNode.IncomingDoorIndex;
                    int        OutgoingDoorIndex = BranchNextNode != null ? BranchNextNode.IncomingDoorIndex : -1;
                    int        NumDoors          = BranchModule.ConnectionTransforms.Length;
                    for (int DoorIndex = 0; DoorIndex < NumDoors; DoorIndex++)
                    {
                        if (DoorIndex == IncomingDoorIndex || DoorIndex == OutgoingDoorIndex)
                        {
                            // These doors are already extended
                            continue;
                        }

                        bool bGrowFromHere = (random.NextFloat() < snapConfig.SideBranchProbability);
                        if (!bGrowFromHere)
                        {
                            continue;
                        }

                        // TODO: Optimize me.  it recalculates the the bounds for the whole tree for every main branch node
                        OccupiedBounds.Clear();
                        CalculateOccupiedBounds(BuildNode, OccupiedBounds);

                        var BranchGrowNode = new ModuleGrowthNode();
                        BranchGrowNode.IncomingModuleDoorIndex = DoorIndex;
                        BranchGrowNode.IncomingModule          = BranchStartNode.Module;
                        BranchGrowNode.ModuleTransform         = BranchStartNode.AttachmentConfig.AttachedModuleTransform;

                        LayoutBuildState = new SnapLayoutBuildState();
                        LayoutBuildState.ModuleInfoList = ModuleInfos;
                        ModuleBuildNode BranchBuildNode = BuildLayoutRecursive(BranchGrowNode, OccupiedBounds, 1, snapConfig.SideBranchSize, false, false, LayoutBuildState);
                        if (BranchBuildNode != null)
                        {
                            // Make sure we don't end up with an undesirable leaf node
                            if (BranchBuildNode.Extensions.Count == 0 && BranchBuildNode.Module != null && snapConfig.SideBranchSize > 1)
                            {
                                continue;
                            }

                            BranchBuildNode.Parent = BranchStartNode;
                            BranchStartNode.Extensions.Add(BranchBuildNode);
                        }
                    }
                }
            }

            snapModel.ResetModel();


            sceneProvider.OnDungeonBuildStart();

            // Spawn the modules and register them in the model
            {
                var spawnedModuleList = new List <SnapModule>();
                TraverseTree(BuildNode, delegate(ModuleBuildNode Node)
                {
                    // Spawn a module at this location
                    ModuleInfo moduleInfo = Node.Module;

                    var templateInfo            = new GameObjectPropTypeData();
                    templateInfo.Template       = moduleInfo.ModuleTemplate;
                    templateInfo.NodeId         = moduleInfo.ModuleGuid.ToString();
                    templateInfo.Offset         = Matrix4x4.identity;
                    templateInfo.IsStaticObject = true;

                    Node.spawnedModule = sceneProvider.AddGameObject(templateInfo, Node.AttachmentConfig.AttachedModuleTransform);

                    // Register this in the model
                    var snapModule        = new SnapModule();
                    snapModule.InstanceID = Node.ModuleInstanceID;
                    spawnedModuleList.Add(snapModule);
                });
                snapModel.modules = spawnedModuleList.ToArray();
            }

            // Generate the list of connections
            {
                var connectionList = new List <SnapModuleConnection>();
                TraverseTree(BuildNode, delegate(ModuleBuildNode Node)
                {
                    if (Node.Parent != null)
                    {
                        var Connection = new SnapModuleConnection();
                        Connection.ModuleAInstanceID = Node.ModuleInstanceID;
                        Connection.DoorAIndex        = Node.AttachmentConfig.AttachedModuleDoorIndex;

                        Connection.ModuleBInstanceID = Node.Parent.ModuleInstanceID;
                        Connection.DoorBIndex        = Node.IncomingDoorIndex;

                        connectionList.Add(Connection);
                    }
                });
                snapModel.connections = connectionList.ToArray();
            }

            sceneProvider.OnDungeonBuildStop();

            FixupDoorStates(BuildNode);
        }
コード例 #21
0
        public static float NextFloatRange(this System.Random random, float min, float max)
        {
            float f = random.NextFloat();

            return(MathW.Remap(f, 0, 1, min, max));
        }
コード例 #22
0
        /// <summary>
        /// Generate a layout and save it in the model
        /// </summary>
        void GenerateCityLayout()
        {
            var width  = random.Range(demoConfig.minSize, demoConfig.maxSize);
            var length = random.Range(demoConfig.minSize, demoConfig.maxSize);

            demoModel.CityWidth  = width;
            demoModel.CityHeight = length;

            demoModel.Cells = new SimpleCityCell[width, length];

            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = new SimpleCityCell();
                    cell.Position         = new IntVector(x, 0, z);
                    cell.CellType         = SimpleCityCellType.House;
                    cell.Rotation         = GetRandomRotation();
                    demoModel.Cells[x, z] = cell;
                }
            }


            // Build a road network by removing some houses
            // First build roads along the edge of the map
            for (int x = 0; x < width; x++)
            {
                MakeRoad(x, 0);
                MakeRoad(x, length - 1);
            }
            for (int z = 0; z < length; z++)
            {
                MakeRoad(0, z);
                MakeRoad(width - 1, z);
            }

            // Create roads in-between
            for (int x = GetRandomBlockSize() + 1; x < width; x += GetRandomBlockSize() + 1)
            {
                if (width - x <= 2)
                {
                    continue;
                }
                for (int z = 0; z < length; z++)
                {
                    MakeRoad(x, z);
                }
            }
            for (int z = GetRandomBlockSize() + 1; z < length; z += GetRandomBlockSize() + 1)
            {
                if (length - z <= 2)
                {
                    continue;
                }
                for (int x = 0; x < width; x++)
                {
                    MakeRoad(x, z);
                }
            }

            RemoveRoadEdges();


            // Insert bigger houses
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    foreach (var blockDimension in demoConfig.customBlockDimensions)
                    {
                        bool bProcess = random.NextFloat() < blockDimension.probability;
                        if (!bProcess)
                        {
                            continue;
                        }

                        int BlockWidth  = blockDimension.sizeX;
                        int BlockHeight = blockDimension.sizeZ;

                        InsertHouseDelegate InsertHouse = delegate() {
                            if (CanContainBiggerHouse(x, z, BlockWidth, BlockHeight))
                            {
                                if (random.NextFloat() < demoConfig.biggerHouseProbability)
                                {
                                    InsertBiggerHouse(x, z, BlockWidth, BlockHeight, 0, blockDimension.markerName);
                                }
                            }
                        };


                        InsertHouseDelegate InsertHouse90 = delegate()
                        {
                            // Try the 90 degrees rotated version
                            if (CanContainBiggerHouse(x, z, BlockHeight, BlockWidth))
                            {
                                if (random.NextFloat() < demoConfig.biggerHouseProbability)
                                {
                                    InsertBiggerHouse(x, z, BlockHeight, BlockWidth, 90, blockDimension.markerName);
                                }
                            }
                        };

                        if (random.NextFloat() < 0.5f)
                        {
                            InsertHouse();
                            InsertHouse90();
                        }
                        else
                        {
                            InsertHouse90();
                            InsertHouse();
                        }
                    }
                }
            }


            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    var cell = demoModel.Cells[x, z];
                    if (cell.CellType == SimpleCityCellType.House)
                    {
                        FaceHouseTowardsRoad(cell);
                    }
                }
            }


            // Create padding cells

            var padding     = demoConfig.cityWallPadding;
            var paddedCells = new List <SimpleCityCell>();

            for (int p = 1; p <= padding; p++)
            {
                var currentPadding = p;

                var sx = -currentPadding;
                var sz = -currentPadding;
                var ex = width + currentPadding - 1;
                var ez = length + currentPadding - 1;

                // Fill it with city wall padding marker
                for (int x = sx; x < ex; x++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(x, sz, cellType));
                    paddedCells.Add(CreateCell(x, ez, cellType));
                }

                for (int z = sz; z < ez; z++)
                {
                    SimpleCityCellType cellType = SimpleCityCellType.CityWallPadding;

                    paddedCells.Add(CreateCell(sx, z, cellType));
                    paddedCells.Add(CreateCell(ex, z, cellType));
                }
            }
            demoModel.WallPaddingCells = paddedCells.ToArray();
        }
コード例 #23
0
 public static int NextIntRanged(this System.Random rand, int min, int max)
 {
     return(min + UnityEngine.Mathf.FloorToInt(rand.NextFloat() * (max - min)));
 }
コード例 #24
0
        /// <inheritdoc />
        public override List <MeshData> Build(Building building)
        {
            var random     = new System.Random((int)building.Id);
            var footprint  = building.Footprint;
            var roofOffset = building.Elevation + building.MinHeight + building.Height;
            var roofHeight = roofOffset + building.RoofHeight;

            var offset = new ClipperOffset();

            offset.AddPath(footprint.Select(p => new IntPoint(p.X * Scale, p.Y * Scale)).ToList(),
                           JoinType.jtMiter, EndType.etClosedPolygon);

            var result = new List <List <IntPoint> >();

            offset.Execute(ref result, random.NextFloat(1, 3) * -Scale);

            if (result.Count != 1 || result[0].Count != footprint.Count)
            {
                Trace.Warn(LogCategory, Strings.RoofGenFailed, Name, building.Id.ToString());
                return(base.Build(building));
            }

            var    topVertices = ObjectPool.NewList <Vector2d>(footprint.Count);
            double scale       = Scale;

            foreach (var intPoint in result[0])
            {
                topVertices.Add(new Vector2d(intPoint.X / scale, intPoint.Y / scale));
            }
            // NOTE need reverse vertices
            topVertices.Reverse();

            var floorCount = building.Levels;
            var topMesh    = CreateMesh(topVertices);
            var floorMesh  = CreateMesh(footprint);

            var roofVertexCount  = topMesh.Triangles.Count * 3 * 2 + footprint.Count * 2 * 12;
            var floorVertexCount = floorMesh.Triangles.Count * 3 * 2 * floorCount;

            var vertexCount = roofVertexCount + floorVertexCount;

            var planeCount = footprint.Count + floorCount + 1;

            bool limitIsReached = false;

            if (vertexCount * 2 > Consts.MaxMeshSize)
            {
                vertexCount    = roofVertexCount;
                planeCount     = building.Footprint.Count + 1;
                limitIsReached = true;
            }

            var meshIndex = new MultiPlaneMeshIndex(planeCount, vertexCount);
            var meshData  = new MeshData(meshIndex, vertexCount);

            var roofGradient = CustomizationService.GetGradient(building.RoofColor);
            int index        = FindStartIndex(topVertices[0], footprint);

            for (int i = 0; i < topVertices.Count; i++)
            {
                var top        = topVertices[i];
                var bottom     = footprint[(index + i) % footprint.Count];
                var nextTop    = topVertices[(i + 1) % topVertices.Count];
                var nextBottom = footprint[(index + i + 1) % footprint.Count];

                var v0 = new Vector3((float)bottom.X, roofOffset, (float)bottom.Y);
                var v1 = new Vector3((float)nextBottom.X, roofOffset, (float)nextBottom.Y);
                var v2 = new Vector3((float)nextTop.X, roofHeight, (float)nextTop.Y);
                var v3 = new Vector3((float)top.X, roofHeight, (float)top.Y);

                meshIndex.AddPlane(v0, v1, v2, meshData.NextIndex);
                AddTriangle(meshData, roofGradient, v0, v2, v3);
                AddTriangle(meshData, roofGradient, v2, v0, v1);
            }
            ObjectPool.StoreList(topVertices);

            // Attach top reusing roof context object
            var context = new RoofContext()
            {
                Mesh      = topMesh,
                MeshData  = meshData,
                MeshIndex = meshIndex,

                Bottom             = roofHeight,
                FloorCount         = 1,
                FloorHeight        = building.Height / floorCount,
                FloorFrontGradient = CustomizationService.GetGradient(building.FloorFrontColor),
                FloorBackGradient  = CustomizationService.GetGradient(building.FloorBackColor),

                IsLastRoof        = true,
                RoofFrontGradient = roofGradient,
                RoofBackGradient  = roofGradient
            };

            AttachFloors(context);

            if (!limitIsReached)
            {
                context.Mesh       = floorMesh;
                context.MeshData   = meshData;
                context.Bottom     = building.Elevation + building.MinHeight;
                context.FloorCount = floorCount;
                context.IsLastRoof = false;
                AttachFloors(context);
                return(new List <MeshData>(1)
                {
                    meshData
                });
            }

            var meshDataList = BuildFloors(building, building.Levels, false);

            meshDataList.Add(meshData);
            return(meshDataList);
        }
コード例 #25
0
        public void Generate(ValueStore keyStore)
        {
            Reset();

            if (park == null)
            {
                return;
            }

            var seed = 0;

            // Generate a random seed.
            foreach (char c in keyStore.Seed)
            {
                seed += (int)c;
            }

            _waterRandom = new SRandom(seed);
            _treeRandom  = new SRandom(seed);


            for (var z = 0; z <= park.zSize; z++)
            {
                for (var x = 0; x <= park.xSize; x++)
                {
                    // Calculate height of terrain patch based on perlin noise.
                    var y = (Mathf.PerlinNoise(x / (park.xSize * keyStore.PlainScale) + seed, z / (park.zSize * keyStore.PlainScale) + seed) *
                             (1 + keyStore.DitchRatio)) -
                            (float)keyStore.DitchRatio;
                    if (y < 0 && keyStore.DitchRatio != 0)
                    {
                        y /= keyStore.DitchRatio;
                    }


                    y = y * (y < 0 ? keyStore.MaxDepth : (float)keyStore.MaxHeight);
                    y = y > 0 ? Mathf.FloorToInt(y) : Mathf.CeilToInt(y);

                    // Generate terrain type for the terrain patch based on perlin noise.
                    if (keyStore.GenerateTerrainType)
                    {
                        var patch = park.getTerrain(x, z);
                        if (patch != null)
                        {
                            var types            = ScriptableSingleton <AssetManager> .Instance.terrainTypes.Length;
                            var terrainTypeIndex = Mathf.PerlinNoise(x / (park.xSize * keyStore.TerrainScale) + seed,
                                                                     z / (park.xSize * keyStore.TerrainScale) + seed);

                            patch.TerrainType = Mathf.FloorToInt(Mathf.Abs(terrainTypeIndex - 0.5f) * types);
                        }
                    }

                    // Limit heights near road.
                    var roadWidth = Mathf.Max(MIN_ROAD_WIDTH, keyStore.EntranceClearance);
                    if (x < roadWidth)
                    {
                        continue;
                    }

                    y = Mathf.Clamp(y, roadWidth - x, x - roadWidth);

                    // Limit heights near entrance.
                    var distanceToEntrance = Vector3.Distance(park.parkEntrances.First().transform.position,
                                                              new Vector3(x, GROUND_HEIGHT, z));

                    if (distanceToEntrance < roadWidth)
                    {
                        continue;
                    }

                    // If this location should be raised, change the hight of the patch and the ones around.
                    if (y != 0)
                    {
                        for (var cornerIndex = 0; cornerIndex < 4; cornerIndex++)
                        {
                            var ox = cornerIndex == 1 || cornerIndex == 2 ? 1 : 0;
                            var oz = cornerIndex == 2 || cornerIndex == 3 ? 1 : 0;

                            var patch = park.getTerrain(x - ox, z - oz);

                            if (patch != null)
                            {
                                var current = patch.h[cornerIndex] - DEF_HEIGHT;
                                patch.smoothChangeHeight(park, cornerIndex, y - current);
                            }
                        }
                    }
                }
            }

            // Randomly flood the map.
            for (var i = 0; i < keyStore.FloodRounds; i++)
            {
                var x = Mathf.RoundToInt(_waterRandom.NextFloat(keyStore.EntranceClearance, park.xSize));
                var z = Mathf.RoundToInt(_waterRandom.NextFloat(0, park.zSize));

                var patch = park.getTerrain(x, z);
                if (patch == null || patch.hasWater() || patch.getLowestHeight() >= GROUND_HEIGHT)
                {
                    continue;
                }

                WaterFlooding.flood(new Vector3(x, GROUND_HEIGHT - WATTER_OFFSET, z));
            }

            // Randomly spawn a forrest.
            for (var i = 0; i < keyStore.TreeCount; i++)
            {
                var x = Mathf.RoundToInt(_treeRandom.NextFloat(keyStore.EntranceClearance, park.xSize - PARK_FENCE_OFFSET));
                var z = Mathf.RoundToInt(_treeRandom.NextFloat(PARK_FENCE_OFFSET, park.zSize - PARK_FENCE_OFFSET));

                var patch = park.getTerrain(x, z);
                if (patch == null || patch.hasWater())
                {
                    continue;
                }

                var y = patch.getHighestHeight();
                if (y != patch.getLowestHeight())
                {
                    continue;
                }

                TreeEntity fir = null;
                foreach (var o in ScriptableSingleton <AssetManager> .Instance.getDecoObjects())
                {
                    if (o.getName().StartsWith("Fir") && o is TreeEntity)
                    {
                        fir = o as TreeEntity;
                    }
                }

                if (fir != null)
                {
                    var tree = ConfigWindow.Instantiate(fir);
                    tree.transform.position = new Vector3(x, y, z);
                    tree.transform.forward  = Vector3.forward;
                    tree.Initialize();
                    tree.startAnimateSpawn(Vector3.zero);
                }
            }
        }
コード例 #26
0
ファイル: BSPDungeonBuilder.cs プロジェクト: kabirules/Kenny
        NodeConnection[] ConnectPartitions(BSPNodeObject leftPartition, BSPNodeObject rightPartition, bool horizontalSplit)
        {
            var connections = new List <NodeConnection>();

            if (leftPartition.discarded || rightPartition.discarded)
            {
                return(connections.ToArray());
            }

            var leftRooms  = new List <BSPNodeObject>();
            var rightRooms = new List <BSPNodeObject>();

            if (horizontalSplit)
            {
                FindBoundaryEdgeRooms(leftPartition, BSPNodeDirection.Right, leftRooms);
                FindBoundaryEdgeRooms(rightPartition, BSPNodeDirection.Left, rightRooms);
            }
            else               // Vertical split
            {
                // Left = bottom partition
                // Right = top partition
                FindBoundaryEdgeRooms(leftPartition, BSPNodeDirection.Top, leftRooms);
                FindBoundaryEdgeRooms(rightPartition, BSPNodeDirection.Bottom, rightRooms);
            }

            // Connect the two rooms together
            if (leftRooms.Count == 0 || rightRooms.Count == 0)
            {
                return(connections.ToArray());
            }

            Shuffle(leftRooms);
            Shuffle(rightRooms);

            bool roomsConnected = false;

            foreach (var leftRoom in leftRooms)
            {
                // First check if any of the right rooms are connected
                foreach (var rightRoom in rightRooms)
                {
                    if (leftRoom.connectedRooms.Contains(rightRoom))
                    {
                        roomsConnected = true;
                        break;
                    }
                }

                foreach (var rightRoom in rightRooms)
                {
                    if (leftRoom.connectedRooms.Contains(rightRoom))
                    {
                        // Already connected
                        continue;
                    }

                    bool shouldConnectRooms = true;
                    if (roomsConnected)
                    {
                        // rooms are already connected along this edge.  Check if can loop
                        shouldConnectRooms = random.NextFloat() < bspConfig.loopingProbability;
                    }

                    if (shouldConnectRooms)
                    {
                        // Connect left and right together
                        var intersection    = Rectangle.Intersect(leftRoom.bounds, rightRoom.bounds);
                        var minIntersection = bspConfig.roomPadding * 2;
                        if (intersection.Size.x > minIntersection || intersection.Size.z > minIntersection)
                        {
                            // These two rooms can connect
                            leftRoom.connectedRooms.Add(rightRoom);
                            rightRoom.connectedRooms.Add(leftRoom);
                            roomsConnected = true;

                            var connection = new NodeConnection(leftRoom, rightRoom, bspConfig.roomPadding);
                            connections.Add(connection);
                        }
                    }
                }
            }

            return(connections.ToArray());
        }