Advertisement

Adding parameters to a procedurally generated game board

Started by April 02, 2018 03:33 AM
3 comments, last by ethancodes 6 years, 5 months ago

I've got a brick breaker game that procedurally generates bricks in random locations. I have it narrowed down to the columns and rows that I want them to spawn in. However, I don't want a bunch of disjointed bricks everywhere. I want them to all be connected. I don't care too much about the general layout, as long as they are all touching when they spawn. How can I do this? Is there a way that I can make sure as each one spawns, it spawns touching one of the previously spawned ones? I have attached the code for the board manager for anyone who wants to see what I'm working with. Thanks!


		private int columns = 20;                //Number of columns in our game board.
		private int rows = 30;  				//Number of rows in our game board.

		public int brickCount;               //Number of bricks to spawn.

		//Define brick types to assign sprites to in editor
		public GameObject oneHitBrick;                                
		public GameObject twoHitBrick;                                  
		public GameObject threeHitBrick;                                 
		public GameObject explodingBarrel;  //temporarily represented by the unbreakable brick
		                         
		private Transform boardHolder;                                  //A variable to store a reference to the transform of our Board object.
		private List <Vector3> gridPositions = new List <Vector3> ();   //A list of possible locations to place tiles.

		//Clears our list gridPositions and prepares it to generate a new board.
		void InitialiseList ()
		{
			//Clear our list gridPositions.
			gridPositions.Clear ();

			//Loop through x axis (columns).
			for(int x = 1; x < columns-1; x++)
			{
				//Within each column, loop through y axis (rows).
				for(int y = 22; y < rows-1; y++)
				{
					//At each index add a new Vector3 to our list with the x and y coordinates of that position.
					gridPositions.Add (new Vector3(x, y, 0f));
				}
			}
		}

//RandomPosition returns a random position from our list gridPositions.
		Vector3 RandomPosition ()
	{
		//Declare an integer randomIndex, set it's value to a random number between 0 and the count of items in our List gridPositions.
		int randomIndex = Random.Range (1, gridPositions.Count);

		//Declare a variable of type Vector3 called randomPosition, set it's value to the entry at randomIndex from our List gridPositions.
		Vector3 randomPosition = gridPositions [randomIndex];

			//Remove the entry at randomIndex from the list so that it can't be re-used.
			gridPositions.RemoveAt (randomIndex);

			//Return the randomly selected Vector3 position.
			return randomPosition;
		}


		//LayoutObjectAtRandom accepts an array of game objects to choose from along with a minimum and maximum range for the number of objects to create.
		void LayoutObjectAtRandom (GameObject brick, int brickCount)
		{

			//Instantiate objects until the randomly chosen limit objectCount is reached
			for(int i = 0; i < brickCount; i++)
			{
				//Choose a position for randomPosition by getting a random position from our list of available Vector3s stored in gridPosition
				Vector3 randomPosition = RandomPosition();

				//Instantiate tileChoice at the position returned by RandomPosition with no change in rotation
				Instantiate(brick, randomPosition, Quaternion.identity);
			}
		}


		//SetupScene initializes our level and calls the previous functions to lay out the game board
		public void SetupScene (int level)
		{
			//Creates the outer walls and floor.
			//BoardSetup ();

			//Reset our list of gridpositions.
			InitialiseList ();

			brickCount = (int)Mathf.Log(level, 2f); //set the number of bricks based on the current level

			//Instantiate a random number of wall tiles based on minimum and maximum, at randomized positions.
			LayoutObjectAtRandom (oneHitBrick, brickCount);

			//Instantiate a random number of food tiles based on minimum and maximum, at randomized positions.
			LayoutObjectAtRandom (twoHitBrick, brickCount);

			LayoutObjectAtRandom (threeHitBrick, brickCount);
		}

 

It would probably be simpler to use a 2D array and have each element of that array store a brick or null.  Then when you want to see if a cell is OK to place a brick in, check to see if at least one neighboring cell has a brick in it.  You only have to check four elements of the array rather than the entire list of existing bricks.

You could also keep a set of locations that you know are good places to place bricks, and update that set when you add/remove bricks.  This would let you also randomly pick from that set fairly in one step, instead of having to randomly retry different locations if you can't place a brick at your first attempted location.

Advertisement

@Nypyren I've never really used multidimensional arrays, or arrays in general all that much. However after doing some reading I do think it would be best to follow your suggestion. I'm running into an error though when I try to set an indices to null once a brick has been set there. i don't want to accidentally choose the same grid space twice. Is there a way to set it to null without this error, or is there a better way of handling this entirely. Thank you!


gridPositions[randomIndex1,randomIndex2] = null;

the error is "Cannot convert null to 'UnityEngine.Vector3' because it is a non-nullable value type.

So this is the code I have so far for this. I'm really having a hard time figuring out how to get the grid positions that have a brick already spawned removed from the choices. I thought that I could just use an if statement to check whether it is null, and if it is then check to see if it's touching another brick. If it is then spawn, if not then choose another random location. What i don't like about this is that when we get down to needing to spawn just 1 or 2 bricks, there won't be many options left that meet those requirements. How much is this going to slow down my game because it's randomly picking a bunch of choices and hasn't landed on the correct one yet. Does anybody have any suggestions for me on how to remove a positions from pool of options? Thank you!


	private int columns = 20;                //Number of columns in our game board.
		private int rows = 30;  				//Number of rows in our game board.

		public int brickCount;               //Number of bricks to spawn.

		//Define brick types to assign sprites to in editor
		public GameObject oneHitBrick;                                
		public GameObject twoHitBrick;                                  
		public GameObject threeHitBrick;                                 
		public GameObject explodingBarrel;  //temporarily represented by the unbreakable brick
		                         
		private Transform boardHolder;                                  //A variable to store a reference to the transform of our Board object.
		//private List <Vector3> gridPositions = new List <Vector3> ();   //A list of possible locations to place tiles.
		private Vector3[,] gridPositions;
		//Clears our list gridPositions and prepares it to generate a new board.
		void InitialiseList ()
		{
			//Clear our list gridPositions.
			Array.Clear(gridPositions, 0, gridPositions.Length);
			//gridPositions.Clear ();

			//Loop through x axis (columns).
			for(int x = 1; x < columns-1; x++)
			{
				//Within each column, loop through y axis (rows).
				for(int y = 22; y < rows-1; y++)
				{
					//At each index add a new Vector3 to our list with the x and y coordinates of that position.
					gridPositions[x,y] = new Vector3();
				}
			}
		}
	
		//RandomPosition returns a random position from our list gridPositions.
		Vector3 RandomPosition ()
	{
		//Create 2 random ints to choose the grid position for a brick
		int randomIndex1 = Random.Range (1, gridPositions.Length);
		int randomIndex2 = Random.Range (1, gridPositions.Length);

		//Declare a variable of type Vector3 called randomPosition, set it's value to the entry at randomIndex from our List gridPositions.
		Vector3 randomPosition = gridPositions [randomIndex1,randomIndex2];

			//Remove the entry at randomIndex from the array so that it can't be re-used.
			gridPositions[randomIndex1,randomIndex2] = null;

			//Return the randomly selected Vector3 position.
			return randomPosition;
		}

 

This topic is closed to new replies.

Advertisement