MINING QUEST: ‘Keep Your Enemies Clo...Farther’ - Solutions

Quest: Mining Quest
Challenge: Keep Your Enemies Clo…Farther

Feel free to share your solutions, ideas and creations below. If you get stuck, you can find some ideas here for completing this challenge.

Making progress on the challenges. This one took me a while.
There is probably a simpler solution, but it is working.

In Start() I calculate the player starting position (center). This will be needed, once the map size gets variable too.

    private int centerLocationX;
    private int centerLocationY;

    void Start()
    {
        centerLocationX = (xSize / 2); // integer division
        centerLocationY = (ySize / 2); 
    }

In SpawnEnemies() I start by calculating a List of valid locations (each an array with coordinates). If at least one coordinate x/y is not in the safe zone, the location is valid. Later I pick a random location from that list for each enemy.

private void SpawnEnemies()
    {
        // Challenge 5, safe space 3x3 around player
        List<int[]> validLocations = new List<int[]>();

        for (int x = 0; x < xSize; x++)
        {
            for (int y = 0; y < ySize; y++)
            {
                if (x < centerLocationX - 1 || x > centerLocationX + 1 ||
                    y < centerLocationY - 1 || y > centerLocationY + 1)
                {
                    int[] location = { x, y };
                    validLocations.Add(location);
                }
            }
        }

        for (int i = 0; i < amountOfEnemies; i++)
        {
            int[] randomLocation = validLocations[Random.Range(0, validLocations.Count - 1)];

            Vector2 spawnLocation = new Vector2(randomLocation[0], randomLocation[1]);
            Instantiate(enemyPrefab, spawnLocation, Quaternion.identity);
        }
    }
3 Likes

Because the map changes sizes at runtime, I first had to ensure the player ended up generally in the middle. It’s a bit brute force, but it works. I then iterate through a 3x3 grid around the player and feed those to my Blocked Coordinates method. That method takes the x/y coordinates and drops it into a list of Vector2s that will be referenced later to tell the rest of the items and enemies what coordinates they cannot spawn on:

    void Awake() 
    {
        gridLength = Random.Range(gridMin,gridMax);
        playerSpawn = gridLength / 2;
        PlacePlayer();
        blockedCoordinates = new List<Vector2>();
    }
    void Start()
    {
        SetPlayerSafeZone();
        GenerateEnviron();
        SpawnEnemies();
    }

    private void PlacePlayer()
    {
        playerPrefab.transform.position = new Vector2(playerSpawn,playerSpawn);
    }
    private void SetPlayerSafeZone()
    {
        int playerXPosOffset = (int)playerPrefab.transform.position.x -1;
        int playerYPosOffset = (int)playerPrefab.transform.position.y -1;

        for (int x = (int)playerPrefab.transform.position.x - 1; x < playerXPosOffset + 3; x++)
        {
            for (int y = (int)playerPrefab.transform.position.y - 1; y < playerYPosOffset + 3; y++)
            {
                BlockCoordinates(x,y);
            }
        }
    }

And then in my SpawnEnemies() method I first divide the length of the grid by an int (currently set to 3) to determine how many enemies will spawn, so that the number of enemies increases as the grid does. I then iterate through the for loop, and while it still picks a random Vector2 to instantiate on, before actually instantiating it checks my list of Blocked Coordinates. If the Vector2 is not on the list, the enemy is instantiated, otherwise I subtract 1 from “I” in order to rerun the check and ensure that all of the enemies spawn.

private void SpawnEnemies()
    {
        int amountOfEnemies = gridLength/enemyDivisor;

        for (int i = 0; i < amountOfEnemies; i++)
        {
            Vector2 spawnLocation = new Vector2(Random.Range(1, gridLength), Random.Range(1, gridLength));
            if(CanSpawn((int)spawnLocation.x,(int)spawnLocation.y))
            {
                GameObject newEnemy = Instantiate(enemyPrefab, spawnLocation, Quaternion.identity);
            } 
            else
            {
                i--;
            }
        }
    }

Privacy & Terms