Exemple #1
0
        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;
         }
     }
 }
Exemple #4
0
 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));
             }
         }
     }
 }