Beispiel #1
0
    private static void SetOriginOpenListForCanonicalDijkstra(FastPriorityQueue <PathNode> openList,
                                                              MapColliderInfo map, int2 origin, int2 dir)
    {
        int2 next = origin + dir;

        if (MapColliderUtils.UnReachable(map, next.x, next.y))
        {
            return;
        }

        float cost = 1f;

        if (dir.x != 0 && dir.y != 0)
        {
            if (MapColliderUtils.UnReachable(map, origin + new int2(dir.x, 0)) &&
                MapColliderUtils.UnReachable(map, origin + new int2(0, dir.y)))
            {
                return;
            }

            cost = 1.5f;
        }

        map.IntegrationField[next.x, next.y] = cost;
        openList.Enqueue(new PathNode(next, dir), cost);
    }
Beispiel #2
0
 private static void CanonicalOrdering(FastPriorityQueue <PathNode> openList, MapColliderInfo map, int2 node, int2 dir, float cost)
 {
     if (dir.x == 0 || dir.y == 0)
     {
         MoveCardinal(openList, map, node, dir, cost);
     }
     else
     {
         MoveDiagonal(openList, map, node, dir, cost);
     }
 }
    private void CreateBarrier(MapColliderInfo colliderMap, MapTerrainInfo terrainMap, int x, int y)
    {
        if (MapColliderUtils.UnReachable(colliderMap, x, y))
        {
            return;
        }

        for (int y2 = -1 + y; y2 < (1 + y); y2++)
        {
            for (int x2 = -1 + x; x2 < (1 + x); x2++)
            {
                MapColliderUtils.AddCost(colliderMap, x2, y2, 3);
            }
        }
        MapColliderUtils.SetCostValue(colliderMap, x, y, 255);


        // Instantiate a barrier on (x, y)
        var barrierRenderer = EntityPrefabContainer.BarrierRenderer;
        var drawPos         = barrierRenderer.GetComponent <Position2DComponent> ().Value.Offset;

        drawPos += new float2(x, y);
        var heading = barrierRenderer.GetComponent <Heading2DComponent> ().Value.Value;

        PostUpdateCommands.CreateEntity(EntityPrefabContainer.BarrierArchetype);
        PostUpdateCommands.SetComponent(new Position2D()
        {
            Value  = new float2(x, y),
            Offset = drawPos - new float2(x, y)
        });
        PostUpdateCommands.SetComponent(new Heading2D()
        {
            Value = heading
        });
        PostUpdateCommands.SetComponent(new TransformMatrix
        {
            Value = MathUtils.GetTransformMatrix(drawPos, heading)
        });
        PostUpdateCommands.SetComponent(
            barrierRenderer.GetComponent <BarrierComponent> ().Value
            );
        PostUpdateCommands.SetSharedComponent(
            barrierRenderer.GetComponent <TerrainRendererComponent> ().Value
            );

        var barrierColPos = new Vector3(x, 0, y);
        var barrierCol    = Object.Instantiate(EntityPrefabContainer.BarrierColliderPrefab,
                                               barrierColPos, Quaternion.identity);

        terrainMap.Terrains[x, y] |= TerrainType.Barrier;
        MapTerrainUtils.AddCollider(terrainMap, barrierCol);
    }
Beispiel #4
0
    public static bool IsWall(MapColliderInfo map, int x, int y)
    {
        if (x >= map.MapWidth || x < 0)
        {
            return(false);
        }
        if (y >= map.MapHeight || y < 0)
        {
            return(false);
        }

        return(map.CostField[x, y] == 0xff);
    }
Beispiel #5
0
    public static void SetCostValue(MapColliderInfo map, int x, int y, byte value)
    {
        if (x >= map.MapWidth || x < 0)
        {
            return;
        }
        if (y >= map.MapHeight || y < 0)
        {
            return;
        }

        map.CostField[x, y] = value;
    }
Beispiel #6
0
    public static bool UnReachable(MapColliderInfo map, int x, int y)
    {
        if (x >= map.MapWidth || x < 0)
        {
            return(true);
        }
        if (y >= map.MapHeight || y < 0)
        {
            return(true);
        }

        return(map.CostField[x, y] == 0xff);
    }
Beispiel #7
0
    public static void SubtracCost(MapColliderInfo map, int x, int y, byte value)
    {
        if (x >= map.MapWidth || x < 0)
        {
            return;
        }
        if (y >= map.MapHeight || y < 0)
        {
            return;
        }

        map.CostField[x, y] = (byte)math.clamp(map.CostField[x, y] - value, 0, 0xff);
    }
Beispiel #8
0
    /// <summary>
    /// If node is a jump point, return the new direction. Otherwise return int2(0,0)
    /// </summary>
    private static int2 IsJumpPoint(MapColliderInfo map, int2 child, int2 dir)
    {
        int2 parent     = child - dir;
        int2 falseReval = new int2(0, 0);

        if (dir.x == 0 && dir.y != 0)
        {
            if (parent.x > 0)
            {
                if (MapColliderUtils.IsWall(map, parent.x - 1, parent.y) &&
                    !MapColliderUtils.IsWall(map, child.x - 1, child.y))
                {
                    return(new int2(-1, dir.y));
                }
            }
            if (parent.x < (map.MapWidth - 1))
            {
                if (MapColliderUtils.IsWall(map, parent.x + 1, parent.y) &&
                    !MapColliderUtils.IsWall(map, child.x + 1, child.y))
                {
                    return(new int2(1, dir.y));
                }
            }
        }
        else if (dir.x != 0 && dir.y == 0)
        {
            if (parent.y > 0)
            {
                if (MapColliderUtils.IsWall(map, parent.x, parent.y - 1) &&
                    !MapColliderUtils.IsWall(map, child.x, child.y - 1))
                {
                    return(new int2(dir.x, -1));
                }
            }

            if (parent.y < (map.MapHeight - 1))
            {
                if (MapColliderUtils.IsWall(map, parent.x, parent.y + 1) &&
                    !MapColliderUtils.IsWall(map, child.x, child.y + 1))
                {
                    return(new int2(dir.x, 1));
                }
            }
        }

        return(falseReval);
    }
Beispiel #9
0
    public void AddMapColliderList(string name, List <MapColliderItem> itemList)
    {
        foreach (var item in _mapColliderInfoList)
        {
            if (item._name == name)
            {
                Debug.LogError("MapDesc Has Same Map Collider Info");
                return;
            }
        }

        MapColliderInfo info = new MapColliderInfo();

        info._name     = name;
        info._itemList = itemList;
        _mapColliderInfoList.Add(info);
    }
Beispiel #10
0
    /// <summary>
    /// Use the uniform cost field to generate the integration field.
    /// It is more efficient than <see cref = "GenerateDijkstraIntegratField" />
    /// </summary>
    public static void GenerateCanonicalDijkstraIntegratField(MapColliderInfo map, int2 target)
    {
        if (MapColliderUtils.UnReachable(map, target.x, target.y))
        {
            return;
        }

        float maxValue = float.MaxValue;

        int mapWidth  = map.MapWidth;
        int mapHeight = map.MapHeight;

        float[, ] inteField         = map.IntegrationField;
        IntegrateFlag[, ] inteInfos = map.IntegrateInfos;

        for (int y = 0; y < mapHeight; y++)
        {
            for (int x = 0; x < mapWidth; x++)
            {
                inteField[x, y]  = maxValue;
                inteInfos[x, y] &= ~IntegrateFlag.Visited; // Init all field visited flag to false
            }
        }

        FastPriorityQueue <PathNode> openList = new FastPriorityQueue <PathNode> (mapWidth * mapHeight / 10);

        // Origin
        inteField[target.x, target.y]  = 0;
        inteInfos[target.x, target.y] |= IntegrateFlag.Visited;
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(1, 0));
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(1, 1));
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(0, 1));
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(-1, 1));
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(-1, 0));
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(-1, -1));
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(0, -1));
        SetOriginOpenListForCanonicalDijkstra(openList, map, target, new int2(1, -1));

        while (openList.Count > 0)
        {
            var bestNode = openList.Dequeue();

            CanonicalOrdering(openList, map, bestNode.Node, bestNode.Dir,
                              inteField[bestNode.Node.x, bestNode.Node.y]);
        }
    }
Beispiel #11
0
    private static void MoveDiagonal(FastPriorityQueue <PathNode> openList, MapColliderInfo map, int2 start, int2 dir, float cost)
    {
        if (dir.x == 0 || dir.y == 0)
        {
            return;
        }

        while (!MapColliderUtils.UnReachable(map, start.x, start.y))
        {
            IntegrateFlag integrateFlag = map.IntegrateInfos[start.x, start.y];

            if (integrateFlag.HasFlag(IntegrateFlag.Visited))
            {
                if (map.IntegrationField[start.x, start.y] > cost)
                {
                    map.IntegrationField[start.x, start.y] = cost;
                }
                else
                {
                    return;
                }
            }
            else
            {
                map.IntegrateInfos[start.x, start.y]  |= IntegrateFlag.Visited;
                map.IntegrationField[start.x, start.y] = cost;
            }

            MoveCardinal(openList, map, start, new int2(dir.x, 0), cost);
            MoveCardinal(openList, map, start, new int2(0, dir.y), cost);

            if (!MapColliderUtils.UnReachable(map, start + new int2(dir.x, 0)) ||
                !MapColliderUtils.UnReachable(map, start + new int2(0, dir.y)))
            {
                start += dir;
                cost  += 1.5f;
            }
            else
            {
                return;
            }
        }
    }
Beispiel #12
0
    private static void MoveCardinal(FastPriorityQueue <PathNode> openList, MapColliderInfo map, int2 start, int2 dir, float cost)
    {
        start += dir;
        cost  += 1;

        while (!MapColliderUtils.UnReachable(map, start.x, start.y))
        {
            IntegrateFlag integrateFlag = map.IntegrateInfos[start.x, start.y];

            if (integrateFlag.HasFlag(IntegrateFlag.Visited))
            {
                if (map.IntegrationField[start.x, start.y] > cost)
                {
                    map.IntegrationField[start.x, start.y] = cost;
                }
                else
                {
                    return;
                }
            }

            int2 newdir = IsJumpPoint(map, start, dir);
            if (newdir.x != 0 || newdir.y != 0)
            {
                if (integrateFlag.HasFlag(IntegrateFlag.Visited))
                {
                    map.IntegrateInfos[start.x, start.y] &= ~IntegrateFlag.Visited;
                }
                map.IntegrationField[start.x, start.y] = math.min(map.IntegrationField[start.x, start.y], cost);
                openList.Enqueue(new PathNode(start, newdir), cost);
                return;
            }
            else
            {
                map.IntegrateInfos[start.x, start.y]  |= IntegrateFlag.Visited;
                map.IntegrationField[start.x, start.y] = cost;
                start += dir;
                cost  += 1;
            }
        }
    }
Beispiel #13
0
    public static void GenerateFlowField(MapColliderInfo map, int2 target)
    {
        float[] neighboers = new float[8];
        bool[]  blocks     = new bool[8];

        float[, ] inteField        = map.IntegrationField;
        FlowFieldDir[, ] flowField = map.FlowField;

        float maxValue = float.MaxValue;

        for (int y = 0; y < (map.MapHeight); y++)
        {
            for (int x = 0; x < (map.MapWidth); x++)
            {
                if (MapColliderUtils.UnReachable(map, x, y))
                {
                    flowField[x, y] = FlowFieldDir.None;
                    continue;
                }

                blocks[0] = MapColliderUtils.UnReachable(map, x - 1, y + 1);
                blocks[1] = MapColliderUtils.UnReachable(map, x, y + 1);
                blocks[2] = MapColliderUtils.UnReachable(map, x + 1, y + 1);
                blocks[3] = MapColliderUtils.UnReachable(map, x - 1, y);
                blocks[4] = MapColliderUtils.UnReachable(map, x + 1, y);
                blocks[5] = MapColliderUtils.UnReachable(map, x - 1, y - 1);
                blocks[6] = MapColliderUtils.UnReachable(map, x, y - 1);
                blocks[7] = MapColliderUtils.UnReachable(map, x + 1, y - 1);


                neighboers[0] = (blocks[0] || (blocks[3] && blocks[1])) ? maxValue : inteField[x - 1, y + 1];
                neighboers[1] = (blocks[1]) ? maxValue : inteField[x, y + 1];
                neighboers[2] = (blocks[2] || (blocks[1] && blocks[4])) ? maxValue : inteField[x + 1, y + 1];
                neighboers[3] = (blocks[3]) ? maxValue : inteField[x - 1, y];
                neighboers[4] = (blocks[4]) ? maxValue : inteField[x + 1, y];
                neighboers[5] = (blocks[5] || (blocks[3] && blocks[6])) ? maxValue : inteField[x - 1, y - 1];
                neighboers[6] = (blocks[6]) ? maxValue : inteField[x, y - 1];
                neighboers[7] = (blocks[7] || (blocks[4] && blocks[6])) ? maxValue : inteField[x + 1, y - 1];

                int minIdx = 0;

                for (int i = 1; i < 8; i++)
                {
                    if (neighboers[i] < neighboers[minIdx])
                    {
                        minIdx = i;
                    }
                }

                switch (minIdx)
                {
                case 0:
                    flowField[x, y] = FlowFieldDir.Deg135;
                    break;

                case 1:
                    flowField[x, y] = FlowFieldDir.Deg90;
                    break;

                case 2:
                    flowField[x, y] = FlowFieldDir.Deg45;
                    break;

                case 3:
                    flowField[x, y] = FlowFieldDir.Deg180;
                    break;

                case 4:
                    flowField[x, y] = FlowFieldDir.Deg0;
                    break;

                case 5:
                    flowField[x, y] = FlowFieldDir.Deg225;
                    break;

                case 6:
                    flowField[x, y] = FlowFieldDir.Deg270;
                    break;

                case 7:
                    flowField[x, y] = FlowFieldDir.Deg315;
                    break;
                }
            }
        }

        flowField[target.x, target.y] = FlowFieldDir.None;
    }
Beispiel #14
0
    public static void GenerateDijkstraIntegratField(MapColliderInfo map, int2 target)
    {
        float maxValue = float.MaxValue;

        int mapWidth  = map.MapWidth;
        int mapHeigth = map.MapHeight;

        byte[, ] costField  = map.CostField;
        float[, ] inteField = map.IntegrationField;

        for (int y = 0; y < mapHeigth; y++)
        {
            for (int x = 0; x < mapWidth; x++)
            {
                inteField[x, y] = maxValue;
            }
        }
        inteField[target.x, target.y] = 0;

        Queue <int2> openList = new Queue <int2> (mapWidth * mapHeigth / 10);

        openList.Enqueue(target);

        int2[] neighborIds = new int2[4];

        while (openList.Count > 0)
        {
            int2 cur = openList.Dequeue();

            float endCost        = 0;
            int   neighborLength = 0;

            if (cur.y > 0)
            {
                neighborIds[neighborLength++] = new int2(cur.x, cur.y - 1);
            }
            if (cur.y < (mapHeigth - 1))
            {
                neighborIds[neighborLength++] = new int2(cur.x, cur.y + 1);
            }
            if (cur.x > 0)
            {
                neighborIds[neighborLength++] = new int2(cur.x - 1, cur.y);
            }
            if (cur.x < (mapWidth - 1))
            {
                neighborIds[neighborLength++] = new int2(cur.x + 1, cur.y);
            }

            int2 neighborId;
            for (int i = 0; i < neighborLength; i++)
            {
                neighborId = neighborIds[i];
                if (MapColliderUtils.UnReachable(map, neighborId.x, neighborId.y))
                {
                    continue;
                }

                endCost = inteField[cur.x, cur.y] + costField[neighborId.x, neighborId.y] + 1;
                if (endCost < inteField[neighborId.x, neighborId.y])
                {
                    if (!openList.Contains(neighborId))
                    {
                        openList.Enqueue(neighborId);
                    }
                    inteField[neighborId.x, neighborId.y] = endCost;
                }
            }
        }
    }
Beispiel #15
0
 public static bool UnReachable(MapColliderInfo map, int2 coordinate)
 {
     return(UnReachable(map, coordinate.x, coordinate.y));
 }