UnityGameProjectsCode / Rise2Point0Game / Level / LevelGenerator.cs
LevelGenerator.cs
Raw
using System.Collections.Generic;
using UnityEngine;

public class LevelGenerator : MonoBehaviour
{
    public List<GameObject> tileSets = new List<GameObject>();
    public List<GameObject> tileRightConnectors = new List<GameObject>();
    public List<GameObject> tileLeftConnectors = new List<GameObject>();
    private List<GameObject> createdNormalTiles = new List<GameObject>();
    private List<GameObject> createdConnectorTiles = new List<GameObject>();
    private List<GameObject> createdBackgrounds = new List<GameObject>();
    private List<GameObject> createdClouds = new List<GameObject>();
    private List<GameObject> createdParticles = new List<GameObject>();
    private GameObject createdSecretTile;
    List<GameObject> inactiveTileSets = new List<GameObject>();
    List<GameObject> inactiveRightConnectorTileSets = new List<GameObject>();
    List<GameObject> inactiveLeftConnectorTileSets = new List<GameObject>();
    List<GameObject> inactiveBackgrounds = new List<GameObject>();
    private GameObject envObjects;
    private GameObject deathWall;

    public GameObject backgroundPrefab;
    public GameObject cloudsPrefab;
    public GameObject particlesPrefab;
    public Material baseBackgroundMaterial;
    public Sprite baseBackgroundSprite;
    public Material backgroundVariationMaterial;
    public Sprite backgroundVariationSprite;
    public Material baseFadeBackgroundMaterial;
    public Sprite baseFadeBackgroundSprite;
    public Material backgroundFadeVariationMaterial;
    public Sprite backgroundFadeVariationSprite;
    public GameObject secretTilePrefab;

    private GameObject baseBackground;
    private GameObject playerObject;
    private int tileIteration = 0;
    private int tileCurrentHeight = 0;
    private int tileBuildHeight = 0;
    private bool secretTileUsed;

    private Color[] colors = new Color[] {
        new Color(0.7f, 0, 1, 1), //purple
        new Color(1, 0.5f, 0, 1), //orange
        new Color(0.85f, 0.7f, 0, 1), //gold
        new Color(1, 0.8f, 0.4f, 1), //sunOrange
        new Color(0.7f, 1, 0.21f, 1), //crimson
        new Color(0.54f, 0.23f, 0, 1), //brown
        new Color(0.66f, 0.66f, 0.66f, 1), //silver
        new Color(0.78f, 0.5f, 0.18f, 1), //bronze
        new Color(0.61f, 0.82f, 0.9f, 1), //diamond
        new Color(0.1f, 0.52f, 0.7f, 1), //dark blue
        new Color(0.83f, 0.4f, 0.65f, 1), //pink
        new Color(0.52f, 0.55f, 0.77f, 1), //light blue
        new Color(0.17f, 1, 0.4f, 1) //light green
    };

    public List<GameObject> CreatedNormalTiles { get => createdNormalTiles; set => createdNormalTiles = value; }
    public List<GameObject> CreatedConnectorTiles { get => createdConnectorTiles; set => createdConnectorTiles = value; }
    public List<GameObject> CreatedBackgrounds { get => createdBackgrounds; set => createdBackgrounds = value; }
    public List<GameObject> CreatedClouds { get => createdClouds; set => createdClouds = value; }
    public List<GameObject> CreatedParticles { get => createdParticles; set => createdParticles = value; }

    private void Awake()
    {
        envObjects = GameObject.Find("Env Objects");
        playerObject = ObjectManager.GetObject(0);
    }

    private void Start()
    {
        baseBackground = GUIManager.GetObject(0);
        deathWall = ObjectManager.GetObject(2);
        //ChangeBaseBackgroundColor();

        //tiles will only need to be created once since the same tiles will be used for everything
        CreateTileSets();

        BuildLevel();
    }

    private void Update()
    {
        //if the player is above the tile build height, place more tiles
        if (!GUIManager.GetMainMenuCanvasState())
        {
            bool playerState = playerObject.activeSelf;

            if (playerState)
            {
                int playerHeight = Mathf.RoundToInt(playerObject.transform.position.y + 3.5f);

                if (playerHeight >= tileBuildHeight)
                {
                    BuildLevel();
                }
            }
            else
            {
                int deathWallHeight = Mathf.RoundToInt(deathWall.transform.position.y + 35);

                if (deathWallHeight >= tileBuildHeight)
                {
                    BuildLevel();
                }
            }
        }
    }

    public void CreateTileSets()
    {
        try
        {
            //Make 2 copies of each tile set and then turn them off
            for (int i = 0; i < tileSets.Count; i++)
            {
                for (int y = 0; y < 2; y++)
                {
                    createdNormalTiles.Add(Instantiate(tileSets[i] as GameObject, envObjects.transform));
                    createdNormalTiles[createdNormalTiles.Count - 1].SetActive(false);
                }
            }

            //Make 2 copies of all right and left connectors

            for (int i = 0; i < tileRightConnectors.Count; i++)
            {
                for (int y = 0; y < 2; y++)
                {
                    createdConnectorTiles.Add(Instantiate(tileRightConnectors[i] as GameObject, envObjects.transform));
                    createdConnectorTiles[createdConnectorTiles.Count - 1].SetActive(false);
                }
            }

            for (int i = 0; i < tileRightConnectors.Count; i++)
            {
                for (int y = 0; y < 2; y++)
                {
                    createdConnectorTiles.Add(Instantiate(tileLeftConnectors[i] as GameObject, envObjects.transform));
                    createdConnectorTiles[createdConnectorTiles.Count - 1].SetActive(false);
                }
            }

            //make 5 background objects
            for (int i = 0; i < 5; i++)
            {
                createdBackgrounds.Add(Instantiate(backgroundPrefab as GameObject, envObjects.transform));
                createdBackgrounds[i].SetActive(false);
            }

            //make 1 copy of the secret tile
            createdSecretTile = Instantiate(secretTilePrefab as GameObject, envObjects.transform);
            createdSecretTile.SetActive(false);
        }
        catch (System.Exception e)
        {
            Debug.Log(e.StackTrace);
        }
    }

    public void SetTileObstaclesStates(bool newState)
    {
        foreach (GameObject normalTile in createdNormalTiles)
        {
            normalTile.GetComponent<TileControl>().SetObstaclesState(newState);
        }

        foreach (GameObject connectorTile in createdConnectorTiles)
        {
            connectorTile.GetComponent<TileControl>().SetObstaclesState(newState);
        }
    }

    public void BuildLevel()
    {
        try
        {
            GameObject targetTileSet;
            int tileXPos = -20;
            int tileYPos = 0;

            //find and add any inactive tiles to the list that have not been added
            foreach (GameObject tileSet in createdNormalTiles)
            {
                if (!tileSet.activeSelf && !inactiveTileSets.Contains(tileSet))
                    inactiveTileSets.Add(tileSet);
            }

            foreach (GameObject tileSet in createdConnectorTiles)
            {
                if (!tileSet.activeSelf && tileSet.CompareTag("Right Tile") && !inactiveRightConnectorTileSets.Contains(tileSet))
                    inactiveRightConnectorTileSets.Add(tileSet);

                if (!tileSet.activeSelf && tileSet.CompareTag("Left Tile") && !inactiveLeftConnectorTileSets.Contains(tileSet))
                    inactiveLeftConnectorTileSets.Add(tileSet);
            }

            foreach (GameObject background in createdBackgrounds)
            {
                if (!background.activeSelf && !inactiveBackgrounds.Contains(background))
                    inactiveBackgrounds.Add(background);
            }

            //raise the tile height to match the new height for the start of this set
            for (int i = 0; i < tileIteration; i++)
            {
                tileYPos += 40;
            }

            //if this is not the first itteration, added a new background and BG effects
            if (tileIteration > 0)
            {
                GameObject tempBackground = inactiveBackgrounds[Random.Range(0, inactiveBackgrounds.Count)];
                GameObject tempClouds = Instantiate(cloudsPrefab as GameObject, envObjects.transform);
                GameObject tempParticles = Instantiate(particlesPrefab as GameObject, envObjects.transform);
                tempBackground.SetActive(true);
                tempBackground.transform.position = new Vector3(0, tileYPos + 40, 1);
                tempClouds.transform.position = tempBackground.transform.position;
                tempParticles.transform.position = new Vector3(0, tempBackground.transform.position.y - 40, 2);

                int randomColor = Random.Range(0, colors.Length);

                //NO LONGER NEEDED. NO BACKGROUND COLOR CHANGES.

                //tempBackground.GetComponent<SpriteRenderer>().material.color = colors[randomColor];

                //foreach (Transform transform in tempBackground.GetComponentInChildren<Transform>())
                //{
                //    transform.gameObject.GetComponent<SpriteRenderer>().material.color = colors[randomColor];
                //}

                inactiveBackgrounds.Remove(tempBackground);
                createdClouds.Add(tempClouds);
                createdParticles.Add(tempParticles);
            }

            //place 12 different tiles into the set positions
            for (int i = 0; i < 12; i++)
            {
                //if in position to place a connector, choose if one should be placed
                if ((tileXPos == -20 || tileXPos == 0) && inactiveRightConnectorTileSets.Count > 0)
                {
                    //if so, choose a connector from both the right and left sets and place them
                    if (Random.Range(0, 2) == 1)
                    {
                        targetTileSet = inactiveRightConnectorTileSets[Random.Range(0, inactiveRightConnectorTileSets.Count)];
                        GameObject targetLeftConnector = inactiveLeftConnectorTileSets[Random.Range(0, inactiveLeftConnectorTileSets.Count)];

                        targetTileSet.SetActive(true);
                        targetTileSet.transform.position = new Vector2(tileXPos, tileYPos);
                        targetLeftConnector.SetActive(true);
                        targetLeftConnector.transform.position = new Vector2(tileXPos + 20, tileYPos);

                        SpawnItemsOnTileSet(targetTileSet);
                        SpawnItemsOnTileSet(targetLeftConnector);

                        inactiveRightConnectorTileSets.Remove(targetTileSet);
                        inactiveLeftConnectorTileSets.Remove(targetLeftConnector);

                        //increment the tile position to account for the 2 new tiles
                        tileXPos += 40;

                        if (tileXPos == 40)
                        {
                            tileXPos = -20;
                            tileYPos += 20;
                        }

                        //increment i to account for the 2nd tile added
                        i++;
                    }
                    else //if a connector is not going to be used, place a random normal tile
                    {
                        targetTileSet = inactiveTileSets[Random.Range(0, inactiveTileSets.Count)];

                        targetTileSet.SetActive(true);
                        targetTileSet.transform.position = new Vector2(tileXPos, tileYPos);

                        SpawnItemsOnTileSet(targetTileSet);

                        inactiveTileSets.Remove(targetTileSet);

                        tileXPos += 20;

                        if (tileXPos == 40)
                        {
                            tileXPos = -20;
                            tileYPos += 20;
                        }
                    }
                }
                else //if not in position for a right connector OR no connectors were available, create a normal tile
                {
                    //choose if the secret tile will be used if at xPos 20
                    //check if the tile has already been used in the current run
                    if (!secretTileUsed && tileXPos == 20 && tileBuildHeight >= 320)
                    {
                        int secretWallUseChance = Random.Range(0, 100);

                        if (secretWallUseChance > 97)
                        {
                            targetTileSet = createdSecretTile;
                            secretTileUsed = true;
                        }
                        else
                            targetTileSet = inactiveTileSets[Random.Range(0, inactiveTileSets.Count)];
                    }
                    else
                    {
                        targetTileSet = inactiveTileSets[Random.Range(0, inactiveTileSets.Count)];
                    }

                    targetTileSet.SetActive(true);
                    targetTileSet.transform.position = new Vector2(tileXPos, tileYPos);

                    SpawnItemsOnTileSet(targetTileSet);

                    inactiveTileSets.Remove(targetTileSet);

                    tileXPos += 20;

                    if (tileXPos == 40)
                    {
                        tileXPos = -20;
                        tileYPos += 20;
                    }
                }
            }

            tileIteration += 2;
            tileCurrentHeight += 80;
            tileBuildHeight = tileCurrentHeight - 20;
        }
        catch (System.Exception e)
        {
            Debug.LogError(e.StackTrace);
        }
    }

    public void SpawnItemsOnTileSet(GameObject tileSet)
    {
        try
        {
            tileSet.GetComponent<TileControl>().SpawnItems();
        }
        catch (System.Exception e)
        {
            Debug.Log(e.StackTrace);
        }
    }

    public void ResetLevel()
    {
        for (int i = 0; i < createdNormalTiles.Count; i++)
        {
            ResetTileSet(createdNormalTiles[i]);
        }

        for (int i = 0; i < createdConnectorTiles.Count; i++)
        {
            ResetTileSet(createdConnectorTiles[i]);
        }

        ResetTileSet(createdSecretTile);

        for (int i = 0; i < createdBackgrounds.Count; i++)
        {
            createdBackgrounds[i].SetActive(false);
        }

        for (int i = 0; i < createdClouds.Count; i++)
        {
            GameObject[] tempRefs = createdClouds.ToArray();
            Destroy(tempRefs[i]);
        }

        for (int i = 0; i < createdParticles.Count; i++)
        {
            GameObject[] tempRefs = createdParticles.ToArray();
            Destroy(tempRefs[i]);
        }

        createdClouds.Clear();
        createdParticles.Clear();
        tileIteration = 0;
        tileCurrentHeight = 0;
        tileBuildHeight = 0;
        secretTileUsed = false;

        //ChangeBaseBackgroundColor();
    }

    //public void ChangeBaseBackgroundColor()
    //{
    //    int randomColor = Random.Range(0, colors.Length);
    //    baseBackground.GetComponent<SpriteRenderer>().material.color = colors[randomColor];
    //}

    public void ChangeAllTilesBackgroundMaterials()
    {
        //called from unlock system to change the appearance of backgrounds
        for (int i = 0; i < createdBackgrounds.Count; i++)
        {
            createdBackgrounds[i].GetComponent<SpriteRenderer>().material = backgroundVariationMaterial;
            createdBackgrounds[i].GetComponent<SpriteRenderer>().sprite = backgroundVariationSprite;

            foreach (Transform item in CreatedBackgrounds[i].GetComponentInChildren<Transform>())
            {
                if (item.name == "Bottom Fade")
                {
                    item.GetComponent<SpriteRenderer>().material = backgroundFadeVariationMaterial;
                    item.GetComponent<SpriteRenderer>().sprite = backgroundFadeVariationSprite;
                }
            }
        }

        baseBackground.GetComponent<SpriteRenderer>().material = backgroundVariationMaterial;
        baseBackground.GetComponent<SpriteRenderer>().sprite = backgroundVariationSprite;
    }

    public void RevertAllBackgroundMaterials()
    {
        //called when resetting unlocks to reset backgrounds to their default material.
        Color lastColor = baseBackground.GetComponent<SpriteRenderer>().material.color;

        for (int i = 0; i < createdBackgrounds.Count; i++)
        {
            createdBackgrounds[i].GetComponent<SpriteRenderer>().material = baseBackgroundMaterial;
            createdBackgrounds[i].GetComponent<SpriteRenderer>().material.color = lastColor;
            createdBackgrounds[i].GetComponent<SpriteRenderer>().sprite = baseBackgroundSprite;

            foreach (Transform item in CreatedBackgrounds[i].GetComponentInChildren<Transform>())
            {
                if (item.name == "Bottom Fade")
                {
                    item.GetComponent<SpriteRenderer>().material = baseFadeBackgroundMaterial;
                    item.GetComponent<SpriteRenderer>().material.color = lastColor;
                    item.GetComponent<SpriteRenderer>().sprite = baseFadeBackgroundSprite;
                }
            }
        }

        baseBackground.GetComponent<SpriteRenderer>().material = baseBackgroundMaterial;
        baseBackground.GetComponent<SpriteRenderer>().material.color = lastColor;
        baseBackground.GetComponent<SpriteRenderer>().sprite = baseBackgroundSprite;
    }

    private void ResetTileSet(GameObject tileToReset)
    {
        tileToReset.SetActive(false);
        tileToReset.GetComponent<TileControl>().RemoveItems();

        foreach (Transform item in tileToReset.GetComponentsInChildren<Transform>())
        {
            if (item.TryGetComponent(out BoxCollider2D boxColl))
                if(boxColl.name == "Blocker Wall")
                    boxColl.enabled = false;
                else
                    boxColl.enabled = true;

            if (item.TryGetComponent(out SpriteRenderer targetSprite))
            {
                Color currentSpriteColor = targetSprite.color;

                if (item.name == "Glow")
                    targetSprite.color = new Color(currentSpriteColor.r, currentSpriteColor.g, currentSpriteColor.b, 0.1019608f);
                else if (item.name.Contains("Gradient"))
                    targetSprite.color = new Color(currentSpriteColor.r, currentSpriteColor.g, currentSpriteColor.b, 0.07843138f);
                else
                    targetSprite.color = new Color(currentSpriteColor.r, currentSpriteColor.g, currentSpriteColor.b, 1);

                if(item.name.Contains("Wall Piece"))
                    item.gameObject.SetActive(false);
            }
        }
    }
}