SGDK Version 2 > General Discussion

FMod features in SGDK2

(1/3) > >>

Vincent:
Hi guys!  :)

I started integrating music in my game.  I'm using FMod, since it is pretty much the easiest way to do it.  I think it's great stuff.  Although there are some little things that I felt were lacking, I add them as I go and it really is going fine.

If I understand correctly, FMod provides the dll and FMod.cs.  I suppose bluemonkmn developped FModBase.cs to "wrap" the "wrapper".  It certainly works well and it is very easy to use.  LoadSound, PlaySound, StopSound and UnloadSound are simple enough.

For the music in my game, I wanted to make smooth transitions between each music.  So I added a system to manage the music, making sure that only one music plays at a time and, if there is a music change, the system does a fade-out of the previous music and a fade-in of the new music simultaneously.  I think it is less of a shock for the ears when you change a level or go into the menu.  I didn't implement this system for sound effects.

I'm also thinking to add controls in the options window to manage to SFX volume and music volume.

If anyone is interested in this, please let me know.  I'll send you my code.

Also, bluemonkmn, do you think it would be a good idea to implement these changes into a new version of FModBase.cs?  Or do you prefer to keep it as it is?

See ya!  ;D

bluemonkmn:
It would be a nice feature if it doesn't interfere with the existing operation and is included only as an option to the user.  In SGDK 1, the problem was that all music and sound effects would be forced to fade out when they wanted to stop and you had to do something complicated to make them stop abruptly, which seems wrong.  Did you simply add new functions and leave the existing functions as they were?   I suspect that your enhancements would be good to include in the standard fmodbase.cs.

Vincent:
Cool!

I didn't need to modify the existing FModBase functions.  I'll finish what I'm working on right now, then I'll extract the code and post it here.  It's not 100% clean, but I guess you can sort it out and take what you want.

Vincent:
Okay, here's some of the stuff that I've done.

I added this in the GameForm.cs so when the game loses focus, the music stops playing:

--- Code: ---//this part in the run function of GameForm:
            // Display is minimized or inactive, wait until it is restored
            Application.DoEvents();
            if (GameDisplay != null)
               GameDisplay.SwapBuffers();
//was replaced by:
            // Display is minimized or inactive, wait until it is restored
            Application.DoEvents();
            if (GameDisplay != null)
               GameDisplay.SwapBuffers();
            //don't play music if the game is paused
            if(CurrentMusic != null)
               CustomObjects.FMODBase.StopSound(CurrentMusic);           
            if(NextMusic != null)
               CustomObjects.FMODBase.StopSound(NextMusic);
            System.Threading.Thread.Sleep(0);
            continue;

//this part:
   OutputDebugInfo();

//was replaced by:
   CurrentFadeTime = ManageMusic(CurrentFadeTime);
   OutputDebugInfo();


--- End code ---

I could not add the previous code in a another file (partial class) but the next code I added in another file using the partial class, so this still goes into GameForm.cs


--- Code: ---public partial class GameForm : Form
{
   #region music extra stuff

   public const int FadeDuration = 120; //in frames
   public int CurrentFadeTime = FadeDuration;
   public const float MaxVolume = 0.60f;
   public CustomObjects.FMODBase CurrentMusic;
   public CustomObjects.FMODBase NextMusic;

   //this part is useful for my project only
   //It could be replaced by another function or completely dropped
   public CustomObjects.FMODBase GetMusicToPlay()
   {
      //Verify if music is forced
      if (Counter.ForceMusic.CurrentValue != 0)
      {
         switch(Counter.ForceMusic.CurrentValue)
         {
            case 1:
               return TermogentSwampsNormal.Value;
            case 2:
               return ElderGodLairNormal.Value;
            case 3:
               return VoradorMansionNormal.Value;
            case 4:
               return HumanCityNormal.Value;
            case 5:
               return VampireCitadelNormal.Value;
            case 6:
               return HyldenDimensionNormal.Value;
            case 7:
               return PillarsNosgothNormal.Value;
            case 8:
               return HyldenFortressNormal.Value;
            case 9:
               return MenuNormal.Value;
            case 10:
               return BossNormal.Value;
            case 11:
               return ElderGodNormal.Value;
            case 12:
               return IntroNormal.Value;
            default:
               return NoMusic.Value;
         }
      }
      else
      {
         //verify if in any menu
         if(OverlayMap is MiniMap_Map)
         {
            //not in menu so play level music
            switch(CurrentMap.GetType().Name.Substring(0, 2).ToUpper())
            {
               case "VM":
                  return VoradorMansionNormal.Value;
               case "TS":
                  return TermogentSwampsNormal.Value;
               case "EL":
                  return ElderGodLairNormal.Value;
               case "HC":
                  return HumanCityNormal.Value;
               case "HD":
                  return HyldenDimensionNormal.Value;
               case "VC":
                  return VampireCitadelNormal.Value;
               case "PN":
                  return PillarsNosgothNormal.Value;
               case "HF":
                  return HyldenFortressNormal.Value;
               default:
                  return null;
            }
         }
         else
         {
            //in menu so play menu music
            return MenuNormal.Value;
         }
      }
   }


   //this is the important part.  Plays the music and manages the fades
   public int ManageMusic(int CurrentFadeTime)
   {
      //Find the music to play
      CustomObjects.FMODBase Music = GetMusicToPlay();  //this part could be dropped and a custom function added to change the music or to pass it to this function
      if(Music != CurrentMusic && CurrentFadeTime == FadeDuration) //don't want to manage multiple fades at once
      {
         if(CurrentMusic == null)
            CurrentMusic = Music;
         else
            NextMusic = Music;
      }

      if(CurrentMusic != null)
      {
         //Assess music situation
         if((NextMusic != null) && (CurrentMusic != NextMusic) && (CurrentFadeTime == FadeDuration))
         {
            //we are changing the music
            CurrentFadeTime = 0;
         }

         //Assess fade situation
         if(CurrentFadeTime == FadeDuration)
         {
            //No fading right now, keep playing current music at full volume
            CurrentMusic.Volume = MaxVolume;
            FMODBase.PlaySound(CurrentMusic, SoundReplay.Continue);
         }
         else if(CurrentFadeTime == FadeDuration - 1)
         {
            //The fading is finishing, switch the musics and play the new current music at full volume
            FMODBase.StopSound(CurrentMusic);
            CurrentMusic = NextMusic;
            CurrentMusic.Volume = MaxVolume;
            FMODBase.PlaySound(CurrentMusic, SoundReplay.Continue);
            CurrentFadeTime++;
            NextMusic = null;
         }
         else
         {
            //A fading occurs
            //calculate the volume
            float FadeAmount = (MaxVolume * CurrentFadeTime) / FadeDuration;
            CurrentMusic.Volume = MaxVolume - FadeAmount;
            NextMusic.Volume = FadeAmount;
            FMODBase.PlaySound(CurrentMusic, SoundReplay.Continue);
            FMODBase.PlaySound(NextMusic, SoundReplay.Continue);
            CurrentFadeTime++;
         }
      }
      return CurrentFadeTime;
   }
}


--- End code ---

I also added a field in fmodbase.cs


--- Code: ---private float volume;

--- End code ---

And modified the Volume property like this


--- Code: ---//this part:
      // Override this member to override default volume.
      protected virtual float Volume
      {
         get
         {
            return 1.0f;
         }
      }

//was replaced by:
      public float Volume
      {
         get
         {
            return volume;
         }
         set
         {
            volume = value;
         }
      }

--- End code ---

//So, of course, I don't override the Volume properties in my music files anymore, but I still do for my sound effects.

It would be even better to add controls in the options menu to set a max volume to sound effects and a max volume to music rather than hardcoding it in GameForm like I did.

I will leave that to your more than able hands bluemonkmn.  I suppose you would also prefer to include all of this code into fmodbase.cs only, but I don't see how I could do that.  Since SGDK2 is your application, I'll let you see if any of this is of interest to you or not.

I hope it's not too messy!

Thanks bluemonkmn!

bluemonkmn:
I think the changes to GameForm should be different because you should be able to run projects without importing fmodbase.cs.  I think the currently proposed code will have an error if you try to run a project without importing fmodbase.cs.  My suggestion is to try to confine all the changes to fmodbase.cs.  Is there a way to hook into events raised from GameForm from FModBase.cs?  I will try to look into this when I get a chance if you don't get to it first.

Navigation

[0] Message Index

[#] Next page

Go to full version