We are nearing the home straight now for our game journey. We have come a long way and although it might not look that pretty the game functions pretty well. The next thing to do is program the score and the levels.
To keep track of the score I have written a class called the ScoreManager. The score manager’s responsibility is solely for keeping track of the score. It has a method to update the score which takes an IEnumerable of blocks found. The score then gets updated and an immutable score object is returned back. The score code is pretty straight forward. Scoring works by you get one point for each square you make within a block. If you make multiple blocks at the same time then you get a multiplier bonus of the amount of blocks you made simultaneously.
Another part of the game that is missing is levels. I have decided that you have to make a set amount of squares in blocks to advance the level. The LevelManager is a class that is designed to keep up with this. The logic for the level manager is a little more complex as it has to calculate which level that you are on based on the current score. As always it is fully unit tested. Actually when I first wrote the level manager and tests there was a subtle bug with the LevelManager when you got exactly the amount of squares that you required to get to the next level. This highlights again the importance of TDD. To fix this bug I wrote a test for it to reproduce the bug and sure enough the test failed. All I had to do then was fix the LevelManager to make the test pass, the bug was caused by a greater than inside an if instead of a greater than or equal to. The beauty of using TDD is that now this bug will never come back.
To get the score and level information on the screen I just had to make score and level implement the IDrawableItem interface. Then all I had to do was add an item drawer for the score and the level. The code automatically picked the rest up. This is the beauty of using factories to create classes and to do everything dynamically. If you had to write all of that code manually it would’ve meant updating several places of code to “know” about the new items. The code is completely decoupled and doesn’t have any knowledge of the items that it’s drawing.
To write the text on the screen I had to use a sprite font. As I am using mono game there are some nuances with how you have to do this as you have to target the xmb file (that is produced by building content) at the correct target framework. To do this for Windows all I have done is created a real XNA project solution, added a sprite font to the content and then built it. Then I have gone back to the rotation game solution and manually added the xmb file as a content file to the content directory of the game project. When the game gets ported to iPhone this process will have to be repeated except of course I will have to build it to target the correct framework.
One more thing that I wanted to point out in this post is that you really see the value of single responsibility principle when you decide to make changes to how the game works. When I got the game working I decided that rotating the whole axis as far as it could reach (to the edge of the board) was making the game too easy and not much phone. So I added another implementation of the ISquareSelector interface. This time instead of selecting squares right from the center to the nearest edge I created another class called SingleSquareSelector that only goes one square in each direction. All I had to do (after unit testing the class of course) was to switch the registration in the container to use the SingleSquareSelector and the behaviour changed. The beauty is that to switch back all I have to do is change the registration back. This really shows the value of having one class for one purpose.
I know I won’t win any awards for design but the gameplay is really getting there. You can get the game at this point at part17. If you are unsure of how to do this then you can check the rotation git details page.