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);
        }
Beispiel #2
0
        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;
                }
            }
        }
Beispiel #3
0
        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;
 }
Beispiel #6
0
        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;
            }
        }
Beispiel #7
0
        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);
            }
        }