Level Up

Tile Editor Agony

Started using the Tiled tile editor to create levels for the game, because I thought that was the editor I used for Legend of Tux.  I created a simple sprite sheet which contained the tiles on one layer, and the batteries and LEDs on another layer.  I found that I was only able to export my maps in a very limited number of formats.  It’s sad that this tile editor can’t output a simple indexed array of tiles.  I’m really not in the mood to write a parser for any of these formats, so I went back to the Legend of Tux wiki and found that I actually used Mappy last time.  Therefore, I downloaded Mappy and recreated my levels with that tool.

 

Mappyland

Mappy will not load PNG spritesheets unless two DLLs are included, so I had to download those file separately from the Mappy website.  Apparently there is a now bug with the “export all layers” functionality, so each layer has to be exported individually or else you will get an array filled with zeros.  What a pain!  Unfortunately, they don’t provide a binary download for the previous Mappy versions, and it’s not on SourceForge so a previous version isn’t archived for download.  The author even says on the website that 1.4 is a beta, so why can’t the last stable release still be downloaded?

 

Make sure to set the color depth to 16-bit when creating the map, or else the sprite sheet will not load and Mappy will complain.  As shown in the sprite sheet above, batteries start at index 10, and LEDs start at index 20.  I can get the Elex value of the LED or battery by modding (%) by 10, which really isn’t scalable past 10, so this may need to be reworked later.  This sprite sheet is just used for creating the level arrays, so I was sloppy when placing the numbers.  In the actual game, the numbers are programmatically placed on the objects.

I created getter methods in the LevelDefinition class to return the background tile array and object array.  Then I have a method in the GameLevel class which converts the integer arrays to actual objects (GamePieceBattery, GamePieceLight, etc).  Using the Mappy exporter, I was able to acquire the static array data definitions, which I pasted into my LevelDefinition class.  Wrote simple if/else statements to return the correct array for the level, but this could be changed to a switch/case statement (if C Sharp has those… I don’t know, and I didn’t feel like looking it up, since if/else does the job).

Next Level

Added instance variable to the main ResistorGame class to track the current level.  I’ve been trying to keep instance variables out of this class except for the media files.  When the GAMEWIN state is enabled, the current level instance variable is incremented.  If the current level variable is greater than the maximum number of levels (currently hardcoded to 5), then it gets set back to zero.  For the  LevelSelectScreen, the class could return a level index, and the ResistorGame class can use that value to set the current level instance variable.

One problem I’ve noticed is that the cursor defaults to cell 0,0 at the start of each level, which may be off the actual game board, now that the shape of the levels are custom defined.  I may need to add an additional object to the level definition which is the starting position of the cursor.  Additionally, all levels are using the same value thresholds for the ranks, which will need to be fixed later.  The S rank for luminosity should be easy to calculate (the sum of the bust values of all the LEDs).  As for the time and pieces used rank, I’ll probably just play through the levels a few times, and use my best scores for S rank, then use some sort of bell curve function to determine the thresholds for the A, B, and C ranks.

 

Loose Ends (Fix later)

Here’s just a few additional things that need to be fixed.

Currently, there is a display issue if the wires connect to the resistor from the sides.   The wires need to be removed from the resistor sprites, then just simply display a standard wire which will make the proper connections, then display the resistor core on top of it.

I haven’t decided if I should let the player move the cursor off the board cells, and just prevent the user from placing a piece on a non-board space… or should the player only be allowed to move the cursor on game board spaces.  If the player is allowed to move the cursor off of game board spaces,  then the player shouldn’t be allowed to lay pieces on those empty spaces.

I may allow the player to continually lay wires as long as the confirm button is held down, because currently the player has to keep alternating between pressing the direction and the confirm button to lay continuous pieces, which feels jerky.

The LED values can still fall below zero if enough resistors are used.  Need to set the bottom limit to zero for these.

It’s Time for a Change

Bust Condition Handled

Added code to detect if an LED has busted, which makes the game transition to the GAMEOVER state.  Added a GameOverScreen class to handle the display of the game over state.  Need to determine if I should give a warning to the player if the wire connected to the light is higher than its bust value, and allow the player to put a resistor there before the light has filled to avoid losing the stage.  Currently, once the light starts filling it is locked to that value, which doesn’t give the player a chance to fix their mistake.

Will add a meter to the lower right corner to display the Elex flow value of the currently selected cell.

Time Variables Added

I was able to get the current game time using the TotalGameTime.TotalMilliseconds property of the GameTime object that is passed to the update method.  However, I had to update all the update methods of all classes that extend Screen to accept GameTime as a parameter.  Created three new instance variables to the GameLevel class for holding the level start time, the current time, and the end time.  The end time is now displayed on the game win screen.

Level Definition

Created LevelDefinition class to hold the definition of the layout of each level along with the requirements for each piece/time/luminosity rank.  Created arrays of size 3 for holding each grade threshold.  Index 0 is for the S rank, index 1 is for A rank, 2 is for B rank, and all greater values are assigned C rank.

Fixed the getPieceCount method that returns the Pieces Used end level statistic to not count the LED and battery pieces, but only wires and resistors.

Added methods to the LevelDefinition class to take a piece count, luminosity value, or time and it will return the grade rank for each of those values.  The grade ranks are now displayed on the game win screen.  Using yellow for S, blue for A, green for B, and red for C.

Just thought I would reiterate the fact that I’m trying to make a fun game that is as scientifically accurate as possible, instead of trying to make a scientific simulation as fun as possible.

Batteries not Included

Fill Adjacent Modified

I slightly modified the method for calculating when to start filling adjacent pieces.  Before, when a piece went from unfilled to filled, then it would check to see if it had any unfilled neighbors, and begin filling those.  Now, on every update it loops through all unfilled pieces, sees if those have any filled neighbors, and then begins filling if it has a filled neighbor.  This fixes the problem of not filling a wire if it is placed to a neighbor that has already been filled.  A piece will now begin filling instantly if it is placed next to a filled wire.

Since it is now impossible for the flow to ever stop, then only end game conditions now are when 1) all lights are filled or 2)  one of the lights bust.  Limiting the number of end game conditions to two outcomes is a good thing in my opinion.

Batteries Added

Created a GamePieceBattery class, which replaces the need to manually start filling the first wire from the level startup code.  Batteries automatically start filling without being connected to a filled piece.  Batteries also have a constant Elex value, and they do not take the Elex value from surrounding wires.  Could let the player have a limited number of batteries (just one for the earlier stages) and let the player place the battery on the board.  There could also be only special  cells where batteries can be placed on the board.  One thing to think about is if a wire is already filled and a battery is placed next to it with a higher Elex value, then does the wire take the new Elex value of the battery or start refilling?  Removed all starting cell variables from the GameLevel class, since it is now handled by the battery.  Also removed the level fill wait value, since the battery will automatically filling on its own.

Win State

Added a STATE_GAMEWIN state to the main ResistorGame class, so all of the end level logic, display, and music can be handled in that state.  Much easier than making a bunch of special cases in the STATE_GAMELOOP state.  Created a simple victory fanfare theme, which is played after the player completes a stage.  Got bit by not calling SpriteBatch.begin()/end() again.  Need to find a way to run in debug mode under Windows, so I don’t have to spend as much time trying to figure out the cause of game crashes.  I’ve also added a winning victory fanfare melody, but I’m not as happy with it as my title theme or level theme.  It needs some work, or it needs to be scrapped all together.

Screen Abstract Class

Decided to start working on the title screen, to give the player a way to gracefully exit the game without having to press the default Back button.  I realized that the title screen will be using the same button press handlers and drawing methods as the GameLevel class, so I created a Screen abstract class which defines all of the button press and drawing methods as abstract methods.  The GameLevel class has been changed to GameLevelScreen which now subclasses Screen, and I added the override keyword to all the implemented methods.

I’m going to try a new approach for passing controls between screens in the game.  In Java games that I’ve written in the past, I would have to pass a reference of the main class to the specific screen class.  This was really messy, so this time I’m going to make the screen class report the next screen to display through a getter method, eliminating the need to pass and keep track of a reference of ResistorGame in the TitleScreen and GameLevelScreen classes.  I added a protected variable in the Screen class to keep track of the next screen and a method called getNextState.  This method returns -1 to stay on the same screen or a positive integer to move to a different screen, which are the same states defined in the ResistorGame class.  For instance, when the confirm button is pressed on the title screen, it sets the next state variable to the constant for the GAMELOOP state, and then the next call to update in the ResistorGame class will call the getNextState on the TitleScreen object and then appropriately set the state to make the GameLevelScreen the active screen.  By doing this, I was able to take the state logic mess out of the ResistorGame class and I now just have a currentScreen object of type Screen that holds a reference to the current Screen object, so the button press and display methods are just called on currentScreen, and through polymorphism the appropriate implementation of those methods are called based on the subclass.  If I spent some extra time on it, I could probably eliminate the state variable out of the ResistorGame class entirely, and just rely solely on the class type of the currentScreen object.

The title screen has been modified to display three options: New Game, Level Select, and Quit.  The Back button has now been disabled, and the user must select Quit from the main menu to quit the game.

The Level Select currently just allows the user to select a stage level between 1 and 9 using up and down button presses.  For now it doesn’t actually change levels since there is only one level defined.