I have a puzzle game I am creating that features a grid based on the values of a 2D array. The player can then place special orbs that modify the values in the grid squares (0 is a blank orb, 1 is fire orb, 2 is water orb, 3 is lightning orb, 4 is earth orb, 9 is a blank space for an orb to be placed). This works perfectly. The problem I’m having is when I try to reset or change the level, the values are not being reset or properly updated. If I place a special orb in a grid space and change the level, the sprite resets but it retains the special orb value in that position. I’m guessing the issue is with how I’m trying to update the array values for the new level?
Here is my script that is in charge of the array data and the for loops. The GUI button script at the bottom has the current level change code. All of the grid spaces have the “gridspace” tag so they can be deleted before the new level is created.
//These are variables needed for the level creation portion of the game to work
var obj_BlankSpot : Transform;
var obj_PlacedBlankOrb : Transform;
var currentOrb : int; // sets up the currently selected orb variable for use with other scripts
static var gridH : int; //used for grid height
static var gridW : int; //used for grid width
static var r : int; //used in the grid creation for loops
static var c : int; //used in the grid creation for loops
var destroyGrid : GameObject[]; // used to destroy puzzle grid game objects when a level is reset or loaded
//This will create a 2D array that will hold some spots and data for various squares
//9 represents a blank square where a player can place an orb
//0 represent a square filled with a blank orb
var startX : int = -1; // this is the left hand side of the puzzle grid
var startY : int = 1; // this is the top of the puzzle grid
var gridArray = [
[9, 0, 9, 0],
[9, 9, 0, 9],
[9, 9, 9, 9],
[0, 0, 9, 0]];
function Start()
{
///This will end up placing the correct objects in the level based on gridArray
gridW = gridArray[0].length; //gets the width of the gridArray for the for loops
gridH = gridArray.length; //gets the height of the gridArray for the for loops
for(r = 0; r < gridW; r++)
{
for(c = 0; c < gridH; c++)
{
var currentX = startX + (r*.96); // this moves newsprites right for each new column being created
var currentY = startY - (c*.96); // this moves new sprites down for each new row being created
// 1 pixel seems to be .01 unity units. 100 pixels would be 1 unit
// r and c are reversed in the if statements so the squares are placed left to right
if(gridArray
[r] == 9)
{
Instantiate(obj_BlankSpot, Vector3 (currentX, currentY, 0), Quaternion.identity); //this object is a blank square where a player can place an or
}
else if(gridArray[c][r] == 0)
{
Instantiate(obj_PlacedBlankOrb, Vector3 (currentX, currentY, 0), Quaternion.identity); // this object is a square that hold a blank orb that can be broken
}
}
}
}
//Make these buttons fully reset the level and not just the graphics of the sprites but all the data as well
function OnGUI()
{
// Make a background box
GUI.Box (Rect (10,10,100,90), "Menu");
// Make the first button. If it is pressed, the board will be cleared and level 2 will be loaded
if (GUI.Button (Rect (20,40,80,20), "Level 2"))
{
destroyGrid = GameObject.FindGameObjectsWithTag ("gridspace"); // adds all puzzle grid pieces to the destroyGrid array
for(var o = 0 ; o < destroyGrid.length ; o ++) // for all entries in the destroyGrid array
{
Destroy(destroyGrid[o]); //destroys the current grid piece
}
// sets up a test grid for level 2
gridArray = [
[9, 0, 9, 0, 9],
[9, 9, 0, 9, 9],
[9, 0, 9, 0, 9],
[9, 9, 9, 9, 9],
[0, 0, 9, 0, 9]];
Start(); // runs the start function again to create the new grid
}
}
I know that's a chunk of code to sort through, so I took a few screenshots in case those help explain the problem. The first screenshot shows the level 1 4x4 grid with an orb placed in the top left. The second screenshot shows that level 2 has a 5x5 grid but I can't place orbs in the the spot that the lightning orb was placed in level 1 or in the 5th row and column, which weren't present in level 1. That makes me think I'm doing something wrong when I try to update the array for the new level.
![alt text][1]
![alt text][2]
[1]: http://i.imgur.com/0kuBYEq.png?1
[2]: http://i.imgur.com/VqBIkKk.png?1
///////////////////////////////////////////////////////////////////////////
//////////
UPDATE: Blank Spot Script
/////////
///////////////////////////////////////////////////////////////////////////
Here is a copy of the other script in which I modify gridArray from the code above. I cut out a large portion of the code for this example simply to save space since it just consisted of more if statements using the same code. A few things to note is that the gridArrayScript variable links to the script above so that I can access variables from that. xCoord and yCoord in the Awake() function save the r and c values at the time of creation so that each instance of the prefab will remember where it's positioned in the grid. When the game object is clicked on with the mouse, it uses xCoord and yCoord to access its position in gridArray and change the value of that spot. Of course at this point, it looks like the objects are still pulling from the original gridArray instead of the new one in level 2. How would I go about fixing that?
//selectedOrbScript : scr_gridArray makes it so that I can access scr_gridArray's variables like currentOrb
//the sprite values make it so that the blank spot can change into various orbs based on what the player has selected
var gridArrayScript : scr_gridArray;
gridArrayScript.currentOrb = 0; // sets the value of currentOrb to 0 at the beginning of each level when it is placed
var xCoord : int;
var yCoord : int;
var fireSprite : Sprite;
var waterSprite : Sprite;
var lightningSprite : Sprite;
var earthSprite : Sprite;
function Awake()
{
xCoord = gridArrayScript.r; //sets xCoord = to the c value in the loops for the 2D array
yCoord = gridArrayScript.c; //sets yCoord = to the r value in the loops for the 2D array
}
/* Orb data codes for if checks in the mouse click function
0 = blank orb
1 = fire orb
11 = fire in empty square
13 = fire and lightning in empty square
2 = water orb
22 = water in empty square
3 = lightning orb
33 = lightning in empty square
4 = earth orb
9 = empty square
*/
function OnMouseDown ()
{
if(gridArrayScript.gridArray[yCoord][xCoord] == 9 ||
gridArrayScript.gridArray[yCoord][xCoord] == 11 ||
gridArrayScript.gridArray[yCoord][xCoord] == 13 ||
gridArrayScript.gridArray[yCoord][xCoord] == 22 ||
gridArrayScript.gridArray[yCoord][xCoord] == 33) // checks to see if the spot has no orb before executing any code
{
//in the if statements xCoord and yCoord are reversed due to the way the grid is created
////////////////////////////////
//Fire Orb Code
///////////////////////////////
if(gridArrayScript.currentOrb == 1) //execute this is fire orb is currently selected
{
GetComponent(SpriteRenderer).sprite = fireSprite; //changes the sprite to a fire orb
if (gridArrayScript.gridArray[yCoord][xCoord] == 33 ||
gridArrayScript.gridArray[yCoord][xCoord] == 13 ) // checks to see if the square has lightning or fire and lightning in it
{
print ("You broke an orb"); ////////////////// remove this line when testing is done and replace it with a pop up messages, level reset, and broken orb sprite
}
else //if the spot doesn't have lightning in it to break the fire orb as it's placed, execute the code
{
gridArrayScript.gridArray[yCoord][xCoord] = 1; // changes the data for this square to fire orb
// Executes fire orb code going to the right or x+
if ((xCoord+1) < gridArrayScript.gridW) //checks to see if there is a grid space to the right
{
if (gridArrayScript.gridArray[yCoord][xCoord+1] == 0 ||
gridArrayScript.gridArray[yCoord][xCoord+1] == 3) //checks to see if the object is a blank orb or lightning orb
{
print ("You broke an orb"); ////////////////// remove this line when testing is done and replace it with a pop up messages, level reset, and broken orb sprite
}
else if (gridArrayScript.gridArray[yCoord][xCoord+1] == 9) // checks to see if this is an empty square
{
gridArrayScript.gridArray[yCoord][xCoord+1] = 11; // changes the data for this square to be fire an empty square
}
else if (gridArrayScript.gridArray[yCoord][xCoord+1] == 33) // checks to see if this is an empty square with lightning
{
gridArrayScript.gridArray[yCoord][xCoord+1] = 13; // changes the data for this square to be fire and lightning in an empty square
}
if ((xCoord+2) < gridArrayScript.gridW) //checks to see if there is a grid space 2 spaces to the right
{
if(gridArrayScript.gridArray[yCoord][xCoord+1] != 4) // checks to see if there was an earth orb in the previous square to block this
{
if (gridArrayScript.gridArray[yCoord][xCoord+2] == 0 ||
gridArrayScript.gridArray[yCoord][xCoord+2] == 3) //checks to see if the object is a blank orb or lightning orb
{
print ("You broke an orb"); ////////////////// remove this line when testing is done and replace it with a pop up messages, level reset, and broken orb sprite
}
else if (gridArrayScript.gridArray[yCoord][xCoord+2] == 9) // checks to see if this is an empty square
{
gridArrayScript.gridArray[yCoord][xCoord+2] = 11; // changes the data for this square to be fire an empty square
}
else if (gridArrayScript.gridArray[yCoord][xCoord+2] == 33) // checks to see if this is an empty square with lightning
{
gridArrayScript.gridArray[yCoord][xCoord+2] = 13; // changes the data for this square to be fire and lightning in an empty square
}
}
}
}
}
}
//more similar code for different circumstances
}
}
///////////////////////////////////////////////////////////////////////////
/////////////////////////////2ND UPDATE://////////////////////////
///////////////////////////////////////////////////////////////////////////
So I tried out NoseKills debugging process just to double check the values of the array after it had supposedly been updated. As shown above, level 1's array has the following set up:
[9, 0, 9, 0],
[9, 9, 0, 9],
[9, 9, 9, 9],
[0, 0, 9, 0]];
I placed fire orbs in all of the blank spots which changed it to:
[1, 0, 1, 0],
[1, 1, 0, 1],
[1, 1, 1, 1],
[0, 0, 1, 0]];
After I press the "level 2 button" the array should be reset to:
[9, 0, 9, 0, 9],
[9, 9, 0, 9, 9],
[9, 0, 9, 0, 9],
[9, 9, 9, 9, 9],
[0, 0, 9, 0, 9]];
However it's not changing at all after I used the print out that NoseKills suggested. All of the 9's are still 1's, and the print out isn't even acknowledging that there is a 5th row and column. The highest space on the grid that the printout shows after level 2 was loaded is 3,3 instead of 4,4 like it should be. The second script is still pulling the original array data instead of the new one. Is there any easy to way to fix that or something I should include in my second scripts OnMouseDown or Awake functions?
///////////////////////////////////////////////////////////////////////////
//////////////////////Final Update?//////////////////////////////
///////////////////////////////////////////////////////////////////////////
So I was able to fiddle with things enough that I think I may have stumbled across a fix. From the limited testing that I've done, it looks like the array data is updating properly, even though I'm not 100% sure why this worked and the other did not. With the following code the game starts out with nothing, and pressing the level buttons load the appropriate puzzle grid and wipes away the old data. My only issue at the moment is that I can't declare my 2D array as blank without popping up a bunch of errors in that script or one of the ones that point to it. To bypass that I just threw in a value that has no meaning just to make it work. Here's the new code.
var startX : int; // used to track the left side of the puzzle grid
var startY : int; // used to track the top of the puzzle grid
//this is just a placeholder to declare the 2D array so that there aren't errors, creates a blank level
static var gridArray = [[99]];
levelCounter = 0; //starts the level counter at 0
function Start()
{
//puts all grid spaces into the destroyGrid array so they can be destroyed before the level is recreated
destroyGrid = GameObject.FindGameObjectsWithTag ("gridspace");
for(var o = 0 ; o < destroyGrid.length ; o ++)//cycles through all the grid spaces
{
Destroy(destroyGrid[o]); //destroys the current grid space
}
//This will create a 2D array that will hold some spots and data for various squares based on the level
//9 represents a blank square where a player can place an orb
//0 represent a square filled with a blank orb
if(levelCounter == 1) //if level 1 is selected
{
startX = -1; // this is the left hand side of the puzzle grid
startY = 1; // this is the top of the puzzle grid
gridArray = [
[9, 0, 9, 0],
[9, 9, 0, 9],
[9, 9, 9, 9],
[0, 0, 9, 0]];
}
else if(levelCounter == 2) //if level 2 is selected
{
startX = -2; // this is the left hand side of the puzzle grid
startY = 1; // this is the top of the puzzle grid
gridArray = [
[9, 0, 9, 0, 9],
[9, 9, 0, 9, 9],
[9, 0, 9, 0, 9],
[9, 9, 9, 9, 9],
[0, 0, 9, 0, 9]];
}
///This will end up placing the correct objects in the level based on gridArray
gridW = gridArray[0].length; //gets the width of the gridArray for the for loops
gridH = gridArray.length; //gets the height of the gridArray for the for loops
for(r = 0; r < gridW; r++)
{
for(c = 0; c < gridH; c++)
{
var currentX = startX + (r*.96); // this moves newsprites right for each new column being created
var currentY = startY - (c*.96); // this moves new sprites down for each new row being created
// 1 pixel seems to be .01 unity units. 100 pixels would be 1 unit
// r and c are reversed in the if statements so the squares are placed left to right
if(gridArray[c][r] == 9)
{
Instantiate(obj_BlankSpot, Vector3 (currentX, currentY, 0), Quaternion.identity); //this object is a blank square where a player can place an or
}
else if(gridArray[c][r] == 0)
{
Instantiate(obj_PlacedBlankOrb, Vector3 (currentX, currentY, 0), Quaternion.identity); // this object is a square that hold a blank orb that can be broken
}
}
}
}
Do you pass gridArray to some other script to be manipulated by player controls? Do you pass the new grid to that scrip also or is that other script still trying to modify the old grid perhaps? Might be useful to put some Debug.Log()s in place to see what actually is stored in the array you are trying to add orbs to in level 2.
– NoseKillsActually yeah, the script that I have set up to execute the code for placing orbs into the blank spots ends up accessing gridArray so it can change the value/data of that spot in order to react with the rest of the board. For example, the blank spot in the top left corner is [0,0] starts with a value of 9 (indicates an empty spot). If I place a fire orb there (value of 1) it would change [0,0] to a value of 1. You're thinking that even those I'm setting the gridArray to have new values, that the old values are still being stored and accessed somewhere? I'll see if I can test that
– floydtheroosterYeah. Could you post code of how you are using gridArray in your other scripts? You have to realise that when yo make the Level 2 gridArray, that's a completely new array instance. If you passed gridArray to other scripts in Level1, make sure to pass the newly created gridArray to all those scripts in Level 2 again.
– NoseKillsAlright so I tried out the test code by printing out what the value of the array is after I change some of the values and try to load level 2. As previously though, the array isn't updating at all, even though graphically the new game objects are being created, the data within gridArray is not changing. The any blank spaces that I modified are still modified, and during the print out, it doesn't even include column or row 5 (4 in the actual array). This must be way it keeps saying it's outside the scope of the array when I click on those ones.
– floydtherooster