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)); }
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)); }
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)); }
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); } } }
/** * \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); }
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); }
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); } } } } }
/// <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 }; }
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); }
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); }
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; } } }
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); } } } }
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; } }
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(); }
private float getRandomPs() { return(r.NextFloat(rMin, rMax)); }
/// <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(); }
public static float NextFloat(this Random random, float min, float max) { return(min + (max - min) * random.NextFloat()); }
/// <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(); }
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); } } }
// 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); }
public static float NextFloatRange(this System.Random random, float min, float max) { float f = random.NextFloat(); return(MathW.Remap(f, 0, 1, min, max)); }
/// <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(); }
public static int NextIntRanged(this System.Random rand, int min, int max) { return(min + UnityEngine.Mathf.FloorToInt(rand.NextFloat() * (max - min))); }
/// <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); }
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); } } }
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()); }