Lack of Updates

A little more than a week ago, I was at home and started having chest pains.  The pains would no go away, so I went to the emergency room and they found a blood clot in my heart.  The operation to add the stent went quickly and it seemed like I was only in the operating room for less than 30 minutes.  After resting in the hospital for three days, I was allowed to leave and return home which was a week ago from today.  Each day I’m feeling stronger, and I’ll be back at my full time job very soon.

I’m taking a break from game development for now.  I think sitting around on my butt in front of the computer three days every week on my off days could have played a role in my heart attack.  I also need to get outside and exercise more.  I’m also improving my diet by eating less fast food and more fruits and vegetables, since I need to cut my cholesterol in about half.  My cardiologist said that I was the youngest person he had ever treated that does not smoke, drink alcohol, or do drugs.  He could not determine any one factor which caused it, but it was more like a one in a million chance thing that happened.  However, doing the right things like eating well and exercising will help lower the chances of it happening again.

Reorganizing Displays

One problem that continued to remain was the two different game states for the two display types in the game.  Those two display states are for the 2D sprite based view and the 3d model based view.  These two views shared the same data model, which is a reference to the game world.  However, having two game screen classes still led to some redundant code.  Both Screen states inherited from the ResistorKit.Screen class, which means that the control methods (stick movements and button presses) had to be handled in both Screen classes.  Therefore all of the controls were duplicated in both screens.  Additionally, other things not related to the display code also had to be duplicated, such as the sound effects.

Therefore, I modified the code so that there is only one GameScreen class.  This “new”class has two instance variables, one for the each display type, which are the GameScreen2D and GameScreen3D.  I should have probably renamed those to “Display” instead of “Screen”, since “Screen” implies a state in my game.  I could have also created a “Display” superclass for those two classes, but I thought that would have been overkill, especially since probably only one display method will ever be used in the final game.  I separated the actual drawing code for each display into its respective class.  The screen to be displayed is based on an instance variable in the GameScreen class which is set to an enum value that represents the currently active display type.  This prevents having to keep track of the display state in the main game class, which was the inefficient original approach that I took.

This also solves a long standing problem when exiting the menu screen.  Since the menu screen did not keep track of what screen was before it, the game always returned the player to the sprite based view even when the player was using the 3D model based view.  With the single display class, the player is always returned to the one screen state, which correctly displays the game screen based on the current display method.

I also have the GameScreen overlay displayed in the main GameScreen class, since the overlay should be identical for both the 2D and 3D views.

The only control difference between the 2D and 3D display is that the 3D display allows control of moving the camera when the Right Trigger is held.  That is the only display specific code that needs to be updated in the GameScreen class, and I will fix that in the near future.


screen106
screen107

I came across a new problem since adding my Jukebox class, which is an AccessViolationException when the program is ended.  This problem was reported in a thread on the AppHub forums, but a definite solution was never reported.  To see if it would help, I added a “Copy for Windows” of the ResistorKit library, and I added a reference in the BlastingBits for Windows project to the ResistorKit for Windows DLL.  However, I still occasionally see this error.

Jukebox

I thought I would implement something relatively simple tonight, so I decided to work on audio.  I already have two songs that play for the title screen and level screen, but the logic is built into my main game class which isn’t ideal.

For this game, I decided to take a new approach with the music.  Instead of manually starting and stopping songs when needed, I decided to assign a Song to each Screen class.  When the current Screen is changed, then the music is changed to match that screen.  I may have to make some exceptions, for instance in the case of a boss battle.  The player would still be on the GameScreen instance, but the music would need to change.

To implement this, I added a new Jukebox class to my ResistorKit library.  This will hold the references to all songs and sound effects.  Songs and sound effects are still loaded in the LoadContent method of the main game class, but after each has loaded it is added to the Jukebox object using the addSong and AddSoundEffect methods that I created.  The one drawback is that each Screen needs a reference to the Jukebox.  I can set the Jukebox in the current screen on each call to Update, but I will need to double check in the Screen to ensure that the Jukebox reference is not null before calling any methods on it.  I also created an instance variable in the Jukebox class to keep track of the currently playing Song.  The Song is only changed if the current song instance variable is changed, since there may be multiple screens with the same Song.  Overall, I like this method much better because it keeps the references to all audio objects in one class.  The beauty of this is that a Song identifier only has to be set for a Screen once, and then the music for that screen is automatically played whenever that screen becomes active.

In my main game class, I created an enum called GameSongs which holds identifiers for all of the Songs.  This is much cleaner than all of the int constants that I have been using.  I will want to go back and convert my Texture2D constant int identifiers to enums as well.  The only problem is that my Jukebox class in ResistorKit is not aware of the enum in my game.  I’d rather not put the enum or a reference to it in my library, because that would prevent other projects with different song identifiers from using the library.  I was able to solve this problem by casting the enum identifier to an int when calling the addSong method on the Jukebox object.

After adding the Jukebox to the game and making the necessary updates, I was able to use it to play the sound files.  One issue that I noticed was that since the Attract screen is displayed first, the setCurrentScreen method never gets called since it does not transition from another screen state, so the music wasn’t playing.  As a quick fix, I set the next screen state to the Attract screen in the constructor of the Attract screen, just so that the setCurrentScreen method gets called when it is first displayed.  This change made the music play correctly.  Since the Title Screen has the same Song, the music continued to play without breaking during the transition from the Attract screen to the Title screen which is what I wanted.

screen104

Finally, I pulled one of the sound effects from Resistor to use for the gun.  I just needed a temporary sound effect to use to see if the play method for sound effects in Jukebox is working.  I have to say, the Windows Media Player for Windows 8 is really horrible, because it is full screen with no way to change the size.  The Windows 8 music interface forces you to look at a bunch of advertisements from musicians I’ve never heard of and musicians that I really don’t like.  Fortunately, installing Audacity is a really fast and simple process.

screen105

One thing that is easy to forget is to set the Jukebox object in the Screen class to protected, so that the objects that subclass the Screen class can use the Jukebox object.  Fortunately, this only has to be set in the library, so the Jukebox will automatically be accessible to any implemented subclass.  Also, it is necessary to set the enum in the main game class to public so that any implemented Screen subclass can reference the sound effect identifiers.  However, the enum does not need to be set to static or constant.

After making these changes, the gun sound effect plays correctly when pressing the fire button.  However, the sound effect would play even if the player does not have a gun equipped and a projectile is not shot.  I would rather not put the sound effect playing code into the model.  I noticed that I already had a LifeTime variable defined in the projectile class, which keeps track of how many frames the projectile has lived.  Therefore, I just added a getter method for that variable, and I play the sound effect if the LifeTime variable is one (first frame).  I moved the code to play the sound from the button press method to the loop that draws the projectiles, and now it only plays the sound if a projectile is shot.  Having the sound play on the first projectile frame will give me the ability to play different sounds based on the projectile type (fire, ice, et cetera), since the projectile is already instantiated.