Ambiguity

Multiple Wire Problem

Noticed a problem that doesn’t happen too often, but when it does it is really annoying.  This is when you place a wire (or resistor) next to two filled wires with different flow values.  For instance, if I place a wire where the blue square is in the first image below, then what flow value should the new wire get?  Should it be a 3 from the left wire or a 5 from the right wire?  Remember, this is my puzzle/arcadey game rules, and not a real simulation so I get to make up the rules.  Currently, it just uses the value of the first check in the if/elseif/else block.  However, this is ambiguous to the player, because the player can’t determine what the value of the wire placed will be.  That’s unless they’re clever enough to figure out that the cells are evaluated in a clockwise manner starting at the top.  So currently the new wire would get a value of 5 from the right wire.  However, if the wire were placed in the blue square in the second image, then the new wire would get a value of 3.  This was confusing me as I play tested the game, so I’m sure it would also confuse other players as well.

  

Therefore, in the checkStartFilling method in the GameLevelScreen class, I added a loop that calculates the highest value of all the adjacent cells, and uses that highest value for the new wire.  In the two images below, now placing a wire in the blue square will set the new wire’s value to 5 in both cases, since 5 is greater than 1.  It’s not realistic, but a least the player can clearly anticipate what the value will be now.

 

Connection Problem

This logically fixed the problem, but the display was still misleading, because it would make a complete loop with two different flow values in the loop.

 

To fix this problem, I updated the draw method in the GamePiece class to only make connections to wires with the same flow value.   The resistor wires are a little tricky, because it’s difficult to determine which wires carried the flow in and which ones carried the flow out.  Another visual distortion happened when two wires with different values were placed next to each other that only had one joining wire each.  Those appeared to connect since the default image for a wire with only one connection spanned all the way across the cell horizontally.  Therefore, I made wire images specifically for only one connection (N, E, S, W) on each side and an image for a no connection wire ( O ) to resolve this issue.  These new images provide a few pixels for a break padding, so that those wires don’t appear to be connected to pieces that they are not connected.  Now as shown the in the screen shot below, with the updated code and images the user can clearly see the flow through each of the wires, and there is no doubt that the value of the wire in the blue square is now 5.

Game Win Screen Updated

Moved the game win display code to the game win screen, to make it consistent with the other screens.  To to this, I had to pass the piece count, luminosity, and time values to the Game Win screen.  Additionally, I had to pass a reference to the level definition object, so that the rank values can be calculated.  I also added a win delay on the Game Level screen, so that there is a one second pause between the time when the last LED is activated and when the Game Win screen is displayed.

More Level Design

Created twenty new levels (21 to 40).  I purposely designed some of the levels to force the player to use the higher level resistors (2, 3, and 4).  I increase the highest level battery used by one for each ten levels.  One flaw that I’m making in level design is making it so that every tile must have a piece to clear the stage.  Technically, this is fine but the user will always get an S rank in pieces used.  Therefore, I should always include a few tiles that don’t have to be used, so that there is a chance for lower piece ranks.

 

During play testing, I noticed that one level didn’t have any tiles and only objects.  This was due to me exporting the wrong layer as the tile layer.  Going back and exporting the correct layer resolved this problem.

 

High Level Resistors

The player now starts out with only one selectable resistor (value 1).  Every 10 levels, the maximum selectable resistor increases by one.  This prevents the player from using a high level resistor to lower the initial wire to zero, which would allow the player to quickly complete the level.

(Gray video distortion fixed. Thanks to tip from SHADEE.)

Spamming not Allowed

Cooldowns

Made another gameplay change today.  The fact that the player could pick a high level resistor and spam it to quickly complete the level was really bothering me.  Thefore, I added an array in the GameLevelScreen class which holds the cooldown value for each selectable piece.  When the piece is dropped, the cooldown value for that piece is set to 2 seconds (120 frames).  That value is decreased by one on each update until it reaches zero, then the user may place that resistor again.  So now the user can still use all resistors, but it will take a really long time to complete the stage, which solves the problem of the player winning the stage quickly if all resistors are used.  Using all resistors will also not give the player the best luminosity score.  I could put in a limit on how many times each resistor can be used, but I think that would over-complicate things.

Active Screen

A new abstract method has been defined in the Screen class, which is setActiveScreen.  This is a method that I already had in the TitleScreen class, but I thought it should be included in all Screen classes.  This method is called whenever the Screen gets set as the currentScreen.  Initialization that needs to be done whenever the screen gets control (such as setting pause values) can be set in this method.  This was going to be necessary for both the GameWinScreen and GameOverScreen, so I thought it was best to have it as a common abstract method.  Those two screens now have a pause instance variable that is set to the wait time in the setActiveScreen method, which prevents the player from bypassing the screen until that pause value hits zero.  This will also allow me to just call setActiveScreen on the currentScreen object once when control is passed, and I won’t have to call that method specifically for each Screen subclass instance.  I already had a setCurrentScreen method defined in the Screen class, but it is not abstract and its job is to set the next screen state to -1.  I think having the setActiveScreen abstract method handle the subclass specific code is best for now.

Title Screen Completed

Added a new background image for the currently select main menu item.  Used Gimp to create a free selection shape on top of one of the computer card images.  Used the color tools to make the image grayscale, and then increased the brightness twice.  Then I applied the bevel filter twice, and drop shadow filter once.  Also gave the currently selected item ‘s font a green color, and changed the font to Motorwerk.  Unless there is a good reason to change it again, I’m considering the title screen done.

 Loose Ends

Made a slight modification to the level complete sound effect, so the pitch gradually raises through the sound clip.

Added delay when an LED busts before moving to the Game Over screen.  The LED is now filled with red when it is busted (could use a cool breaking graphical effect later).

Keep on Trucking

Laundry List

I’m getting the feeling that this is the point where a lot of my other game projects have died out.  A core game and fancy title graphics.  I have rarely taken the time to go back and add all the bells and whistles, such as sound effects and flashy graphical effects.  Plus, I’m really not a fan of level design.  It really feels arbitrary to me, but it does take expertise to make good levels in a puzzle style game.

Therefore, to keep myself on track I made a laundry list of the next things to complete in the game.  Some will require a little research since this is my first XNA game, such as saving the game status.

  • Hold Confirm button to keep placing wires
  • Zoom in for letters on title screen
  • Game over screen delay / graphics
  • Display level/stage before starting a level
  • Transitions between screens (such as fade out)
  • Show player ranks for stages on level select
  • Don’t allow levels that haven’t been completed to be selected on level select
  • More levels; different array sizes
  • Colored backgrounds for level screens
  • Save levels completed along with ranks
  • Render objects in Blender
  • Add graphics/sound effects on level complete screen
  • Keyboard controls so that others who don’t have XBox can play test

The first task I tackled was the hold confirm button to keep laying pieces.  This is a core gameplay change, so I felt it was most important.  Basically, I just required a new instance variable in the GameLevelScreen class, which tracks if the confirm button is being held down.  On each update, it checks to see if the button is held down, and if it is, then it tries to set a piece at the current cell.  Therefore, it is constantly trying to set a piece at the current cell (but can’t since no more than one piece can be assigned to a cell), so there may be room for optimization here later.  Anyway, the controls feel MUCH better and less jerky now with this in place.  I think I need to put a cooldown on resistor usage, because the player can select a resistor and just spam it all over the board to quickly complete the level.  It’s okay for the wires to not have a cooldown, because spamming wires will likely cause the player to bust an LED and lose.

Continuing to resolve the tasks that required the most programming first, I decided to implement the record display on the level select screen.  To do this, I had to create a PlayerRecords class, which holds the records of each completed level.  This object is populated with the level ranks after each level is completed.  The level select screen uses this to display the ranks for each level.  Currently, if a level is replayed, then the ranks are overwritten each time the level is completed, which should be fixed later.  For now, the level select screen just shows the integer values associated with each rank, but these will be changed to the rank graphics in the near future.  Plus, I will need to implement a way to scroll through the higher levels.

 

In the level select screenshot above, I played through level 1 getting ranks C, S, B.  Then I selected level 5 and got ranks S, C, B.  Noticed an error which caused the game to crash.  After completing the fifth level (level index 4), it would actually go to level index 5 (which didn’t exist but used the layout of level index 0 as default).  When that level was completed, it would go to level index 1 (level 2) next.  So it appeared that it was looping back to level 1 (level index 0), but it really wasn’t.  Therefore, when it tried to save the statistics for level index 5, it reported an error because I only allocated the array in the PlayerRecords class to hold values for five levels (level index 0 through 4).  I went ahead and added the level index to the game level display, but I will probably create a method to convert that index to a stage number.

New Levels

Next I started working on adding new levels.  Before churning out new levels in the Mappy tile editor, I wanted to make sure that new levels can be easily added to the game.  I added two new List variables to the LevelDefinition class, to hold all of the tile maps and object maps.  This will eliminate the if/elseif statement mess that was in the getter methods that return the object arrays, tile arrays, and rank arrays for the currently selected level.  I really need to create a Map object to hold those values for each level, but I don’t want to have too many classes right now, so I don’t think it’s worth the time and effort to rework that code now.  The only benefit is that it would eliminate potential problems of managing five parallel Lists, but instead it would just be one list of Map objects.  I added additional checks in each of the methods that return ranks in the LevelDefinition class, so that it doesn’t try to index a position in one of the rank arrays if the level parameter is greater than the size of one of the rank lists.  This shouldn’t ever happen unless the NUM_LEVELS constant in the LevelDefition class is set to a value higher than the size of the rank Lists.  If this happens in the object or tile array getter methods, then it just returns the array information for level 1 (index 0).  I didn’t add any checks to see if the object and tile arrays were completely empty, because I thought that would be obsessive.  I may have to think about the ability to add an expansion to the game later, which may conflict with the PlayerRecords definition.

I used the Mappy tile editor to create more levels for the game, bringing the total to 20.  I wrote a small Ruby script to loop through all the files in the map export directory, and it does some minor modifications to prepare those arrays to be used in the game, then it writes out the results so that I have all the arrays in one file instead of 40 different files.  Made another minor modification to the rank code, which was preventing it from saving the ranks for the first stage (index 0).

  

 

More Title Screen Updates

Got side tracked and spent about an hour getting the letters on the title screen to zoom in.  After all letters are displayed, then there is a 5 second pause, then the letters zoom in again.   I’m not sure how much more time I will want to spend on the title screen.  Gameplay is most important, but the title screen is the first thing that people see.  I definitely wanted to display the title screen as soon as possible.  I am so sick of seeing idiotic Game Studio Logos on startup that just waste my time.

So now I think I just need to re-do the font for the menu items to match the title font, and then have a new menu item selected image (the default tile has been there for a while).  I’m thinking of just using another portion of the computer card images that I already have, and maybe apply a brighter white color and a drop shadow.