Rank Updates

Rank Modifications

Modified the way that ranks are calculated at the end of a level.  Before, I had S, A, and B values defined for each of the three categories (pieces, luminosity, time) for each level.  I’ve realized that I will not have enough time to come up with all of those values for even the 50 stages that I currently have.  Therefore, I’m just going to define values for the S ranks.  Then, I will derive the A, B, and C values for pieces by adding 1, 2, and 3 to the S rank.  The same goes for the luminosity value, but decreasing the value by 1, 2, and 3.  For time, I will set a base S rank time, and then calculate the A, B, C ranks by adding 2 seconds for each lower rank level.

Fixed an issue with records being wiped when New Game is selected after the game is executed again.  This is because the constructor of the PlayerRecords class was initializing all of the array values to -1.  Now the save data is loaded once when the game is started, after the rank arrays are initialized in the constructor.

The rank values now gradually appear on the game win screen.  Currently, the ding sound effect is played when each value appears.  The game is already heavy on the voice work, so I thought the letter voice work was excessive.  I may use Audacity later to modify the ding sound, so it is different for each rank or new best ranks.

Added boolean variables and methods to track if the new ranks obtained for the level are better than the previous ranks obtained for the level.  This wasn’t pretty, because the GameWinScreen doesn’t have references to the GameLevelScreen or PlayerRecords classes, so it has to keep local variables to track if each rank is the best.  The GameWinScreen then uses those boolean variables to display if the rank is a new best if appropriate.

Level Number Display

Created a static method in the Level Definition class, which takes an integer level number and converts that number into a string level name.  It divides the level number by 10 and adds 1 to get the first number, and then takes the modulo of the level number by 10 plus 1 to get the second number.  For instance, level 25 becomes “3 – 6”.  Level 10 becomes “2 – 1”.  This is the value that will be displayed to the player on the various game screens.

  

Even Software Developers Need a Break Sometimes

Burnout

Took a coding break on Sunday, since I was starting to feel the burnout.  Participating in a programming competition on Saturday really pushed me to the limit as far as writing code goes.  I had done little game playing in April, so I’ve dropped a few places in the XBox gamerscore leaderboards on TrueAchievements.  Therefore, I picked up an easy game from Redbox and scored a quick 700 gamerscore for a quick rank boost.  I also played a few Indie and XBLA games to check out some of the currently independent developed games.

Level Design

I was able to do a little level design, but that was about it.  One thing I’ve got to watch out for is placing two LEDs next to each other, because the GameLight class is derived from the GamePiece class, which means an LED will automatically start filling other adjacent LEDs.  This prevents the player from using resistors to change the flow values for the adjacent LEDs.  This could lead to an automatic bust in some cases.  Noticed that I also need to display the level/stage number on the level complete screen, which would also help me with recording my scores for the rank information.  There are now 50 total levels to play in the game.

  

Did some more playtesting of the game through the XBox, and began recording my scores, which will be used for the ranks.  I want the S Rank to be difficult to obtain, but I’ve got to ensure that it is possible to get the values that I define for the S Ranks.

Level Select Screen Glitch

Noticed an issue on the Level Select screen where the cursor keeps going back to index 0  from index 1 when the down button is pressed.  Not sure what is causing this, but I will check to see if the pause value is getting set properly in the setActiveScreen method.  Pressing up seems to fix it so that down properly moves the cursor down the screen.  Looked at the code, and I realized that it happens when the user holds up and then presses the confirm button on the Level Select screen (to select a level) before releasing up.  The boolean that tracks if up is pressed was not getting set to false, because the Level Select screen never saw the up direction being released.  Setting that boolean to false in the setActiveScreen method of the Level Select screen fixed the problem.


Wipe Out

Level Select

Began working on improving the Level Select screen.  First, I needed a method to convert the numeric ranks to a character or string.  I really didn’t know where was the best place to put this method, so I included it as a static method in the LevelDefinition class, so that other classes won’t need a reference to a LevelDefinition object to get the string representing the rank (S, A, B, or C).  And yes, you can spell three letter dirty words using the rank letters.

Next, I got the vertical scrolling working on the level select screen.  Defined variables  to track the number of levels displayed on the screen, the offset level (minimum level displayed), and the currently selected index.  The selected level is the offset level plus the selected index, which is a derived value calculated in a method.  In the screenshot below, the offset level is 3, the selected index is 4, so the selected level is 7.  I may go back later and add another static method to convert the level numbers to more meaningful values, such as “1-1” for level 0, “1-2” for level 1, and “2-1” for level 10.  If the user presses down and the currently selected index is the maximum number of levels displayed on the screen, then the level offset is increased by one (unless the maximum number of levels are already displayed).  If the user presses up and the currently select index is zero, then the level offset is decreased by one (unless the level offset is already zero).  Simple up and down arrows are displayed when the minimum level index can be increased or decrased, letting the player know that there are more levels to be displayed.

 

Saving Data

I was able to get simple saving done (just strings) a few days ago, but this really didn’t actually save any of the game data.  So I went back and created a method in the PlayerRecords class which serializes all of the record data.  Basically, it just writes out one line for each level.  The line first contains a Y/N value indicating if the level was completed, then three pipe delimited values containing the integer value for the ranks achieved for that level.  Conversely, I created a parse data method which takes a string acquired by my file load method, and uses splits to read data out of each line and out of each pipe delimited value.  These values are then stored into the data arrays.  I also created a reset method, which clears all data by writing an empty string to the save data file, and then loads that data file.

Clearing Data

I also wanted to give the player the ability to delete all their records, in case they want to start fresh.  This was accomplished by calling the reset method when the Back button was pressed on the Level Select screen.  However, this made it too easy for the player to press Back and wipe all their data.  The player could have just wanted to go back to the title screen and didn’t know which button to press.  Therefore, I created a mini-state within the level select class which prompts the user to confirm if they really want to delete all the records.  The default is (obviously) “no”, so the user has to consciously press up to change the value to “yes” and then press the confirm button.  The one thing that confused me was that the selected index for the “yes” value was zero, since it was the choice on top and “no” has a value of one.  This goes completely against my programming instincts, where one is a positive or true value, and zero is a negative or false value.  The one exception being the return values from main in a C program, where zero is success and a positive value is an error return code.  This functionality could have been extracted out into its own Confirmation Dialog class, but I didn’t feel like taking the time to do the required setup to get that working, since it would not fit my standard Screen display model.  So instead, there is just a boolean in the Level Select class which determines if it should display the confirmation screen and process the events on the confirmation screen.  It’s too bad that I can’t use my menu code that I wrote in Ruby for TetraCity, because it is a very solid menu’ing system that I wrote.

 

So now it looks like I am almost completely done with the core functionality of the entire game.  The only thing that I know that needs to be changed is that when the user replays a level, a rank should only be overwritten if the user actually gets a better rank than the one currently achieved.  It should also let the player know if they have beaten one of their previous ranks.  Currently, the rank data for the level will be overwritten regardless.  I could add an options menu to change the sound volume and button layout, but I think there is very little value in doing that compared to the actual benefit of having those options.  If the sound is too loud, then that is the reason why television remote controls have volume controls.  Nobody ever really looks at credits screens, so I don’t see the point in making one.  None of the classic games ever had credit screens, aside from the credits that play at the end of the game.

The final two main tasks that remain to be completed are the improved graphics and finishing designing the remaining levels.  Each level requires the array data to be generated in Mappy, and then I have to manually add the rank requirement data for each stage.  Finally, I could add an ending screen which displays once the player completes all levels.