It's all well and good having three levels, but without a mechanism to move between them they are useless. We are going to add a check to see if the player has finished a level, if they have then increment the level counter and load the next level in the array. We only need to do the check at the end of every move; to do so every frame would be redundant.
We'll write the following method first and then explain it:
// If this method returns true then we have finished the level boolhaveFinishedLevel () { // Initialise the counter for how many crates are on goal // tiles int cratesOnGoalTiles = 0; // Loop through all the rows in the current level for (int i = 0; i< levels[currentLevel].Length; i++) { // Get the tile ID for the column and pass it the switch // statement for (int j = 0; j < levels[currentLevel][i].Length; j++) { switch (levels[currentLevel][i][j]) { case 5: // Do we have a match for a crate on goal // tile ID? If so increment the counter cratesOnGoalTiles++; break; default: break; } } } // Check if the cratesOnGoalTiles variable is the same as the // amountOfCrates we set when building the level if (amountOfCrates == cratesOnGoalTiles) { return true; } else { return false; } }
In the BuildLevel
method, whenever we instantiate crate
, we increment the amountOfCrates
variable. We can use this variable to check if the amount of crates on goal tiles is the same as the amountOfCrates
variable, if it is then we know we have finished the current level. The for
loops iterate through the current level's rows and columns, and we know that 5
in the array is a crate on a goal tile. The method returns a Boolean based on whether we have finished the level or not. Now let's add the call to the method. The logical place would be inside the MovePlayer
method, so go ahead and add a call to the method just after the pCol += tCol;
statement.
As the method returns true
or false
, we're going to use it in an if
statement, as shown in the following code:
// Check if we have finished the level if (haveFinishedLevel()) { Debug.Log("Finished"); }
The Debug.Log
method will do for now, let's check if it's working. The solution for level one is on YouTube at http://www.youtube.com/watch?v=K5SMwAJrQM8&hd=1. Click on the play icon at the top-middle of the Unity screen and copy the sequence of moves in the video (or solve it yourself), when all the crates are on the goal tiles you'll see Finished in the Console panel.
Assuming everything went correctly, you should have seen the Finished
text appear. Next is to load a new level which is probably going to be easier than you think. We already have all the code to build a level and add the character in our current scene. Rather than elaborately tear it down and unload the current assets, we can simply increment the currentLevel
counter and then reload the scene; our existing code will take care of the rest. Replace the Debug.Log
method with the following code:
// Check if we have finished the level if (haveFinishedLevel()) { currentLevel++; if (currentLevel == levels.Length) { currentLevel = 0; } PlayerPrefs.SetInt("currentLevel", currentLevel); Invoke("LoadNextLevel", 1.0f); }
Here, we are checking if we have finished the level with the haveFinishedlevel
method, and then incrementing the currentLevel
counter. The next check makes sure that it doesn't go over the amount of levels we actually have by comparing it to the Length
of the levels array, if it does go over, we set it back to 0
to loop the level order. We then store the level in the PlayerPrefs
object, so you can resume from that point after quitting the game. The last line is the Invoke
method, as we don't want to load the new level at the exact moment, we finish placing the last crate
. We can invoke a method after a delay. Here, the method to Invoke
is named LoadNextLevel
and the delay is 1.0f
, which means one second. Let's create the LoadLevel
method:
Void LoadNextlevel () { Application.LoadLevel("GameScreen"); }
As you've seen previously, Application.LoadLevel
just loads a new scene, and because we have set out method to use the currentLevel
variable, we can simply reload our scene to render the next level.
Sometimes things just don't go your way. In Sokoban
, you can get yourself into a situation where it is impossible to complete the level. As this is the case, then we need the ability to restart the game. Let's map it to the Y
button on the Ouya controller. Add the following code to the bottom of your Update
method:
// Should we restart the current level? if (OuyaInput.GetButtonDown(OuyaButton.Y, playerNumber)) { Application.LoadLevel("GameScreen"); }
Give your game a test on the Ouya, and when in the main game, click on the Y
button. You should reset back to the start position.
3.138.120.187