public XRectangle RestrictToWithin(XRectangle other) { int l = Left; int r = Right; int t = Top; int b = Bottom; if (l < other.Left) { l = other.Left; } if (r > other.Right) { r = other.Right; } if (t < other.Top) { t = other.Top; } if (b > other.Bottom) { b = other.Bottom; } X = l; Y = t; Width = r - l + 1; Height = b - t + 1; return(this); }
public void BlurArea(int amount) { if (amount == 0) return; var map = Maps[0]; float[,] newMap = new float[sizeX, sizeY]; XRectangle range = new XRectangle(0, 0, sizeX, sizeY); for (int x = range.Left; x < range.Right; ++x) { for (int y = range.Top; y < range.Bottom; ++y) { float ave = 0, cnt = 0; for (int dx = -amount; dx <= amount; ++dx) { for (int dy = -amount; dy <= amount; ++dy) { if (dx * dx + dy * dy > amount * amount) continue; float weight = 1 - (float)Math.Sqrt( (float)(dx * dx + dy * dy) / (amount * amount) ); int px = x + dx, py = y + dy; if (px >= 0 && py >= 0 && px < sizeX && py < sizeY) { ave += map[px, py] * weight; cnt += weight; } } } newMap[x, y] = ave / cnt; } } Maps[0] = newMap; }
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 XRectangle RestrictToWithin(XRectangle other) { int l = Left; int r = Right; int t = Top; int b = Bottom; if (l < other.Left) l = other.Left; if (r > other.Right) r = other.Right; if (t < other.Top) t = other.Top; if (b > other.Bottom) b = other.Bottom; X = l; Y = t; Width = r - l + 1; Height = b - t + 1; return this; }
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); } }
public void BlurArea(int amount) { if (amount == 0) return; var map = Map; int sizeX = Map.GetLength(0), sizeY = Map.GetLength(1); Node[,] newMap = new Node[sizeX, sizeY]; XRectangle range = activeArea. Inflate(1). RestrictToWithin(new XRectangle(0, 0, sizeX, sizeY)); for (int y = range.Top; y < range.Bottom; ++y) { for (int x = range.Left; x < range.Right; ++x) { int ave = 0, cnt = 0; for (int dy = -amount; dy <= amount; ++dy) { for (int dx = -amount; dx <= amount; ++dx) { if (dx * dx + dy * dy > amount * amount) continue; int weight = 100 - (100 * (int)(dx * dx + dy * dy) / (amount * amount)); int px = x + dx, py = y + dy; if (px >= 0 && py >= 0 && px < sizeX && py < sizeY) { ave += (map[px, py].IsPositive ? 70 : 0) * weight; cnt += weight; } } } newMap[x, y].Weight = ave / cnt; if (newMap[x, y].IsPositive) { Debug.Assert(activeArea.Contains(new XPoint2(x, y)), "A blurred area should never be larger than the previous area (in terms of bounding box)"); } } } activeArea = range; Map = newMap; }
public void WithAreaTiles(Action<XPoint2, int> onTile) { var map = Maps[0]; XRectangle range = new XRectangle(0, 0, sizeX, sizeY); for (int x = range.Left; x < range.Right; ++x) { for (int y = range.Top; y < range.Bottom; ++y) { float weight = map[x, y]; //if (weight > 0) { onTile(new XPoint2(x, y), (int)(weight * 20)); } } } }