public int GetDistanceSquaredToArea(XPoint2 pnt, RMArea area, int minDist) { Debug.Assert(area.Built, "GetDistanceSquaredToArea() does not work for unbuilt areas"); XRectangle range = area.ActiveArea; range.RestrictToWithin(new XRectangle(pnt.X, pnt.Y, 1, 1)); range.Inflate(minDist); int minDist2 = int.MaxValue; for (int x = range.Left; x < range.Right; ++x) { for (int y = range.Top; y < range.Bottom; ++y) { int dx = x - pnt.X, dy = y - pnt.Y; int dist2 = dx * dx + dy * dy; if (dist2 > minDist * minDist) { continue; } if (Map[x, y] == area) { if (dist2 < minDist2) { minDist2 = dist2; } } } } return(minDist2); }
public void AddArea(XPoint2 pos, int size, float coherence) { EnsureMaps(1); var map = Maps[0]; int fringe = (int)Math.Round( (size * (1 - coherence)) ); XRectangle range = new XRectangle(pos.X, pos.Y, 0, 0). Inflate(size + fringe). RestrictToWithin( new XRectangle(0, 0, sizeX, sizeY) ); range = new XRectangle(0, 0, sizeX, sizeY); List <TerrainType> types = new List <TerrainType>(); float noiseRnd = pos.X + pos.Y * 10; for (int x = range.Left; x < range.Right; ++x) { for (int y = range.Top; y < range.Bottom; ++y) { int dist2 = (x - pos.X) * (x - pos.X) + (y - pos.Y) * (y - pos.Y); float noise = SimplexNoise.simplex_noise_2octaves( (float)x / (size + 2), noiseRnd, (float)y / (size + 2) ) / 2 - 0.5f; map[x, y] = (1 - (float)Math.Sqrt(dist2) / size) + (noise - 0.5f) * (1 - coherence) * 2; } } }
public int GetDistanceSquaredToArea(XPoint2 pnt, RMArea area, int minDist) { Debug.Assert(area.Built, "GetDistanceSquaredToArea() does not work for unbuilt areas"); int sizeX = Map.GetLength(0), sizeY = Map.GetLength(1); XRectangle range = area.ActiveArea; range.RestrictToWithin(new XRectangle(pnt.X, pnt.Y, 1, 1)); range.Inflate(minDist); range.RestrictToWithin(new XRectangle(0, 0, sizeX, sizeY)); int minDist2 = int.MaxValue; for (int x = range.Left; x < range.Right; ++x) { for (int y = range.Top; y < range.Bottom; ++y) { int dx = x - pnt.X, dy = y - pnt.Y; int dist2 = dx * dx + dy * dy; if (dist2 > minDist * minDist) { continue; } var tile = Map[x, y]; if (tile != null) { while (tile != area && tile.Parent != null) { tile = tile.Parent; } } if (tile == area) { if (dist2 < minDist2) { minDist2 = dist2; } } } } return(minDist2); }
public void AddArea(XPoint2 pos, int size, float coherence, Func <XPoint2, bool> validityCheck) { List <XPoint2> stack = new List <XPoint2>(); stack.Add(pos); int at = 0; int loopAt = stack.Count; Map[pos.X, pos.Y] = new Node() { Weight = 100000 }; List <XPoint2> tmp = new List <XPoint2>(); activeArea = new XRectangle(pos.X, pos.Y, 1, 1); while (size > 0) { float maxV = float.MinValue; for (int i = 0; i < stack.Count; ++i) { var p = stack[i]; var node = Map[p.X, p.Y]; Debug.Assert(node.Weight > 0, "Weight < 0 means the tile is already accepted!"); float weight = node.Weight + (1 + node.Extra); if (weight > maxV) { maxV = weight; at = i; } } var pnt = stack[at]; { --size; stack.RemoveAt(at--); --loopAt; float val = Map[pnt.X, pnt.Y].Weight; Debug.Assert(val > 0, "Tile must have a positive weight to start with!"); Map[pnt.X, pnt.Y].Weight = -1; activeArea = activeArea.ExpandToInclude(pnt); const float NoiseScale = 30; /*if (coherence < 1) { * float noise = (SimplexNoise.simplex_noise_3octaves(pnt.X / NoiseScale, 0, pnt.Y / NoiseScale) / 2 - 0.5f); * val *= 1 + (noise - 0.5f) * (1 - coherence) / 0.5f; * }*/ tmp.Clear(); for (int p = 0; p < propogOffs.Length; ++p) { XPoint2 pnt2 = pnt + propogOffs[p]; if (pnt2.X >= 0 && pnt2.Y >= 0 && pnt2.X < Map.GetLength(0) && pnt2.Y < Map.GetLength(1)) { if (!validityCheck(pnt2)) { continue; } if (Map[pnt2.X, pnt2.Y].Weight < 0) { continue; } tmp.Add(pnt2); } } for (int t = 0; t < tmp.Count; ++t) { var pnt2 = tmp[t]; XPoint2 delta = pnt2 - pnt; float noise = (SimplexNoise.simplex_noise_3octaves(pnt2.X / NoiseScale, (delta.X + delta.Y * 2) * 5, pnt2.Y / NoiseScale) / 2 - 0.5f); float tVal = val - (float)Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y); //tVal *= 1 + (noise - 0.5f) * (1 - coherence) / 0.3f; Map[pnt2.X, pnt2.Y].Weight = Math.Max(Map[pnt2.X, pnt2.Y].Weight, tVal); Map[pnt2.X, pnt2.Y].Extra = Math.Max( Map[pnt2.X, pnt2.Y].Extra, (noise - 0.0f) * (1 - coherence) / 0.5f * 50 ); if (!stack.Contains(pnt2)) { stack.Add(pnt2); } } /*} else { * stack.RemoveAt(at--); * --loopAt;*/ } if (stack.Count == 0) { break; } /*at += 1; * while (at >= loopAt) { * at -= loopAt; * loopAt = stack.Count; * }*/ } }
public void SetTileArea(XPoint2 pnt, RMArea area) { Map[pnt.X, pnt.Y] = area; }
public void AddArea(XPoint2 pos, int size, XReal coherence, Func <XPoint2, bool> validityCheck) { int origSize = size; List <XPoint2> stack = new List <XPoint2>(); stack.Add(pos); int at = 0; for (int x = 0; x < Map.GetLength(0); ++x) { for (int y = 0; y < Map.GetLength(1); ++y) { Map[x, y].Weight = int.MaxValue; Map[x, y].Extra = 0; } } Debug.Assert(pos.X >= 0 && pos.Y >= 0 && pos.X < Map.GetLength(0) && pos.Y < Map.GetLength(1), "Out of bounds"); Map[pos.X, pos.Y] = new Node() { Weight = 70 }; activeArea = new XRectangle(pos.X, pos.Y, 1, 1); while (size > 0 && stack.Count > 0) { float minV = float.MaxValue; for (int i = 0; i < stack.Count; ++i) { var p = stack[i]; var node = Map[p.X, p.Y]; float weight = Math.Abs(node.Weight) + node.Extra; if (weight < minV) { minV = weight; at = i; } } var pnt = stack[at]; --size; stack.RemoveAt(at--); int val = Map[pnt.X, pnt.Y].Weight; activeArea = activeArea.ExpandToInclude(pnt); const float NoiseScale = 30; for (int p = 0; p < propogOffs.Length; ++p) { XPoint2 pnt2 = pnt + propogOffs[p]; if (pnt2.X >= 0 && pnt2.Y >= 0 && pnt2.X < Map.GetLength(0) && pnt2.Y < Map.GetLength(1)) { if (!validityCheck(pnt2)) { continue; } if (Map[pnt2.X, pnt2.Y].Weight <= val + propogCost[p]) { continue; } int extraW = 0; for (int p2 = 0; p2 < propogOffs.Length; ++p2) { XPoint2 delta = propogOffs[p2]; float noise = (SimplexNoise.simplex_noise_3octaves(pnt2.X / NoiseScale, (delta.X + delta.Y * 2) * 5, pnt2.Y / NoiseScale) / 2 - 0.5f); extraW = Math.Max( extraW, (int)(20 * 70 * (noise - 0.0f) * (1 - coherence) / 0.5f) );//origSize / 46 } if (!stack.Contains(pnt2)) { if (Map[pnt2.X, pnt2.Y].IsPositive) { size++; } stack.Add(pnt2); } Map[pnt2.X, pnt2.Y].Weight = val + propogCost[p] * Math.Sign(val); if (extraW > Map[pnt2.X, pnt2.Y].Extra) { Map[pnt2.X, pnt2.Y].Extra = extraW; } } } } for (int s = 0; s < stack.Count; ++s) { var pnt = stack[s]; Map[pnt.X, pnt.Y].Weight = int.MinValue; } }
void CalculateDistances(int minDistance, int maxDistance) { var map = Map; XRectangle range = activeArea; XRectangle mapRect = new XRectangle(0, 0, Map.GetLength(0), Map.GetLength(1)); range.Inflate(maxDistance); range.RestrictToWithin(mapRect); List <XPoint2> stack = new List <XPoint2>(); for (int y = range.Top; y < range.Bottom; ++y) { for (int x = range.Left; x < range.Right; ++x) { int minDist = int.MaxValue; for (int o = 0; o < propogOffs.Length; ++o) { XPoint2 off = propogOffs[o]; if (!mapRect.Contains(new XPoint2(x + off.X, y + off.Y))) { continue; } if (map[x + off.X, y + off.Y].IsPositive != map[x, y].IsPositive) { int newCost = propogCost[o]; minDist = Math.Min(minDist, newCost); } } if (minDist < int.MaxValue) { stack.Add(new XPoint2(x, y)); map[x, y].Weight = (map[x, y].IsPositive ? 70 : 70 - minDist); } else { map[x, y].Weight = (map[x, y].IsPositive ? maxDistance * 70 : minDistance * 70); } } } while (stack.Count > 0) { int count = stack.Count; for (int s = 0; s < count; ++s) { var pnt = stack[s]; var node = map[pnt.X, pnt.Y]; for (int o = 0; o < propogOffs.Length; ++o) { var newP = pnt + propogOffs[o]; if (!mapRect.Contains(newP)) { continue; } var tnode = map[newP.X, newP.Y]; if (node.IsPositive != tnode.IsPositive) { continue; } int newCost = node.Weight + (node.IsPositive ? propogCost[o] : -propogCost[o]); if (Math.Abs(newCost) < Math.Abs(tnode.Weight)) { map[newP.X, newP.Y].Weight = newCost; stack.Add(newP); } } } stack.RemoveRange(0, count); } }