Doing My Part

August 22, 2012

I really haven’t done any development for Resistor in over a month, so I decided to go ahead and put it into the Peer Review process on the Microsoft Creator’s Club site.  I see it as my way of doing my part in adding to the fine collection of interactive video entertainment titles in the XBox Indie Games marketplace.

With over 400 entries into the Dream Build Play competition, I don’t think I have a chance at being one of the finalists.  If the competition was based purely on uniqueness I think my game would fare better.  However as in real life, looks do matter and my game is about as plain as it gets.

Overall, I would be thrilled if my game could make $100 on the marketplace, which would equal the original investment that I made for the Creator’s Club membership.  Unfortunately, I’ve heard that most XBLIGs don’t make anything, so my goal is probably a bit of a stretch.

Below are the changes I made to the game after putting it through playtest a few weeks ago.

Tutorial System

Tutorial tips were added to teach new players the rules of the games.  These tips should not display as long as the player is doing well in the game.  The tutorial tip system keeps track of which tutorial tips the player has seen, and it doesn’t display a tip that the player has already seen.  However, once the player quits the game the tip flags are reset.  A tip is displayed if the player falls to the B rank in any of the three categories.  Also, if the player doesn’t use the appropriate resistor and gets a Game Over, then a tip will display when the level is started again stating that resistors should be used to reduce the flow value.

More Graphical Improvements

Made the spinning light sprite display while the LEDs are filling, using the scale parameter.

The rank letters at the end of the stage now zoom into position.

Changed the A, B, and C rank colors to use lighter shades of blue, green, and red.  The status icons in the lower right portion of the screen now change with their respective rank values.  I also modified the real time rank value of the luminosity category, so that it calculates the rank based upon the maximum possible luminosity of activated LEDs (instead of all LEDs).  This way, the player starts out with an S rank in luminosity and the rank is only lowered if they connect a wire with a lower flow needed by the LED.

Audio Changes

Used Audacity to make the ding sound when an LED is activated lower based on the difference between the maximum flow value and the current flow value.  The rank grades at the end of the stages use these modified sounds as well.


Home Stretch

May 18, 2012

Small Glitch

Fixed an issue that actually only occurs on one frame of the fill animation.  This happens when a wire goes to the “filled” state, but the neighbor wires have not yet begun filling.  Since the wire is filled, it doesn’t make any connections to neighbors that don’t have the same flow value.  Since the neighbor doesn’t have a flow value initialized yet (assuming it is defaulted to zero), it’s flow value doesn’t not match the flow value of the wire that just completed filling, therefore it will not be connected.  However, on the next frame the empty wire will begin filling, using  the flow value of the filled wire which will make it connected again.  This flicker was quick, but it was noticeable.  Therefore, I added special checks for this case, and made the wires connected in this one frame case.

The Night the Music Died

Used the Pause method on the MediaPlayer to pause the music when the pause screen is active.  Unfortunately, there is no MediaPlayer property to determine if the music is paused, so I had to create a new variable to track if the music was paused.  I simply want to resume if the GameLevelScreen is coming from the pause state, but I want it to start playing anew if it is coming from the title screen or level select.  Also had to set this pause variable to false if the user quit from the pause menu to the main menu, otherwise it would still think that the music just needs to be resumed.  When that happened, it would try to Resume the title screen music when the level started.  The title screen music would just continue to play during the level, and the level music would never start.

Centering Text

Overloaded the drawRaisedString method, so that it now takes six arguments with the last being a boolean signifying if the text should be horizontally centered at the point passed as a parameter.  The drawing code is now in the six parameter method, and the five parameter method of the same name just calls the six parameter method with the boolean set to false.  This will keep me from having to change every line of code in the game that uses the drawRaisedString method.  Plus, I just add “true” as an extra parameter for the text that does need to be centered.

Background Colors

Fixed the background colors for level 4 (yellow) and 5 (green) so those aren’t so bright.  Also created a standard method in the LevelDefinition class that returns the background color, since that color was previously being determined in two different locations.  Updated those locations to use this new standard method.

Added columns of stars in the background which scroll if the player achieves the star rank (S Rank in all three categories at once).  Stars in the even number columns scroll in the opposite direction of the stars in the odd number columns.  I used Inkscape to make the stars since there was no easy way to make a star shape in Gimp.  Then, I just took a screenshot (PrintScreen button) and pasted into Gimp, because copy-and-paste from InkScape to Gimp doesn’t work.  I then used the fuzzy select tool to select the star, set the selected star region to white, inverted the select and set the remaining to transparent (after adding transparency to the layer).

 

One thing that I do like about C Sharp is that after some research, I found that structures (such as Vector2) can be passed by either value or reference.  At first I found it passed by value, when I tried to pass my star position to the getStarPosition method, but it left the position at the original value after the method completed.  Then I found that just using the ref keyword in the method parameter list and in the method call will make it pass the Vector2 by reference, which allows the method to modify the original Vector2 passed to the method.  This was necessary for me to make a trailing star effect, for the blinking stars that circle the results.  After trying a few different things, I thought the best look was two groups of three stars that circled the result screen.  Also, the yellow alternates between the three stars in each group.

More Effects

I also added a glow effect, so that the wire transitioned from yellow to white (four different shades) every 15 frames.  I didn’t like how it looked, so I just set it back to solid yellow.

Using the sprite scale parameter, I was able to make a light layover expand inside of the LED circle.  This gives the appearance that the LED is filling up.  The default color for an LED was set to light gray (previously white) to give a better contrast between the expanding yellow inner circle sprite and the rest of the LED sprite.


Spamming not Allowed

April 29, 2012

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).


Week 3 Wrap-Up

April 24, 2012

(The capture format was set to FLV in XSplit (instead of MP4) with the highest recording quality (20), but there is still some initial distortion in the video after it was loaded to YouTube)

Touch Up Work in Audacity

Touched up the sound effects in Audacity, to give them the appropriate lengths to be used in the game.  For the buzzer, I trimmed down the hair clipper sound effect to 0.25 seconds.  Not sure why, but I wasn’t able to find a crop function in Audacity.  Therefore, I just had to select the portion of the clip I want to use, copy, then paste it in a new Audacity window.  Next I started looking for a sound to use for the main menu.  The buzzers and rings were too harsh of a sound, so I loaded up my shaken Pepto Bismol sound effect.  After cropping out everything except for one shake of the bottle, I realized that this makes a great menu selection sound.  It actually sounds like muddy boots on a wooden walkway.  For the wire filling sound, I slimmed down the running water clip.  The original sound is a little harsh, so I raised the pitch by 265.  The ice sounds were a little flat, so I increased the speed by 200.  It now sounded like an old fashioned money changer.  With this new sound, I added 2 seconds of silence at the end, and then applied the echo effect (delay 0.5 seconds, decay 0.5).  The spoons sounded good without any modification except for cropping out the rest of the noise.  I’ll use this as either a menu sound or a rank display sound.  The spoon hitting the glass made a good sound, but there was a lot of background static noise in the sound capture.  I used Audacity’s noise removal tool to fix it, but it seems to have raised the pitch of the sound as well.  It still sounded okay, so I’ll probably use that as the sound when an LED is lit.  The CO meter made a nice beeping sound, but it was really loud so I used the normalize effect.  I’m not sure where I will use this sound, but I’ll go ahead and import it into the project for now.  This gives me a total of eight sound effects, which should be enough to get me started.

  

Apparently, the volume of the MediaPlayer object uses a value between 0 and 1, and I incorrectly assumed that it was 0 to 100.  For some reason, the sound when it is played on the PC is much louder than it is on the XBox.  Maybe the XBox (or my television) has sound normalization so it isn’t loud like on the PC.  Setting the MediaPlayer volume to 0.1 makes it sound about right on the PC, which I believe is one tenth of the volume.  I will have to test it on the XBox later to see if that makes it too low to hear on the console.  If it does, then I may have to write some platform specific code to handle the differences between the PC and console.

Ran into a bit of an issue with playing sound effects.  In order to play a sound effect, the current screen must have a handle to the MediaPlayer object, which is only available in the main ResistorGame class.  I don’t want to have to pass a MediaPlayer object to each function on each screen that may want to play a sound effect.  I think I’ll make the sound effects like the screen transition, where the screen will implement a public method which will report whether or not the screen needs a sound effect played.  Then the Resistor game class will query that method on each update, and then play any sound effect that is requested to be played.  I usually don’t write code this way, but I think it may make things cleaner in the end, especially if I decide to write a media handler class.  I created a method called getRequestedSoundEffect in the Screen class and added a protected instance variable called iSoundEffect.  If the ResistorGame calls that method and it returns a value greater than -1, then it will play the sound effect at that index in the sound effect array.  Thefore, any of the subclassed Screen just have to set the iSoundEffect variable to any of the sound effect constants defined in the ResistorGame class.  Amazingly, this worked perfectly the first time that I tested it.  I also discovered that MediaPlayer is not required for playing SoundEffect objects (Songs objects only), but it was good that I implemented it this way, otherwise I would have the same problem with passing the sound effect array around to all of the screens.  Just calling the Play method on the SoundEffect object itself will play the sound.  One drawback is that only one sound effect can be played for each update call, otherwise the previous sound effect(s) ID assigned to the iSoundEffect variable will be lost.  This may be a good thing, because there shouldn’t be too many sounds playing at the same time.  Once scenario that I can imagine is if two LEDs are lit at exactly the same time.  Just playing the sound effect once should be sufficient.

Using Audacity and a short tutorial from eHow, I was able to record my voice for the title screen which I gave a repeating robotic sound.  First, I used the Repeat Effect on the start of the audio clip.  Then I used the Delay Effect with Decay=10, Delay=0.01, and Echos=20.  I repeated that effect about 6 times.  I also made audio clips for “level complete”, “game over”, “S”, “A”, “B”, “C” and applied the same effects.

  

Level Selection Modification

I may have messed up by making the LevelDefinition instance a member of the GameLevel class instead of the ResistorGame class.  The ResistorGame class needs to pass the maximum number of levels to the LevelSelectScreen class.  The maximum number of levels is defined in the LevelDefinition object, so it has to get a reference of that object from GameLevelScreen which is a little messy.  I may have to rework this later.

Sound Effects Added to Game

After updating the game code, I now have sound effects for menu movement, menu selection, wire begins filling, light filled, and light busted.  I had to add an additional variable to keep track of light filled, since this property was never actually tracked.  I added that check to the game win check, since it was already looping through the lights on the board, so if the number of lit lights is greater than the number of lit lights on the previous check, then the lit sound effect is played.  I was happy with all the sound effects, except for the electricity one (originally water running from the faucet).  It still sounded to static-like, and it started to give me a headache after awhile.  Therefore, I replaced it with the phaser sound that I made (also from the water running) which has a much smoother sound.  I also had the Pepto Bismol sound (now named SE_PLOP in the constants) play on each menu movement and the spoon sound (SE_SPOON) played on the selection.  This didn’t sound right because the SE_PLOP was longer than SE_SPOON, so I just switched out the occurrences of those two sounds, which makes it sound much better.  The lit light and light busted sound effects sound great.  I may need some delay or an animation when a light is busted, because the light busted sound effect plays through the game over screen.

Special Cases

While playing the game, I noticed a special case that may need to be handled.  If a wire is placed next to two (or more) filled wires (or other pieces), I believe it just takes the Elex value of the first one in the if/elseif statement.  I should calculate the highest of all the neighbors, and assign the new wire the highest value of all the adjacent pieces.

Another thing that had been bothering me is that I thought that the time statistic was proportional to the pieces used statistic, which would make it somewhat redundant.  However, through testing I found that it is possible to get a S rank in time and a C rank in pieces by quickly spamming wire pieces.  This is a good thing, which prevents someone from getting the best possible grade by quickly spamming pieces.  The inverse is also true, where someone can get an S rank in pieces but a C rank in time.  Just take a long time laying down the pieces in the shortest path.

 



Amateur Foley Artist

April 22, 2012

Gathering Sound Effects

Now is a good time for me to start gathering sound effects for the game.  I could have went to one of the sites that offer free creative commons sounds effects and downloaded what I needed there, but one has to be careful to read the license for each sound effect to ensure that it is covered by a creative commons license that allows it to be included in a work that is sold for profit.  Right now, I’m just creating this game for the contest, but if the game is popular I would be willing to sell copies of it for money (sorry RMS).  I’m trying to make the development of this game as open as possible without sharing the source code, because I believe I read once that sharing source is not allowed by XBox Indie games.  I also didn’t want to make another credits screen, which would be filled up with URLs with links to sounds effects.

My iPod Touch was used for recording all of the sound effects as voice memos.  The sound quality isn’t the best, but it does the job.  I wouldn’t mind going back later and recapturing the sounds using a high quality recording system.  Using a tip that I found on the Internet, I was able to export all of the sound effects through iTunes directly into WAV (MP3 was also an option) so I can edit the sound effects in Audacity.  To change iTunes to export as WAV (default is AAC which is useless), there is a setting under Import CD that must be changed.

Now is the fun part of capturing sounds.  My clippers and hair trimmers were used to make buzzing sounds.  These can be used for error sounds.

 

Running water at full pressure almost sounds like electricity.  I doubt anyone would notice the difference, unless they read this post.  Futher modifications in Audacity will also give it a more electric sound.  This will probably be a constant sound that plays as wires are filling.   I think Audacity has an option for making an audio file seamless, so it can be looped multiple times without any breaks in the audio.

 

Ice makes a nice chrunching and breaking sound, without all the mess of breaking a real glass.  This will probably be the sound when an LED breaks.  I know it should probably be a burn out for fizzling sound, but I think the breaking sound will be more dramatic.

 

Two spoons were used to make a nice ringing sound.  The spoon hitting the glass makes a longer vibrating ringing sound.  These will probably be used as a confirmation sound effects.

   

A drawer slamming makes a good sound, which can be used for a cancel event.

 

The test on this CO detector makes a nice beeping sound.  I could imagine that sound being used as the ranks at the end of the level are displayed.

 

I’m not sure if this will make the final cut of sound effects in the game, but a shaken Pepto Bismol bottle makes a great liquid type sound.  I’ll probably find some way of working it in the game.

Background Images

While I was at it, I went ahead and used my iPod Touch to take picutres of an old sound card and network card that I had in storage.  After some touching up in Gimp, these should make great background images.

 

Minor Graphics and Input Fixes

Set the default cursor position for the level to 5,5 because it really bugged me that the cursor starts off the board on the first level in the upper left corner.  It also minimizes the distance that the cursor must move from the starting position to any other space.  The position of the game board has also been centered on the screen (SCREENWIDTH – (iTotalCols * CELL_SIZE)) / 2, (SCREENHEIGHT – (iTotalRows * CELL_SIZE)) / 2 = (640 – (10 * 32)) / 2, (480 – (10 *32)) / 2.  This is a very helpful formula that I’ve used for centering objects in many games.  Fortunately, I already defined a board offset variable as a Vector2, so I just needed to add that formula to that offset variable.

By simply adding one line of code, I was able to disable the ability to place a piece on a empty space.  I still allow the player to move the cursor to empty spaces, primarily due to the fact that the starting position of the cursor (5,5) may be in an empty space.  This happens on level 4 (donut level) where there is empty space in the middle of the board.

Fixed the resistor graphics so that it can be superimposed over the default wire images.  Increased the maximum pieces to 10 (1 + 9 resistors).  Now all resistors are selectable.  The currently selected piece has a red background.  Later, I will probably make only certain resistors available on each level.  For example, there’s really no point in having a 9 resistor on a level where the maximum battery and LED value is 2.  The selected piece can now be changed by using the left and right bumpers.

Now displaying the selectable pieces at the top of the screen, but I’ve got to be careful that it isn’t cut off on the television screen.  I think I remember reading that 20% of each side of the screen image is not displayed on the television.  Added right/left bumper pressed/released abstract methods to the Screen class, which made me implement it in all the Screen subclasses.  Added methods to increment and decrement the selected piece, which is called by the action button (X) press and the bumper button presses.

 

Fixed the GamePieceResistor class so that the Elex value can’t be lowered below zero.  LEDs can be activated with a zero value wire, but it won’t add any points to the total luminosity score at the end of the level.

Made minor modification to the level 3 board, so that the last two LEDs are placed further back on the game board.

The Level Select screen now takes the player to the selected level once the confirm button is pressed.

Changed the cancel button to set the selected piece to the wire (index 0).  The Back button now takes the player back to the main menu.  The Back button will probably be disabled, after I create a Pause menu.

Noticed an issue on the XBox 360 that doesn’t happen when running the game through the PC.  If I set the MediaPlayer sound to zero (for mute), then it must be set back to 100 for sound to play through the XBox again.  Just commenting out the line that set the sound volume to zero will still keep the sound muted.

Went through and manually played the five levels that I have so far, and used my score for the S ranks.  I just created values for the A, B, and C ranks, which seemed appropriate.  All these values are stored in arrays in the LevelDefinition class.  I updated the getPieceRank, getLuminosityRank, and getTimeRank methods to return the appropriate values based on the current level.  Forgot that I was passing the time as milliseconds, which took a little while to debug.  Dividing the time value by 1000 before passing it to the getTimeRank method fixed that problem.

Changed the message from “YOU WIN” to “LEVEL COMPLETE” after completing a level.

Removed the fill frame number from currently filling cells.


Let there be Light (and Sound)

April 11, 2012

Adding Music

Used Mario Paint Composer to create simple title music and stage music.  It really gives the game a classic feel, and it’s really easy to create great sounding tracks with the tool.  I spent about 30 minutes trying to record the audio from the desktop (tried Fraps, then tried connecting the audio jack output to the mic input), but I couldn’t get Audacity to record even though I saw activity from the mic input in the Control Panel sound control.  Finally, I just held my USB headset mic up against the PC speaker and recorded using Audacity.  The sound is a little muffled, but it does the job for now.  At first, I used Audacity export the music into MP3 format.  I did some research to see what what other formats XNA accepts, because I don’t want to risk the possibility of paying royalties for using MP3.

I’ve never had a formal class in music writing, but I was in the band for many years in high school, so this will be my first attempt at writing music for a game.   The GameBoy icon beeps make a nice sound, but I found that too many of them can get annoying, especially when the song is on a loop.  The GameBoys should be using sparingly, like sprinkles on a cupcake.  I found that the Piranha Plant, Coin, ShyGuy, and Boo make the most soothing sounds, so I’ll probably be using those the most.  On my stage 1 song, I have an intro and four melodies.  The intro has the most GameBoy beeps, then it is phased out in the later melodies.  Using the Arranger in Mario Paint Composer, the sequence I used looks like this:  Intro, Intro, Melody A, Melody A, Melody B (transition), Melody C, Melody C, Melody D, Melody D, Melody C, Melody D, Melody C, Melody D.

 

To be on the safe side, I went ahead and converted my raw music files to WAV using Audacity.  I can convert them to WMA later if needed.  I don’t want to run the risk of having to pay royalties by using the MP3 format.  One trick is that in the IDE you have to change the ContentProcessor of the WAV resource to Song, otherwise it will default to SoundEffect which will cause the program crash when it is played as a Song object.

Adding Lights/LEDs

Created the GamePieceLight class which subclasses the GamePiece class.  Currently, it just overrides the draw method, so that it draws a light (circle sprite) instead of a wire.  The lights are not playable pieces, meaning that the user can not place lights on the game board.  The lights are placed on the board at the start of the level.  Learned that you can’t just simply override a method by redefining it like in Java.  In order to override, the method in the superclass must be declared virtual, and the override keyword must be used when defining the method in the subclass.  After fixing those, I was able to add the light pieces by using the setPiece method in the constructor of the GameLevel class, for each light to be placed on the board.  The great thing about OO (object oriented) programming is that the light automatically inherits all of the properties of the GamePiece class, which was the basic wire.  Therefore, it automatically fills the adjacent wires just as a regular wire does, and its isFilled property is automatically set when the FILL_MAX value is reached.  In order to make these superclass instance variables accessible to the subclass, they must be declared protected instead of private.  This makes the variables visible to subclasses, but not visible to other classes.  Before the light is filled, I use White as the color parameter for drawing the light sprite.  Yellow is used as the color parameter when it is filled.  The maximum “bust” value for the light will be added later.

Adding Resistor Pieces

Added instance variables to the GameLevel class, which hold the currently selected piece and the maximum number of selectable pieces.  The current selected piece is initialized to zero (wire) and the maximum number of pieces is set to two.  In the future, I will just create a list or array of piece types, and derive the maximum value from the array length.  I am currently incrementing the selected piece value when the user presses the action button (default X).  If the selected piece value is greater than or equal to the number of pieces, then it is set back to zero.  In the future, I may have one button specifically for laying wires and another button for placing other pieces like resistors.  Changing the selected piece will also probably be handled by the shoulder buttons.  I have displayed the selected piece index on the game screen for now.  When the selected index is 1, then pressing the confirm button will lay down a 2-resistor.  I made the Elex variable in the superclass protected, so that I can subtract 2 from its value.  A method was created in the GamePiece called pieceFilled which is called when the piece’s fill value reaches the max value.  This method is overridden in the GamePieceResistor subclass, calling base.pieceFilled() first to set the filled boolean values in the superclass.  Then I subtract the Elex value in the sublcass, since that is specific to the GamePieceResistor subclass.  When the resistor is not filled, I use the Gray as the third color value in the blit method, giving the resistor a faded appearance.  When the resistor is filled, White is used as the color parameter which makes it appear brighter.  Currently, there is no check to see if the resistor will lower the Elex value below zero.  I could make it so that the flow stops when the flow gets to zero.

As the screenshot shows, the Elex value is lowered from 8 to 6 as it passes through the first resistor, because the 2-resistor lowers it by 2.  When it passes through the second resistor, it lowers again to 4.