Exemplo n.º 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);
    }
Exemplo n.º 2
0
    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);
    }
Exemplo n.º 3
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);
    }
Exemplo n.º 4
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]);
        }
    }
Exemplo n.º 5
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;
            }
        }
    }
Exemplo n.º 6
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;
            }
        }
    }
Exemplo n.º 7
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;
    }
Exemplo n.º 8
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;
                }
            }
        }
    }
Exemplo n.º 9
0
    protected override void OnUpdate()
    {
        if (_camera == null)
        {
            _camera = Camera.main;
        }

        Ray     ray = _camera.ScreenPointToRay(Input.mousePosition);
        float   t   = -ray.origin.y / ray.direction.y;
        Vector3 pos = ray.GetPoint(t);

        int x = (int)pos.x;
        int y = (int)pos.z;

        var colliderMap    = MapColliderInfo.GameMap;
        var terrainMap     = MapTerrainInfo.GameMap;
        var pathController = GameObject.FindObjectOfType(typeof(SimplePathGenerator)) as SimplePathGenerator;

        if (!_InitBoundary)
        {
            colliderMap = MapColliderInfo.GameMap;
            terrainMap  = MapTerrainInfo.GameMap;

            for (int i = 0; i < GameSetting.MAP_WIDTH; i++)
            {
                CreateBarrier(colliderMap, terrainMap, i, 0);
            }
            for (int i = 0; i < GameSetting.MAP_WIDTH; i++)
            {
                CreateBarrier(colliderMap, terrainMap, i, GameSetting.MAP_HEIGHT - 1);
            }
            for (int i = 0; i < GameSetting.MAP_HEIGHT; i++)
            {
                CreateBarrier(colliderMap, terrainMap, 0, i);
            }
            for (int i = 0; i < GameSetting.MAP_HEIGHT; i++)
            {
                CreateBarrier(colliderMap, terrainMap, GameSetting.MAP_WIDTH - 1, i);
            }

            _InitBoundary = true;
        }

        // Add block
        if (Input.GetMouseButton(0))
        {
            CreateBarrier(colliderMap, terrainMap, x, y);
            pathController.Generate();
            return;
        }

        // Remove block
        if (Input.GetMouseButton(1))
        {
            if (terrainMap.Terrains[x, y].HasFlag(TerrainType.Barrier))
            {
                for (int y2 = -1 + y; y2 < (1 + y); y2++)
                {
                    for (int x2 = -1 + x; x2 < (1 + x); x2++)
                    {
                        MapColliderUtils.SubtracCost(colliderMap, x2, y2, 3);
                    }
                }
                MapColliderUtils.SetCostValue(colliderMap, x, y, 0);

                for (int i = 0; i < _barries.Length; i++)
                {
                    int2 floorPos = new int2(_barries.Positions[i].Value);

                    if (floorPos.x == x && floorPos.y == y)
                    {
                        PostUpdateCommands.DestroyEntity(_barries.Entities[i]);
                    }
                }
                MapTerrainUtils.RemoveColliders(terrainMap, new float2(pos.x, pos.z), true);
            }

            pathController.Generate();

            return;
        }

        if (Input.GetMouseButtonDown(2))
        {
            pathController.Target = new int2(x, y);
            pathController.Generate();
            return;
        }

        // Make unit nav
        if (Input.GetKeyDown(KeyCode.N))
        {
            for (int i = 0; i < _navUnits.Length; i++)
            {
                var oldMov = _navUnits.MoveData[i];
                if (oldMov.IsMoving)
                {
                    oldMov.StopMoving();
                }
                else
                {
                    oldMov.StartMoving();
                }
                oldMov.Target = pathController.Target;
                EntityManager.SetComponentData(_navUnits.Entities[i], oldMov);
            }
        }
    }