예제 #1
0
    /**
     * Apply Template To Map
     * Method responsible for modifying the nodes to reflect the template.
     */
    public void ApplyTemplateToMap(MapTemplate mapTemplate)
    {
        Debug.Log("ApplyTemplateToMap");
        // Initialize perlin noise generator to make terrain
        m_envPerlinNoise = new PerlinNoise2D(GetMapRowCount(), GetMapColCount());


        m_nodeList = new SortedDictionary <int, SortedDictionary <int, NodeV2> >();

        Vector3 envPos;
        int     col = 0;
        int     row = 0;


        int N           = -m_tileSize / 2;
        int S           = m_tileSize / 2;
        int E           = m_tileSize / 2;
        int W           = -m_tileSize / 2;
        int westWallCol = GetMapColCount() - 1;

        int northWallRow = GetMapRowCount() - 1;
        //isPlayablePerimeter

        Vector3 westWallOffset  = new Vector3(0, 0, -m_tileSize / 2);
        Vector3 eastWallOffset  = new Vector3(0, 0, m_tileSize / 2);
        Vector3 southWallOffset = new Vector3(m_tileSize / 2, 0, 0);
        Vector3 northWallOffset = new Vector3(-m_tileSize / 2, 0, 0);

        int northRow = 0;
        int eastCol  = GetMapRowCount() - 1;
        int westCol  = 0;
        int southRow = GetMapColCount() - 1;

        Vector2Int cornerNE = new Vector2Int(northRow, eastCol);
        Vector2Int cornerSE = new Vector2Int(southRow, eastCol);
        Vector2Int cornerSW = new Vector2Int(southRow, westCol);
        Vector2Int cornerNW = new Vector2Int(northRow, westCol);

        //==================================================

        //              UPDATE CAMERA LIMITATION

        //==================================================
        // Super sketch but effective
        if (m_sketchCameraBounds)
        {
            float axisVal;
            float posOffsetVal;

            axisVal      = (m_tileSize * GetMapColCount() - 1) / 2F;
            posOffsetVal = transform.position.x;
            Vector2 rangeX = new Vector2(posOffsetVal, posOffsetVal) + new Vector2(-axisVal, axisVal - m_tileSize);

            axisVal      = (m_tileSize * GetMapRowCount() - 1) / 2F;
            posOffsetVal = transform.position.z;
            Vector2 rangeZ = new Vector2(posOffsetVal, posOffsetVal) + new Vector2(-axisVal, axisVal - m_tileSize);


            axisVal      = 100;
            posOffsetVal = transform.position.y + 5;
            Vector2 rangeY = new Vector2(posOffsetVal, posOffsetVal + axisVal);


            UpdateCameraLimitations(rangeX, rangeY, rangeZ);
        }

        //==================================================

        //                GENERATE BASE TILES

        //==================================================
        // Generate Tiles
        float mapWidth  = m_tileSize * GetMapColCount();
        float mapHeight = m_tileSize * GetMapRowCount();

        NodeTemplate nodeTemplate;

        for (row = 0; row < GetMapRowCount(); ++row)
        {
            m_nodeList.Add(row, new SortedDictionary <int, NodeV2>());

            for (col = 0; col < GetMapColCount(); ++col)
            {
                //----------------------------------------------

                // Create Tile at position

                float tileRowPosX = m_tileSize * col - mapWidth / 2;
                float tileRowPosZ = m_tileSize * row - mapHeight / 2;

                Vector3 tilePos = transform.position + new Vector3(tileRowPosX, 0, tileRowPosZ);


                // Decide which prefab
                nodeTemplate = mapTemplate.GetNode(row, col);
                GameObject prefab = nodeTemplate.type == "path" ||
                                    nodeTemplate.type == "start" ||
                                    nodeTemplate.type == "end"
                                    ? m_pathTile : m_grassTile;


                GameObject spawnNode     = Instantiate(prefab, tilePos, Quaternion.identity, this.gameObject.transform);
                NodeV2     spawnInstance = spawnNode.GetComponent <NodeV2>();
                m_nodeList[row].Add(col, spawnInstance);



                //----------------------------------------------

                // Add vegitation to terrain

                if (nodeTemplate.type == "terrain" && nodeTemplate.isEnvPlacable)
                {
                    OddsTable subCategoryTable;

                    // Choose which table to role on
                    if (nodeTemplate.isPlayablePerimeter)
                    {
                        subCategoryTable = m_shrubOddsTable;
                    }
                    else
                    {
                        string rolledKey;
                        if (Random.Range(0F, 10f) / 10F > 0.2F)
                        {
                            rolledKey = m_environmentOddsTable.GetForNormalizedRoll(m_envPerlinNoise.GetValue(row, col));
                        }
                        else
                        {
                            rolledKey = m_environmentOddsTable.Roll();
                        }

                        subCategoryTable = (OddsTable)m_environmentOddsTable.GetPayload(rolledKey);
                    }


                    // Table exists
                    if (subCategoryTable != null)
                    {
                        // Decide prefab at Random
                        string rolledKey;

                        if (Random.Range(0, 1) > 0.5)
                        {
                            rolledKey = subCategoryTable.GetForNormalizedRoll(Mathf.Clamp(Random.Range(-0.2F, 0.2F) + m_envPerlinNoise.GetValue(row, col), 0, 1));
                        }
                        else
                        {
                            rolledKey = subCategoryTable.Roll();
                        }
                        GameObject envPrefab = (GameObject)subCategoryTable.GetPayload(rolledKey);
                        if (envPrefab != null)
                        {
                            SpawnNodeEnv(spawnInstance, envPrefab);
                        }
                    }
                }
                //________________________________________________
            }
        }



        //==================================================

        //                APPLY TILE DATA

        //==================================================
        // Read directly from the map
        NodeTemplate template;

        for (row = 0; row < GetMapRowCount(); ++row)
        {
            for (col = 0; col < GetMapColCount(); ++col)
            {
                if (GetNode(row, col))
                {
                    NodeV2 node = GetNode(row, col);
                    template = mapTemplate.GetNode(row, col);
                    node.SetNodeType(template.type);
                    node.SetIsPlayablePerimeter(template.isPlayablePerimeter);
                    node.SetIsTowerPlacable(template.isTowerPlacable);
                    node.SetIsEnvPlacable(template.isEnvPlacable);
                    node.SetCoordinate(new Vector2Int(col, row));
                }
            }
        }



        //==================================================

        //                DECORATE PATHS

        //==================================================

        m_pathSegments = mapTemplate.GetPathSegments();
        int        globalPathTileCount  = 0;
        int        segmentLargestIndex  = m_pathSegments.Count - 1;
        int        previousSegmentIndex = -1;
        Vector2Int currentPos           = new Vector2Int(0, 0);
        Vector2Int previousPos          = new Vector2Int(0, 0);

        for (int s = 0; s <= segmentLargestIndex; ++s)
        {
            bool isLastSegment = s == segmentLargestIndex;

            PathSegment segment = m_pathSegments[s];

            int deltaX = segment.end.x - segment.start.x;
            int deltaY = segment.end.y - segment.start.y;

            int directionX = deltaX == 0 ? 0 : deltaX / Mathf.Abs(deltaX);
            int directionY = deltaY == 0 ? 0 : deltaY / Mathf.Abs(deltaY);



            //isLastTile, isFirstTile

            // Set up 2D iteration
            int  dy = 0;
            int  dx = 0;
            bool isLastIteration = false;
            bool isDone          = false;
            while (!isDone)
            {
                // Set loop ending flag
                if (isLastIteration)
                {
                    isDone = true;
                }
                //----------------------
                // Execute for-loop contents with dx and dy

                // Get tile location
                row = segment.start.y + dy;
                col = segment.start.x + dx;

                // Select colour
                bool isFirstTile       = globalPathTileCount == 0;
                bool isLastTile        = isLastSegment && isLastIteration;
                bool isDirectionChange = s != previousSegmentIndex;


                currentPos = new Vector2Int(col, row);
                if (isFirstTile)
                {
                    previousPos = currentPos;
                }


                //====================================================================
                // If the segment is not overlapping form the last segment
                if (previousPos != currentPos || isFirstTile)
                {
                    NodeV2 currentTile = GetNode(row, col);

                    Transform parentTransform = currentTile.gameObject.transform;
                    envPos = currentTile.gameObject.transform.position + currentTile.GetEnvOffset();


                    Vector3    wallPos;
                    Quaternion wallRotation;
                    nodeTemplate = mapTemplate.GetNode(row, col);



                    // -------------------------------------------------------------------

                    //                          ADD PATH WALLS

                    // -------------------------------------------------------------------
                    if (currentTile.GetNodeType() != "end" && m_pathWall != null)
                    {
                        if (nodeTemplate.hasWall[(int)NodeTemplate.Wall.N])
                        {
                            wallPos      = envPos + new Vector3(N, 0, 0);
                            wallRotation = Quaternion.AngleAxis(90, Vector3.up);
                            Instantiate(m_pathWall, wallPos, wallRotation, parentTransform);
                        }
                        if (nodeTemplate.hasWall[(int)NodeTemplate.Wall.S])
                        {
                            wallPos      = envPos + new Vector3(S, 0, 0);
                            wallRotation = Quaternion.AngleAxis(-90, Vector3.up);
                            Instantiate(m_pathWall, wallPos, wallRotation, parentTransform);
                        }
                        if (nodeTemplate.hasWall[(int)NodeTemplate.Wall.E])
                        {
                            wallPos      = envPos + new Vector3(0, 0, E);
                            wallRotation = Quaternion.AngleAxis(180, Vector3.up);
                            Instantiate(m_pathWall, wallPos, wallRotation, parentTransform);
                        }
                        if (nodeTemplate.hasWall[(int)NodeTemplate.Wall.W])
                        {
                            wallPos      = envPos + new Vector3(0, 0, W);
                            wallRotation = Quaternion.AngleAxis(0, Vector3.up);
                            Instantiate(m_pathWall, wallPos, wallRotation, parentTransform);
                        }
                    }



                    // -------------------------------------------------------------------

                    //                          ADD PATH PILLARS

                    // -------------------------------------------------------------------
                    Quaternion pillarRotation = Quaternion.identity;
                    if (m_pathPiller != null)
                    {
                        if (nodeTemplate.hasPillar[(int)NodeTemplate.Pillar.NE])
                        {
                            Vector3 pillarPos = envPos + new Vector3(N, 0, E);
                            Instantiate(m_pathPiller, pillarPos, pillarRotation, parentTransform);
                        }
                        if (nodeTemplate.hasPillar[(int)NodeTemplate.Pillar.NW])
                        {
                            Vector3 pillarPos = envPos + new Vector3(N, 0, W);
                            Instantiate(m_pathPiller, pillarPos, pillarRotation, parentTransform);
                        }
                        if (nodeTemplate.hasPillar[(int)NodeTemplate.Pillar.SE])
                        {
                            Vector3 pillarPos = envPos + new Vector3(S, 0, E);
                            Instantiate(m_pathPiller, pillarPos, pillarRotation, parentTransform);
                        }
                        if (nodeTemplate.hasPillar[(int)NodeTemplate.Pillar.SW])
                        {
                            Vector3 pillarPos = envPos + new Vector3(S, 0, W);
                            Instantiate(m_pathPiller, pillarPos, pillarRotation, parentTransform);
                        }
                    }


                    if (currentTile.GetIsPath() && currentTile.GetPlayablePerimeter() && currentTile.GetNodeType() != "end")
                    {
                        Quaternion pillarRot = Quaternion.identity;
                        if (m_leftEntrancePillar != null)
                        {
                            Instantiate(m_leftEntrancePillar, envPos + westWallOffset + northWallOffset, pillarRot, this.gameObject.transform);
                        }
                        if (m_rightEntrancePillar != null)
                        {
                            Instantiate(m_rightEntrancePillar, envPos + westWallOffset + southWallOffset, pillarRot, this.gameObject.transform);
                        }
                    }

                    /*
                     * if (currentTile.GetNodeType() == "end")
                     * {
                     *  Quaternion pillarRot = Quaternion.AngleAxis(180, Vector3.up);
                     *  Instantiate(m_pathPiller, envPos + eastWallOffset + southWallOffset, pillarRot, this.gameObject.transform);
                     *  Instantiate(m_pathPiller, envPos + eastWallOffset + northWallOffset, pillarRot, this.gameObject.transform);
                     * }
                     */


                    if (currentTile.GetNodeType() == "end" && m_finalScene != null)
                    {
                        currentTile.m_height = 11F;
                        Vector3    endPos = currentTile.gameObject.transform.position;
                        Quaternion endRot = Quaternion.AngleAxis(0, Vector3.up);
                        Instantiate(m_finalScene, endPos, endRot, this.gameObject.transform);
                    }



                    if (currentTile.GetNodeType() == "start" && m_startScene != null)
                    {
                        Vector3    startPos = currentTile.gameObject.transform.position + new Vector3(0, 0, -m_tileSize);//HERE
                        Quaternion startRot = Quaternion.AngleAxis(0, Vector3.up);
                        Instantiate(m_startScene, startPos, startRot, this.gameObject.transform);
                    }



                    // -------------------------------------------------------------------

                    //                          ADD Tiles

                    // -------------------------------------------------------------------

                    Quaternion tileRotation = Quaternion.identity;
                    Vector3    tilePos;
                    GameObject tilePrefrab = null;
                    float      tileOffset  = 0;

                    tilePos     = envPos + new Vector3(N / 2, tileOffset, E / 2);
                    tilePrefrab = (GameObject)m_tileOddsTable.GetPayload(m_tileOddsTable.Roll());
                    if (tilePrefrab != null)
                    {
                        Instantiate(tilePrefrab, tilePos, tileRotation, parentTransform);
                    }

                    tilePos     = envPos + new Vector3(S / 2, tileOffset, E / 2);
                    tilePrefrab = (GameObject)m_tileOddsTable.GetPayload(m_tileOddsTable.Roll());
                    if (tilePrefrab != null)
                    {
                        Instantiate(tilePrefrab, tilePos, tileRotation, parentTransform);
                    }

                    tilePos     = envPos + new Vector3(S / 2, tileOffset, W / 2);
                    tilePrefrab = (GameObject)m_tileOddsTable.GetPayload(m_tileOddsTable.Roll());
                    if (tilePrefrab != null)
                    {
                        Instantiate(tilePrefrab, tilePos, tileRotation, parentTransform);
                    }

                    tilePos     = envPos + new Vector3(N / 2, tileOffset, W / 2);
                    tilePrefrab = (GameObject)m_tileOddsTable.GetPayload(m_tileOddsTable.Roll());
                    if (tilePrefrab != null)
                    {
                        Instantiate(tilePrefrab, tilePos, tileRotation, parentTransform);
                    }



                    // -------------------------------------------------------------------

                    //                          ADD LAMPS

                    // -------------------------------------------------------------------
                    if (currentTile.GetNodeType() != "end" && m_pathLamp != null)
                    {
                        float      lampOffset   = 3;
                        Quaternion lampRotation = Quaternion.identity;
                        if (nodeTemplate.hasLamp[(int)NodeTemplate.Pillar.NE])
                        {
                            Vector3 pillarPos = envPos + new Vector3(N, lampOffset, E);
                            lampRotation = Quaternion.AngleAxis(-90, Vector3.up);
                            Instantiate(m_pathLamp, pillarPos, lampRotation, parentTransform);
                        }
                        if (nodeTemplate.hasLamp[(int)NodeTemplate.Pillar.SE])
                        {
                            Vector3 pillarPos = envPos + new Vector3(S, lampOffset, E);
                            lampRotation = Quaternion.AngleAxis(0, Vector3.up);
                            Instantiate(m_pathLamp, pillarPos, lampRotation, parentTransform);
                        }
                        if (nodeTemplate.hasLamp[(int)NodeTemplate.Pillar.SW])
                        {
                            Vector3 pillarPos = envPos + new Vector3(S, lampOffset, W);
                            lampRotation = Quaternion.AngleAxis(90, Vector3.up);
                            Instantiate(m_pathLamp, pillarPos, lampRotation, parentTransform);
                        }
                        if (nodeTemplate.hasLamp[(int)NodeTemplate.Pillar.NW])
                        {
                            Vector3 pillarPos = envPos + new Vector3(N, lampOffset, W);
                            lampRotation = Quaternion.AngleAxis(180, Vector3.up);
                            Instantiate(m_pathLamp, pillarPos, lampRotation, parentTransform);
                        }
                    }
                } // End segment does not overlatp
                  //====================================================================



                // Increment tile could to tell first tile
                ++globalPathTileCount;
                //----------------------
                // Increment loop
                if (dx != deltaX)
                {
                    dx += directionX;
                }
                else if (dy != deltaY)
                {
                    dy += directionY;
                }
                // Detect going on last iteration
                isLastIteration = (dx == deltaX && dy == deltaY);

                previousPos          = currentPos;
                previousSegmentIndex = s;
            }
        }



        //==================================================

        //                ADD OUTTER WALLS

        //==================================================
        if (m_outterWall != null)
        {
            // NORTH WALL
            for (int i = 0; i < GetMapRowCount(); ++i)
            {
                Vector2Int coord    = new Vector2Int(northRow, i);
                NodeV2     nodeInst = GetNode(coord);
                Vector3    nodePos  = nodeInst.gameObject.transform.position;


                if (!nodeInst.GetIsPath())
                {
                    Quaternion outterWallRot = Quaternion.AngleAxis(90, Vector3.up);
                    Instantiate(m_outterWall, nodePos + nodeInst.GetEnvOffset() + northWallOffset, outterWallRot, this.gameObject.transform);
                }
            }
            // SOUTH WALL
            for (int i = 0; i < GetMapRowCount(); ++i)
            {
                Vector2Int coord    = new Vector2Int(southRow, i);
                NodeV2     nodeInst = GetNode(coord);
                Vector3    nodePos  = nodeInst.gameObject.transform.position;
                if (!nodeInst.GetIsPath())
                {
                    Quaternion outterWallRot = Quaternion.AngleAxis(-90, Vector3.up);
                    Instantiate(m_outterWall, nodePos + nodeInst.GetEnvOffset() + southWallOffset, outterWallRot, this.gameObject.transform);
                }
            }



            // EAST WALL
            for (int i = 0; i < GetMapColCount(); ++i)
            {
                Vector2Int coord    = new Vector2Int(i, eastCol);
                NodeV2     nodeInst = GetNode(coord);
                Vector3    nodePos  = nodeInst.gameObject.transform.position;
                if (!nodeInst.GetIsPath())
                {
                    Quaternion outterWallRot = Quaternion.AngleAxis(180, Vector3.up);
                    Instantiate(m_outterWall, nodePos + nodeInst.GetEnvOffset() + eastWallOffset, outterWallRot, this.gameObject.transform);
                }
            }

            // WEST WALL
            for (int i = 0; i < GetMapColCount(); ++i)
            {
                Vector2Int coord    = new Vector2Int(i, westCol);
                NodeV2     nodeInst = GetNode(coord);
                Vector3    nodePos  = nodeInst.gameObject.transform.position;
                if (!nodeInst.GetIsPath())
                {
                    Quaternion outterWallRot = Quaternion.AngleAxis(0, Vector3.up);
                    Instantiate(m_outterWall, nodePos + nodeInst.GetEnvOffset() + westWallOffset, outterWallRot, this.gameObject.transform);
                }
            }
        }



        //==================================================

        //                ADD OUTTER PILLARS

        //==================================================
        if (m_outterPillar != null)
        {
            // NE PILLAR
            if (true)
            {
                NodeV2  nodeInst  = GetNode(cornerNE);
                Vector3 posOffset = northWallOffset + eastWallOffset;
                Vector3 nodePos   = nodeInst.gameObject.transform.position;
                Instantiate(m_outterPillar, nodePos + nodeInst.GetEnvOffset() + posOffset, Quaternion.identity, this.gameObject.transform);
            }


            // NW PILLAR
            if (true)
            {
                NodeV2  nodeInst  = GetNode(cornerNW);
                Vector3 posOffset = northWallOffset + westWallOffset;
                Vector3 nodePos   = nodeInst.gameObject.transform.position;
                Instantiate(m_outterPillar, nodePos + nodeInst.GetEnvOffset() + posOffset, Quaternion.identity, this.gameObject.transform);
            }

            // SW PILLAR
            if (true)
            {
                NodeV2  nodeInst  = GetNode(cornerSW);
                Vector3 posOffset = southWallOffset + westWallOffset;
                Vector3 nodePos   = nodeInst.gameObject.transform.position;
                Instantiate(m_outterPillar, nodePos + nodeInst.GetEnvOffset() + posOffset, Quaternion.identity, this.gameObject.transform);
            }


            // SE PILLAR
            if (true)
            {
                NodeV2  nodeInst  = GetNode(cornerSE);
                Vector3 posOffset = southWallOffset + eastWallOffset;
                Vector3 nodePos   = nodeInst.gameObject.transform.position;
                Instantiate(m_outterPillar, nodePos + nodeInst.GetEnvOffset() + posOffset, Quaternion.identity, this.gameObject.transform);
            }
        }
    }