Level Selection Screen
As the deadline to submit the game is approaching, I am lacking time to write devlogs. And my professional life doesn't help. I am also missing time to work on the game itself. Thus, I guess the devlogs will be shorter and less detailed for this last week.
Two days ago I worked onthe level selection screen. It looks like that :
You can find the code in the repository : LevelSelectionScreen.java.
Creation of the level selection table
Basically, the LevelSelectionScreen.java contains a Table, with many TextButtons. I already talked about the of Table and TextButton to create the HUD.
The key part of the LevelSelectionScreen.java is the positioning of the various TextButtons to form a nice table. Here is the code :
tableLevels = new Table(); tableLevels.defaults().width(Gdx.graphics.getWidth()/10).height(Gdx.graphics.getWidth()/10).space(Gdx.graphics.getWidth()/60); levels = new Array<TextButton>(); for(int i = 0; i < GameConstants.NUMBER_OF_LEVEL; i++){ TextButton textButton = new TextButton("" + (i + 1), textButtonStyle); levels.add(textButton); if((i + 1)%5 == 0) tableLevels.add(textButton).row(); else tableLevels.add(textButton); }
About this code :
I first sets the Table that will contains the various TextButtons. With the line
tableLevels.defaults().width(Gdx.graphics.getWidth()/10).height(Gdx.graphics.getWidth()/10).space(Gdx.graphics.getWidth()/60);
I set the height and width of the buttons, and the spacing between each button.
Then I create an array in which I will store the buttons. This array will be important to interact with the buttons.
And finally, with a for loop I create the TextButtons and arrange them in rows of 5 buttons. For that, I add each buttons to the Table, and every five buttons, I add the button to the Table and create a new row, with the lines :
if((i + 1)%5 == 0) tableLevels.add(textButton).row();
With this code, you obtain this level selection table :
Note in my code the GameConstants.NUMBER_OF_LEVEL, is a number I stored in the GameConstants.java. For now I set this number to 15, but when I see how much work I have to do before the end of the jam, I guess it will be 10 levels or less for the jam version of this game.
Creation of the "Back" button
So now, I want to have a "back" button, to return to the main menu screen if I want to.
Thus I create the back button :
backButton = new TextButton("<", textButtonStyle); backButton.setWidth(Gdx.graphics.getWidth()/10); backButton.setHeight(Gdx.graphics.getWidth()/10);
And I want this to look good, I want the "back" button to be aligned with the table. For that, Actors have a very useful function, that is localToStageCoordinates. If I want the back button to be aligned to the left of the table, I need to know the coordinate of left side of a button in the first column. I'll get this coordinate with this line :
levels.get(0).localToStageCoordinates(new Vector2(0,0))
I take the 1st button, that I stored in the array levels, and I ask to translate Stage coordinate of its origin (new Vector2(0,0)) to the world system.
I also want my "back" button to be at the bottom of the table, and I want it to use the same spacing as the spacing between the buttons of the table. Thus, I set the position of the "back" button with this code :
backButton.setX(levels.get(0).localToStageCoordinates(new Vector2(0,0)).x); backButton.setY(levels.get(levels.size - 1).localToStageCoordinates(new Vector2(0,0)).y - backButton.getHeight() - Gdx.graphics.getWidth()/60);
And you obtain this screen :
hu... wait... what's this bullshit ?
The back button is in the middle of the table.
OK, here is the important part. If you want to translate the coordinate a button in the table to the world coordinate, you first need to add the table to the stage, draw it, and the get the coordinate.
In pseudo-code, you need to do that in the creator():
//Create buttons and put them in the tableLevels <span class="redactor-invisible-space">stage.addActor(tableLevels); stage.draw(); <span class="redactor-invisible-space"> <span class="redactor-invisible-space">//Create the "back" button and set its position stage.addActor(backButton);<span class="redactor-invisible-space"></span></span></span></span>
And now you've got this nice screen :
Differentiating between completed levels and not complete levels
Now we want the player to be able to see which levels he has already done.
There are many ways to deal with that.
The bad solution
We could only create the buttons corresponding to the levels completed and the first next level to complete : If the player already completed levels 1 and 3, we could create a table containing the buttons 1, 2 and 3. Thus the player will know that the last button displayed correspond to the level he has to play. This solution will create inconsistency in the displaying of the table :
The good solutions
There are several way to make this look well. You could create a 2 TextButtonStyles, one for the locked levels, and one for the unlocked levels. This way you could display the buttons with different colors (for example) according on the locked/unlocked state of the level.
The solution I chose is to completely hide the button corresponding to the locked levels with this code, at the end of the creator() :
for(int i = 0; i < levels.size; i++){ if((i + 1) > Data.getLevel()){ levels.get(i).setTouchable(Touchable.disabled); levels.get(i).setVisible(false); } }
I check if the number of the button is greater than the unlock level number that I saved in the Preferences file "Data". I yes, I set the button invisible and untouchable.
And here is the result :
Then you only have to create a Label to display the "Chose a level" title to obtain the screen displayed in the gif, at the beginning of this post.