public void RandomShuffle <T>(List <T> elements) { int n = elements.Count(); for (int i = n - 1; i > 0; --i) { Mathnv.Swap(elements, i, Rand(i + 1)); } }
public static IEnumerator <Vector2Int> GetEnumerator2D <T>(this ArrayGrid <T> grid) { IEnumerator <Vector2Int> iterator = Mathnv.GetAreaEnumerator(grid.w, grid.h); while (iterator.MoveNext()) { yield return(iterator.Current); } }
public static Rect SetMinMax(this Rect input, Vector2 min, Vector2 max) { Vector2 rMin = Mathnv.Min(min, max); Vector2 rMax = Mathnv.Max(min, max); Rect r = new Rect((rMax - rMin) * .5f + rMin, rMax - rMin); return(r); }
public IEnumerator RenderChunks() { var visibleIter = Mathnv.GetAreaEnumerator(MapSize); while (visibleIter.MoveNext()) { Vector2Int current = visibleIter.Current; this[current].GenerateMesh(true); } yield break; }
// random normalized vector //from [ [min.x,min.y] , [max.x,max.y] ] public Vector3 RandVec3Normalized(float min, float max) { if (min > max) { Mathnv.Swap(ref min, ref max); } Vector3 vec = new Vector3(Rand(min, max), Rand(min, max), Rand(min, max)).normalized; vec.Normalize(); return(vec); }
// rolling min or max will be rare, but rolling exactly between the two will be common public double GaussianRandom(double min, double max) { if (min == max) { return(min); } if (min > max) { Mathnv.Swap <double>(ref min, ref max); } min /= 3; max /= 3; return(Rand(min, max) + Rand(min, max) + Rand(min, max));; }
public int Rand(int a, int b) { if (a == b) { return(a); } if (a > b) { Mathnv.Swap(ref a, ref b); } int c = b - a; return(a + Randi() % c); }
public double Rand(double a, double b) { if (a == b) { return(a); } if (a > b) { Mathnv.Swap(ref a, ref b); } double c = b - a; return(a + Randd() * c); }
public float Rand(float a, float b) { if (a == b) { return(a); } if (a > b) { Mathnv.Swap(ref a, ref b); } float c = b - a; return(a + Randf() * c); }
public void CreateChunks() { //Vector2Int center = Vector2Int.FloorToInt(new Vector2(MapSize.x, MapSize.y) * .5f); chunks = new List <MapMesh>(); chunkViews = new List <GameObject>(); var visibleIter = Mathnv.GetAreaEnumerator(MapSize); while (visibleIter.MoveNext()) { Vector2Int current = visibleIter.Current; CreateChunk(current); } }
//random point in an area public Vector2 Rand(Vector2 a, Vector2 b) { if (a.x > b.x) { Mathnv.Swap(ref a.x, ref b.x); } if (a.y > b.y) { Mathnv.Swap(ref a.y, ref b.y); } float cx = b.x - a.x; float cy = b.y - a.y; return(new Vector2(a.x + Randf() * cx, a.y + Randf() * cy)); }
public uint Rand(uint a, uint b) { if (a == b) { return(a); } if (a == 0) { return(Rand(b)); } if (a > b) { Mathnv.Swap(ref a, ref b); } uint n = 2 * b; uint m = a + b; uint c = n % m; return(a + Rand() % c); }
public static void Clamp(this Rect area, Rect min_max) { Mathnv.Clamp(ref area, min_max); }
public static void Clamp(this Rect area, Vector2 pos, Vector2 size) { Mathnv.Clamp(ref area, pos, size); }
void SmoothVertex(int vertex, float skip_height = 0f, bool skip_seams = true) { Vector3 vertexToSmooth = vertices[vertex]; //don't smooth vertices near this value, useful for retaining 'nice' seams if (Mathnv.FastApproximately(vertexToSmooth.y, skip_height, .01f)) { return; } bool xSeam = false; bool zSeam = false; if (vertexToSmooth.x > (maxVertex.x - 1f)) { xSeam = true; } if (vertexToSmooth.z > (maxVertex.y - 1f)) { zSeam = true; } if (vertexToSmooth.x < (minVertex.x + 1f)) { xSeam = true; } if (vertexToSmooth.z < (minVertex.y + 1f)) { zSeam = true; } if (skip_seams && (zSeam || xSeam)) { return; } List <int> neighbors = vertex_neighbors[vertex]; Vector3 summation = Vector3.zero; for (int i = 0; i < neighbors.Count; ++i) { if (xSeam) { summation.z += vertices[neighbors[i]].z; } if (zSeam) { summation.x += vertices[neighbors[i]].x; } if (!xSeam && !zSeam) { summation += vertices[neighbors[i]]; } } summation = summation * (1f / (neighbors.Count)); if (xSeam || zSeam) { Vector3 temp = vertexToSmooth; if (xSeam) { temp.z = summation.z; } if (zSeam) { temp.x = summation.x; } vertices[vertex] = temp; } else { vertices[vertex] = summation; } if (Wall != null && vertHasWall.ContainsKey(vertex)) { int wallVertex = vertHasWall[vertex]; Wall.SetWallVertex(wallVertex, new Vector2(vertices[vertex].x, vertices[vertex].z)); } }
IEnumerator GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap) { Vector2Int p1 = Vector2Int.zero; Vector2Int p2 = Vector2Int.zero; Vector2Int r = Vector2Int.zero; List <Rect> rooms = new List <Rect>(); List <int> roomTypes = new List <int>(); int numberOfRooms = 0; for (numberOfRooms = 0; numberOfRooms < maxNumberOfRooms;) { if (numberOfRooms == 0) { p1.x = map.w / 2 - GameRNG.Rand((int)roomSizeLimit.Max); p1.y = map.h / 2 - GameRNG.Rand((int)roomSizeLimit.Max) - (int)roomSizeLimit.Min; r.x = GameRNG.Rand((int)roomSizeLimit.Min, (int)roomSizeLimit.Min + (int)roomSizeLimit.Max); r.y = roomSizeLimit.RandomValuei(); p2.x = p1.x + r.x; p2.y = map.h / 2; if (p2.x >= map.w) { continue; } } else { p1.x = GameRNG.Rand(map.w - (int)roomSizeLimit.Min) + 1; p1.y = GameRNG.Rand(map.h - (int)roomSizeLimit.Min) / 2 + 1; r.x = roomSizeLimit.RandomValuei(); r.y = roomSizeLimit.RandomValuei(); p2.x = p1.x + r.x; p2.y = p1.y + r.y; if (p2.x >= map.w - 1 || p2.y >= map.h / 2 + 3) { continue; } } bool randAgain = false; for (int j = 0; j < rooms.Count; ++j) { randAgain = true; if (rooms[j].Contains(p1)) { if (!rooms[j].Contains(p2)) { randAgain = false; roomTypes[j]++; } break; } if (rooms[j].Contains(p2)) { if (!rooms[j].Contains(p1)) { randAgain = false; roomTypes[j]++; } break; } } if (randAgain) { continue; } // Create room Rect roomRect = Rect.MinMaxRect(p1.x, p1.y, p2.x, p2.y); rooms.Add(roomRect); roomTypes.Add(0); numberOfRooms++; } yield return(new WaitForEndOfFrame()); // create mirror for (int i = 0; i < numberOfRooms; ++i) { Rect roomRect = rooms[i]; if (mirrorVertical) { Vector2Int min = Vector2Int.FloorToInt(roomRect.min); Vector2Int max = Vector2Int.FloorToInt(roomRect.max); min.x = map.w - min.x - 1; max.x = map.w - max.x - 1; p1.x = min.x; min.x = max.x; max.x = p1.x; roomRect = Rect.MinMaxRect(min.x, min.y, max.x, max.y); } else { Vector2Int min = Vector2Int.FloorToInt(roomRect.min); Vector2Int max = Vector2Int.FloorToInt(roomRect.max); min.y = map.h - min.y - 1; max.y = map.h - max.y - 1; p1.y = min.y; min.y = max.y; max.y = p1.y; roomRect = Rect.MinMaxRect(min.x, min.y, max.x, max.y); } roomTypes.Insert(i, roomTypes[i]); rooms.Insert(i, roomRect); } yield return(new WaitForEndOfFrame()); for (int i = 0; i < rooms.Count; ++i) { IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(Vector2Int.FloorToInt(rooms[i].min), Vector2Int.FloorToInt(rooms[i].max)); while (areaIter.MoveNext()) { Vector2Int current = areaIter.Current; if (valueMap[current] == valueWall) { valueMap[current] = roomTypes[i]; } } } yield return(new WaitForEndOfFrame()); int freeCells = 0; for (int x = 0; x < map.MaxValidPosition.x; ++x) { for (int y = 0; y < map.h / 2; ++y) { int currentValue = valueMap[x, y]; int[] nearValues = new int[] { valueMap[x + 1, y] , valueMap[x, y + 1] , valueMap[x + 1, y + 1] }; if (currentValue != nearValues[0] && nearValues[0] != valueWall) { valueMap[x, y] = valueWall; } if (currentValue != nearValues[1] && nearValues[1] != valueWall) { valueMap[x, y] = valueWall; } if (currentValue != nearValues[2] && nearValues[2] != valueWall) { valueMap[x, y] = valueWall; } if (currentValue != valueWall) { freeCells += 2;// +2 for mirror } valueMap[x, map.h - y - 1] = valueMap[x, y];//mirroring } } if (freeCells < (map.h * map.w * requiredPercentageOfMapNotWalls)) { if (debugOutput) { Dev.Log(string.Format("Not enough open map space. {0} < {1}", freeCells, (map.h * map.w * requiredPercentageOfMapNotWalls))); } success = false; yield break; } ConvertValuesToTiles(map, valueMap); ConnectClosestRooms(map, valueMap, true); ConvertValuesToTiles(map, valueMap); AddDoors(map, valueMap, 1f); success = true; yield break; }
bool GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap) { map[map.CenterPosition] = defaultCorridorElement; Vector2Int s0 = Vector2Int.zero; Vector2 s1 = Vector2Int.zero; Vector2Int p = Vector2Int.zero; Vector2 d = Vector2Int.zero; int iterCount = map.Count / 3; for (int i = 0; i < iterCount; i++) { s1 = GameRNG.RandomPointOnCircle(map.Size.DivideBy(2)) + map.CenterPosition; d.x = strideLimitX.RandomNormalizedValue(); d.y = strideLimitY.RandomNormalizedValue(); d.x -= .5f; d.y -= .5f; int counter = 0; for (; ;) { //try again if (counter > maxTunnelIterations) { --i; break; } s1 += d; p = Vector2Int.FloorToInt(s1); p = map.Wrap(p); if (map.IsValidPosition(p) && map.GetAdjacentPositionsOfType(p, false, defaultCorridorElement).Count > 0) { map[p] = defaultCorridorElement; break; } } } if (placeRooms) { var areaIter = Mathnv.GetAreaEnumerator(Vector2Int.one, map.MaxValidPosition - Vector2Int.one); while (areaIter.MoveNext()) { Vector2Int current = areaIter.Current; Range limitX = new Range(map.w / 2 - strideLimitX.Min, map.w / 2 + strideLimitX.Min); Range limitY = new Range(map.h / 2 - strideLimitY.Min, map.h / 2 + strideLimitY.Min); if ((limitX.Contains(current.x) && limitY.Contains(current.y)) || map[current] == defaultWallElement) { continue; } int n = map.GetAdjacentPositionsOfType(current, false, defaultCorridorElement).Count; if (n == 1) { Rect room = new Rect(Vector2.zero, new Vector2(roomSizeX.RandomValuei(), roomSizeY.RandomValuei())); var roomIter = Mathnv.GetAreaEnumerator(Vector2Int.FloorToInt(room.min), Vector2Int.FloorToInt(room.max)); while (roomIter.MoveNext()) { Vector2Int rCurrent = roomIter.Current; map[current + rCurrent] = defaultRoomElement; } } } } return(true); }
bool GenerateMap(ArrayGrid <MapElement> map, ArrayGrid <int> valueMap) { Vector2Int s0 = Vector2Int.zero; Vector2Int s1 = Vector2Int.zero; Vector2Int p0 = Vector2Int.zero; Vector2Int p1 = Vector2Int.zero; Vector2Int p2 = Vector2Int.zero; Vector2Int diff = Vector2Int.zero; List <Rect> rooms = new List <Rect>(); List <int> roomTypes = new List <int>(); // Place rooms for (int i = 0; i < maxNumberOfRooms; ++i) { // size of room s1 = new Vector2Int(roomSizeLimitX.RandomValuei(), roomSizeLimitY.RandomValuei()); bool result = map.GetPositionOfRandomAreaOfType(defaultWallElement, s1 + roomSizeOffset, ref p0); if (result) { p0 = p0.AddScalar(2); // Connect the room to existing one if (rooms.Count > 0) { int selectedRoom = GameRNG.Rand(rooms.Count); Rect r = rooms[selectedRoom]; // center of this room p1 = p0 + s1.DivideBy(2); // center of second room p2 = Vector2Int.FloorToInt(r.center); // found the way to connect rooms diff = p2 - p1; diff.x = Mathf.Abs(diff.x); diff.y = Mathf.Abs(diff.y); s0 = p1; while (!(diff.x == 0 && diff.y == 0)) { if (GameRNG.Rand(diff.x + diff.y) < diff.x)// move horizontally { diff.x--; s0.x += (s0.x > p2.x ? -1 : 1); } else { diff.y--; s0.y += (s0.y > p2.y ? -1 : 1); } // Check what is on that position if (map[s0] == defaultRoomElement) { break; } else if (map[s0] == defaultCorridorElement) { if (GameRNG.CoinToss()) { break; } } map[s0] = defaultCorridorElement; } } // add to list of rooms Rect roomRect = Rect.MinMaxRect(p0.x, p0.y, p0.x + s1.x, p0.y + s1.y); rooms.Add(roomRect); roomTypes.Add(i); // draw_room int roomType = GameRNG.Rand(4); //select the type of room we should generate if (s1.x == s1.y) { roomType = 3; } if (roomType != 2) { IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(s1); while (areaIter.MoveNext()) { Vector2Int current = areaIter.Current; if (roomType == 0 || roomType == 1)// rectangle room { map[p0 + current] = defaultRoomElement; } else// round room { if (Vector2Int.Distance(s1.DivideBy(2), current) < s1.x / 2) { map[p0 + current] = defaultRoomElement; } } } } else //diamond { IEnumerator <Vector2Int> areaIter = Mathnv.GetAreaEnumerator(s1.DivideBy(2) + Vector2Int.one); while (areaIter.MoveNext()) { Vector2Int current = areaIter.Current; if (current.y >= current.x) { int x0 = p0.x + current.x + s1.DivideBy(2).x; int x1 = p0.x + s1.DivideBy(2).x - current.x; int y0 = p0.y + current.y; int y1 = p0.y + s1.y - current.y; map[x0, y0] = defaultRoomElement; map[x0, y1] = defaultRoomElement; map[x1, y0] = defaultRoomElement; map[x1, y1] = defaultRoomElement; } } } } // end of room addition } return(true); }