Пример #1
0
    public static TSVector2 Gradient(this SDFMap map, List <SDFShape> sharpes, List <DynamicCircle> circles, TSVector2 pos)
    {
        FP delat = FP.ONE;
        FP x     = map.Sample(new TSVector2(pos.x + delat, pos.y), sharpes, circles) - map.Sample(new TSVector2(pos.x - delat, pos.y), sharpes, circles);
        FP y     = map.Sample(new TSVector2(pos.x, pos.y + delat), sharpes, circles) - map.Sample(new TSVector2(pos.x, pos.y - delat), sharpes, circles);

        return(new TSVector2(FP.Half * x, FP.Half * y));
    }
Пример #2
0
    public static TSVector2 Move(this SDFMap map, List <DynamicCircle> circles, FP radius, TSVector2 start, TSVector2 dir, FP len, int layerMask = -1)
    {
        start = map.SDF.WorldToLocal(start);
        TSVector2 end        = start + dir * len;
        RectInt   rect       = map.SDF.ToRect(start, end);
        int       externSize = (int)TSMath.Ceiling(radius / map.SDF.Grain);

        rect.max += new Vector2Int(externSize, externSize);
        moveFilterCache.Clear();
        map.FilterToList(moveFilterCache, rect, layerMask);

        FP        maxStepLen = radius * FP.Half;
        int       moveStep   = (int)TSMath.Ceiling(len / maxStepLen);
        TSVector2 result     = start;

        for (int i = 1; i <= moveStep; ++i)
        {
            FP moveLen = maxStepLen;
            if (i == moveStep)
            {
                moveLen = len - (moveStep - 1) * maxStepLen;
            }

            TSVector2 newPos = result + dir * moveLen;
            FP        sd     = map.Sample(newPos, moveFilterCache, circles);
            if (sd < radius)
            {
                TSVector2 gradient  = map.Gradient(moveFilterCache, circles, newPos);
                TSVector2 asjustDir = dir - gradient * TSVector2.Dot(gradient, dir);
                newPos = result + asjustDir.normalized * moveLen;
                //多次迭代
                for (int j = 0; j < 3; ++j)
                {
                    sd = map.Sample(newPos, moveFilterCache, circles);
                    if (sd >= radius)
                    {
                        break;
                    }
                    newPos += map.Gradient(moveFilterCache, circles, newPos) * (radius - sd);
                }
                //避免往返
                if (TSVector2.Dot(newPos - start, dir) < FP.Zero)
                {
                    return(result + map.SDF.Origin);
                }
                else
                {
                    result = newPos;
                }
                break;
            }
            else
            {
                result = newPos;
            }
        }
        return(result + map.SDF.Origin);
    }
Пример #3
0
    public static FP Sample(this SDFMap map, TSVector2 pos, List <SDFShape> sharpes, List <DynamicCircle> circles)
    {
        FP val = map.SDF.Sample(pos);

        //如果已经在不可行走区域就没必要再计算碰撞体的了
        if (val < 0)
        {
            return(val);
        }
        return(GetSDFFromShapes(sharpes, circles, pos, val));
    }
Пример #4
0
    public void Init(SDFMap map)
    {
        this.map = map;
        Nodes.Clear();
        for (int i = 0; i < map.SDF.Width; ++i)
        {
            for (int j = 0; j < map.SDF.Heigh; ++j)
            {
                if (map.SDF[i, j] >= 0)
                {
                    PathNode node = new PathNode
                    {
                        pos = new Vector2Int(i, j)
                    };
                    int key = i << 16 | j;
                    Nodes.Add(key, node);
                }
            }
        }
        foreach (var kv in Nodes)
        {
            var        node = kv.Value;
            Vector2Int pos  = node.pos;
            int        key  = pos.x << 16 | (pos.y + 1);
            Nodes.TryGetValue(key, out node.neighbor.top);

            key = pos.x << 16 | (pos.y - 1);
            Nodes.TryGetValue(key, out node.neighbor.bottom);

            key = (pos.x - 1) << 16 | pos.y;
            Nodes.TryGetValue(key, out node.neighbor.left);

            key = (pos.x + 1) << 16 | pos.y;
            Nodes.TryGetValue(key, out node.neighbor.right);

            key = (pos.x - 1) << 16 | (pos.y + 1);
            Nodes.TryGetValue(key, out node.neighbor.topLeft);

            key = (pos.x + 1) << 16 | (pos.y + 1);
            Nodes.TryGetValue(key, out node.neighbor.topRight);

            key = (pos.x - 1) << 16 | (pos.y - 1);
            Nodes.TryGetValue(key, out node.neighbor.bottomLeft);

            key = (pos.x + 1) << 16 | (pos.y - 1);
            Nodes.TryGetValue(key, out node.neighbor.bottomRight);
        }
    }
Пример #5
0
    public static TSVector2 DiskCast(this SDFMap map, TSVector2 origin, TSVector2 dir, FP radius, FP maxDistance, List <SDFShape> sharpes, List <DynamicCircle> circles)
    {
        FP t = FP.Zero;

        while (true)
        {
            TSVector2 p  = origin + dir * t;
            FP        sd = map.Sample(p, sharpes, circles);
            if (sd <= radius)
            {
                return(p);
            }
            t += (sd - radius);
            if (t >= maxDistance)
            {
                return(origin + dir * maxDistance);
            }
        }
    }
Пример #6
0
    //直线移动,用于AI的移动
    public static TSVector2 StraightMove(this SDFMap map, List <DynamicCircle> circles, FP radius, TSVector2 start, TSVector2 dir, FP len, int layerMask = -1)
    {
        start = map.SDF.WorldToLocal(start);
        TSVector2 end        = start + dir * len;
        RectInt   rect       = map.SDF.ToRect(start, end);
        int       externSize = (int)TSMath.Ceiling(radius / map.SDF.Grain);

        rect.max += new Vector2Int(externSize, externSize);
        moveFilterCache.Clear();
        map.FilterToList(moveFilterCache, rect, layerMask);

        FP        maxStepLen = radius * FP.Half;
        int       moveStep   = (int)TSMath.Ceiling(len / maxStepLen);
        TSVector2 result     = start;

        for (int i = 1; i <= moveStep; ++i)
        {
            FP moveLen = maxStepLen;
            if (i == moveStep)
            {
                moveLen = len - (moveStep - 1) * maxStepLen;
            }
            TSVector2 newPos = result + dir * moveLen;
            FP        sd     = map.Sample(newPos, moveFilterCache, circles);
            if (sd < radius)
            {
                newPos = result + dir * sd;
                sd     = map.Sample(newPos, moveFilterCache, circles);
                if (sd >= radius)
                {
                    result = newPos;
                }
                break;
            }
            result = newPos;
        }
        return(result + map.SDF.Origin);
    }