Monogame game settings












0















I'm developing a platformer using C# and monogame as a fun project to improve my skills. I want to add support for settings like audio, video, controls and more but I don't know the best way to do so.



I plan on having a XML file that stores all settings kind of like this:



<Settings>
<Audio>
<masterVolume>100</masterVolume>
<musicVolume>40</musicVolume>
<sfxVolume>90</sfxVolume>
</Audio>
<Video>
<Resolution>
<width>1920</width>
<height>1080</height>
</Resolution>
</Video>
<Controls>
<forward>W</forward>
<back>S</back>
<left>A</left>
<right>D</right>
</Controls>
</Settings>


My plan was to use a Settings class that has static variables for audio, video and controls etc that are divided into separate classes so that I can access them through Settings.Audio.MasterVolume or Settings.Controls.Forward.
I want to load the settings into these classes from the XML using Linq and I want to save the settings to the XML file when they are changed by the user.



I know that singletons can be used as well but as far as I can tell from the research I've done it has too many drawbacks. Is that true?



Is this a good way to do this or is there a better way that allows me to access the settings throughout the project without having everything static?



Thanks in advance!










share|improve this question

























  • The main problem with using singletons is "global static state". The solution you've described is exactly that "a Settings class that has static variables for audio, video and controls". Just to be clear, a pure static method is fine. A global constant is fine and games are all about managing state but combining all 3 in this way can cause issues.

    – craftworkgames
    Jan 2 at 22:56
















0















I'm developing a platformer using C# and monogame as a fun project to improve my skills. I want to add support for settings like audio, video, controls and more but I don't know the best way to do so.



I plan on having a XML file that stores all settings kind of like this:



<Settings>
<Audio>
<masterVolume>100</masterVolume>
<musicVolume>40</musicVolume>
<sfxVolume>90</sfxVolume>
</Audio>
<Video>
<Resolution>
<width>1920</width>
<height>1080</height>
</Resolution>
</Video>
<Controls>
<forward>W</forward>
<back>S</back>
<left>A</left>
<right>D</right>
</Controls>
</Settings>


My plan was to use a Settings class that has static variables for audio, video and controls etc that are divided into separate classes so that I can access them through Settings.Audio.MasterVolume or Settings.Controls.Forward.
I want to load the settings into these classes from the XML using Linq and I want to save the settings to the XML file when they are changed by the user.



I know that singletons can be used as well but as far as I can tell from the research I've done it has too many drawbacks. Is that true?



Is this a good way to do this or is there a better way that allows me to access the settings throughout the project without having everything static?



Thanks in advance!










share|improve this question

























  • The main problem with using singletons is "global static state". The solution you've described is exactly that "a Settings class that has static variables for audio, video and controls". Just to be clear, a pure static method is fine. A global constant is fine and games are all about managing state but combining all 3 in this way can cause issues.

    – craftworkgames
    Jan 2 at 22:56














0












0








0








I'm developing a platformer using C# and monogame as a fun project to improve my skills. I want to add support for settings like audio, video, controls and more but I don't know the best way to do so.



I plan on having a XML file that stores all settings kind of like this:



<Settings>
<Audio>
<masterVolume>100</masterVolume>
<musicVolume>40</musicVolume>
<sfxVolume>90</sfxVolume>
</Audio>
<Video>
<Resolution>
<width>1920</width>
<height>1080</height>
</Resolution>
</Video>
<Controls>
<forward>W</forward>
<back>S</back>
<left>A</left>
<right>D</right>
</Controls>
</Settings>


My plan was to use a Settings class that has static variables for audio, video and controls etc that are divided into separate classes so that I can access them through Settings.Audio.MasterVolume or Settings.Controls.Forward.
I want to load the settings into these classes from the XML using Linq and I want to save the settings to the XML file when they are changed by the user.



I know that singletons can be used as well but as far as I can tell from the research I've done it has too many drawbacks. Is that true?



Is this a good way to do this or is there a better way that allows me to access the settings throughout the project without having everything static?



Thanks in advance!










share|improve this question
















I'm developing a platformer using C# and monogame as a fun project to improve my skills. I want to add support for settings like audio, video, controls and more but I don't know the best way to do so.



I plan on having a XML file that stores all settings kind of like this:



<Settings>
<Audio>
<masterVolume>100</masterVolume>
<musicVolume>40</musicVolume>
<sfxVolume>90</sfxVolume>
</Audio>
<Video>
<Resolution>
<width>1920</width>
<height>1080</height>
</Resolution>
</Video>
<Controls>
<forward>W</forward>
<back>S</back>
<left>A</left>
<right>D</right>
</Controls>
</Settings>


My plan was to use a Settings class that has static variables for audio, video and controls etc that are divided into separate classes so that I can access them through Settings.Audio.MasterVolume or Settings.Controls.Forward.
I want to load the settings into these classes from the XML using Linq and I want to save the settings to the XML file when they are changed by the user.



I know that singletons can be used as well but as far as I can tell from the research I've done it has too many drawbacks. Is that true?



Is this a good way to do this or is there a better way that allows me to access the settings throughout the project without having everything static?



Thanks in advance!







c# xml linq linq-to-xml monogame






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 1 at 16:33







TS1997

















asked Jan 1 at 16:21









TS1997TS1997

237




237













  • The main problem with using singletons is "global static state". The solution you've described is exactly that "a Settings class that has static variables for audio, video and controls". Just to be clear, a pure static method is fine. A global constant is fine and games are all about managing state but combining all 3 in this way can cause issues.

    – craftworkgames
    Jan 2 at 22:56



















  • The main problem with using singletons is "global static state". The solution you've described is exactly that "a Settings class that has static variables for audio, video and controls". Just to be clear, a pure static method is fine. A global constant is fine and games are all about managing state but combining all 3 in this way can cause issues.

    – craftworkgames
    Jan 2 at 22:56

















The main problem with using singletons is "global static state". The solution you've described is exactly that "a Settings class that has static variables for audio, video and controls". Just to be clear, a pure static method is fine. A global constant is fine and games are all about managing state but combining all 3 in this way can cause issues.

– craftworkgames
Jan 2 at 22:56





The main problem with using singletons is "global static state". The solution you've described is exactly that "a Settings class that has static variables for audio, video and controls". Just to be clear, a pure static method is fine. A global constant is fine and games are all about managing state but combining all 3 in this way can cause issues.

– craftworkgames
Jan 2 at 22:56












2 Answers
2






active

oldest

votes


















1














Your method works. However, you limit the re-usage of your class.



If you would describe MyClass to others, would you say that the method being used to read the configuration parameters is essential for MyClass? In other words: would most code of your class be meaningless if the configuration parameters wouldn't be read from a configuration file, but for instance from a CSV-file, or from the internet, or whatever method?



You'll probably say no: most code of my class could be reused if the configuration parameters were to be provided differently.



So why limit your class to a class that can only work if it reads the configuration parameters from a configuration file?



I guess that you currently have something like:



static class ConfigurationSettings
{
public static int LeftControl => ...
public static int RighControl => ...
}

class MyClass
{
// MyClass uses configuration settings:
public int LeftControl => ConfigurationSettings.LeftControl;
public int RightControl => ConfigurationSettings.RightControl;

...
}


You can't instantiate two objects of MyClass, each with their own set of configuration parameters. You can't create a MyClass object that uses a different method of providing configuration values.



One of the use cases I quite often need this is when unit testing: I want a quick way to be able to change the configuration settings without having to change the configuration file of the unit test project.



An easy way to allow users of your class to provide different methods for setting is to create an interface with the setting and provide a constructor with this interface:



interface IMySettings
{
int LeftControl {get;}
int RightControl {get;}
...
}

class ConfigurationSettings : IMySettings
{
// ConfigurationSettings reads settings from the configuration file
}

class MyClass
{
// default constructor use the configuration file via ConfigurationSettings:
public MyClass() : this (new ConfigurationSettings())
{
}

// extra constructor for those who don't want to use configuration file
public MyClass(IMySettings settings)
{
this.Settings = settings;
}

protected readonly IMySettings settings;

// MyClass uses settings:
public int LeftControl => this.settings.LeftControl;
public int RightControl => this.settings.RightControl;
}


Users who want to use the settings from the configuration file can use the default constructors; uses who want specific settings use the alternative constructor. This alternative constructor is also used if you want two different MyClass objects, each with their own settings.



At first glance it seems that with minimal changes you can still use the configuration file. However, to be able to implement the interface, the class that reads the configuration file (MyClass) can't be static.



However, you were right: there is only one configuration file, hence there should be only one instance of the class that reads from the configuration file: create a singleton.



In my experience, classes that represent a configuration, is one of the often used reasons to use a singleton instead of a static class






share|improve this answer































    1














    In my game projects I always use some static classes (and/or variables) to hold information that is valid through the whole game.
    This might come in handy especially for audio settings if you want to be able to change the volume and so on from different points of the game.
    This does not necessarily only include user settings. Thinkig of lowering the background music when some character is speaking.



    long story short:
    I would go for the static approach. But take care not to over exceed it.






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997024%2fmonogame-game-settings%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      Your method works. However, you limit the re-usage of your class.



      If you would describe MyClass to others, would you say that the method being used to read the configuration parameters is essential for MyClass? In other words: would most code of your class be meaningless if the configuration parameters wouldn't be read from a configuration file, but for instance from a CSV-file, or from the internet, or whatever method?



      You'll probably say no: most code of my class could be reused if the configuration parameters were to be provided differently.



      So why limit your class to a class that can only work if it reads the configuration parameters from a configuration file?



      I guess that you currently have something like:



      static class ConfigurationSettings
      {
      public static int LeftControl => ...
      public static int RighControl => ...
      }

      class MyClass
      {
      // MyClass uses configuration settings:
      public int LeftControl => ConfigurationSettings.LeftControl;
      public int RightControl => ConfigurationSettings.RightControl;

      ...
      }


      You can't instantiate two objects of MyClass, each with their own set of configuration parameters. You can't create a MyClass object that uses a different method of providing configuration values.



      One of the use cases I quite often need this is when unit testing: I want a quick way to be able to change the configuration settings without having to change the configuration file of the unit test project.



      An easy way to allow users of your class to provide different methods for setting is to create an interface with the setting and provide a constructor with this interface:



      interface IMySettings
      {
      int LeftControl {get;}
      int RightControl {get;}
      ...
      }

      class ConfigurationSettings : IMySettings
      {
      // ConfigurationSettings reads settings from the configuration file
      }

      class MyClass
      {
      // default constructor use the configuration file via ConfigurationSettings:
      public MyClass() : this (new ConfigurationSettings())
      {
      }

      // extra constructor for those who don't want to use configuration file
      public MyClass(IMySettings settings)
      {
      this.Settings = settings;
      }

      protected readonly IMySettings settings;

      // MyClass uses settings:
      public int LeftControl => this.settings.LeftControl;
      public int RightControl => this.settings.RightControl;
      }


      Users who want to use the settings from the configuration file can use the default constructors; uses who want specific settings use the alternative constructor. This alternative constructor is also used if you want two different MyClass objects, each with their own settings.



      At first glance it seems that with minimal changes you can still use the configuration file. However, to be able to implement the interface, the class that reads the configuration file (MyClass) can't be static.



      However, you were right: there is only one configuration file, hence there should be only one instance of the class that reads from the configuration file: create a singleton.



      In my experience, classes that represent a configuration, is one of the often used reasons to use a singleton instead of a static class






      share|improve this answer




























        1














        Your method works. However, you limit the re-usage of your class.



        If you would describe MyClass to others, would you say that the method being used to read the configuration parameters is essential for MyClass? In other words: would most code of your class be meaningless if the configuration parameters wouldn't be read from a configuration file, but for instance from a CSV-file, or from the internet, or whatever method?



        You'll probably say no: most code of my class could be reused if the configuration parameters were to be provided differently.



        So why limit your class to a class that can only work if it reads the configuration parameters from a configuration file?



        I guess that you currently have something like:



        static class ConfigurationSettings
        {
        public static int LeftControl => ...
        public static int RighControl => ...
        }

        class MyClass
        {
        // MyClass uses configuration settings:
        public int LeftControl => ConfigurationSettings.LeftControl;
        public int RightControl => ConfigurationSettings.RightControl;

        ...
        }


        You can't instantiate two objects of MyClass, each with their own set of configuration parameters. You can't create a MyClass object that uses a different method of providing configuration values.



        One of the use cases I quite often need this is when unit testing: I want a quick way to be able to change the configuration settings without having to change the configuration file of the unit test project.



        An easy way to allow users of your class to provide different methods for setting is to create an interface with the setting and provide a constructor with this interface:



        interface IMySettings
        {
        int LeftControl {get;}
        int RightControl {get;}
        ...
        }

        class ConfigurationSettings : IMySettings
        {
        // ConfigurationSettings reads settings from the configuration file
        }

        class MyClass
        {
        // default constructor use the configuration file via ConfigurationSettings:
        public MyClass() : this (new ConfigurationSettings())
        {
        }

        // extra constructor for those who don't want to use configuration file
        public MyClass(IMySettings settings)
        {
        this.Settings = settings;
        }

        protected readonly IMySettings settings;

        // MyClass uses settings:
        public int LeftControl => this.settings.LeftControl;
        public int RightControl => this.settings.RightControl;
        }


        Users who want to use the settings from the configuration file can use the default constructors; uses who want specific settings use the alternative constructor. This alternative constructor is also used if you want two different MyClass objects, each with their own settings.



        At first glance it seems that with minimal changes you can still use the configuration file. However, to be able to implement the interface, the class that reads the configuration file (MyClass) can't be static.



        However, you were right: there is only one configuration file, hence there should be only one instance of the class that reads from the configuration file: create a singleton.



        In my experience, classes that represent a configuration, is one of the often used reasons to use a singleton instead of a static class






        share|improve this answer


























          1












          1








          1







          Your method works. However, you limit the re-usage of your class.



          If you would describe MyClass to others, would you say that the method being used to read the configuration parameters is essential for MyClass? In other words: would most code of your class be meaningless if the configuration parameters wouldn't be read from a configuration file, but for instance from a CSV-file, or from the internet, or whatever method?



          You'll probably say no: most code of my class could be reused if the configuration parameters were to be provided differently.



          So why limit your class to a class that can only work if it reads the configuration parameters from a configuration file?



          I guess that you currently have something like:



          static class ConfigurationSettings
          {
          public static int LeftControl => ...
          public static int RighControl => ...
          }

          class MyClass
          {
          // MyClass uses configuration settings:
          public int LeftControl => ConfigurationSettings.LeftControl;
          public int RightControl => ConfigurationSettings.RightControl;

          ...
          }


          You can't instantiate two objects of MyClass, each with their own set of configuration parameters. You can't create a MyClass object that uses a different method of providing configuration values.



          One of the use cases I quite often need this is when unit testing: I want a quick way to be able to change the configuration settings without having to change the configuration file of the unit test project.



          An easy way to allow users of your class to provide different methods for setting is to create an interface with the setting and provide a constructor with this interface:



          interface IMySettings
          {
          int LeftControl {get;}
          int RightControl {get;}
          ...
          }

          class ConfigurationSettings : IMySettings
          {
          // ConfigurationSettings reads settings from the configuration file
          }

          class MyClass
          {
          // default constructor use the configuration file via ConfigurationSettings:
          public MyClass() : this (new ConfigurationSettings())
          {
          }

          // extra constructor for those who don't want to use configuration file
          public MyClass(IMySettings settings)
          {
          this.Settings = settings;
          }

          protected readonly IMySettings settings;

          // MyClass uses settings:
          public int LeftControl => this.settings.LeftControl;
          public int RightControl => this.settings.RightControl;
          }


          Users who want to use the settings from the configuration file can use the default constructors; uses who want specific settings use the alternative constructor. This alternative constructor is also used if you want two different MyClass objects, each with their own settings.



          At first glance it seems that with minimal changes you can still use the configuration file. However, to be able to implement the interface, the class that reads the configuration file (MyClass) can't be static.



          However, you were right: there is only one configuration file, hence there should be only one instance of the class that reads from the configuration file: create a singleton.



          In my experience, classes that represent a configuration, is one of the often used reasons to use a singleton instead of a static class






          share|improve this answer













          Your method works. However, you limit the re-usage of your class.



          If you would describe MyClass to others, would you say that the method being used to read the configuration parameters is essential for MyClass? In other words: would most code of your class be meaningless if the configuration parameters wouldn't be read from a configuration file, but for instance from a CSV-file, or from the internet, or whatever method?



          You'll probably say no: most code of my class could be reused if the configuration parameters were to be provided differently.



          So why limit your class to a class that can only work if it reads the configuration parameters from a configuration file?



          I guess that you currently have something like:



          static class ConfigurationSettings
          {
          public static int LeftControl => ...
          public static int RighControl => ...
          }

          class MyClass
          {
          // MyClass uses configuration settings:
          public int LeftControl => ConfigurationSettings.LeftControl;
          public int RightControl => ConfigurationSettings.RightControl;

          ...
          }


          You can't instantiate two objects of MyClass, each with their own set of configuration parameters. You can't create a MyClass object that uses a different method of providing configuration values.



          One of the use cases I quite often need this is when unit testing: I want a quick way to be able to change the configuration settings without having to change the configuration file of the unit test project.



          An easy way to allow users of your class to provide different methods for setting is to create an interface with the setting and provide a constructor with this interface:



          interface IMySettings
          {
          int LeftControl {get;}
          int RightControl {get;}
          ...
          }

          class ConfigurationSettings : IMySettings
          {
          // ConfigurationSettings reads settings from the configuration file
          }

          class MyClass
          {
          // default constructor use the configuration file via ConfigurationSettings:
          public MyClass() : this (new ConfigurationSettings())
          {
          }

          // extra constructor for those who don't want to use configuration file
          public MyClass(IMySettings settings)
          {
          this.Settings = settings;
          }

          protected readonly IMySettings settings;

          // MyClass uses settings:
          public int LeftControl => this.settings.LeftControl;
          public int RightControl => this.settings.RightControl;
          }


          Users who want to use the settings from the configuration file can use the default constructors; uses who want specific settings use the alternative constructor. This alternative constructor is also used if you want two different MyClass objects, each with their own settings.



          At first glance it seems that with minimal changes you can still use the configuration file. However, to be able to implement the interface, the class that reads the configuration file (MyClass) can't be static.



          However, you were right: there is only one configuration file, hence there should be only one instance of the class that reads from the configuration file: create a singleton.



          In my experience, classes that represent a configuration, is one of the often used reasons to use a singleton instead of a static class







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 2 at 8:18









          Harald CoppoolseHarald Coppoolse

          12.9k12964




          12.9k12964

























              1














              In my game projects I always use some static classes (and/or variables) to hold information that is valid through the whole game.
              This might come in handy especially for audio settings if you want to be able to change the volume and so on from different points of the game.
              This does not necessarily only include user settings. Thinkig of lowering the background music when some character is speaking.



              long story short:
              I would go for the static approach. But take care not to over exceed it.






              share|improve this answer




























                1














                In my game projects I always use some static classes (and/or variables) to hold information that is valid through the whole game.
                This might come in handy especially for audio settings if you want to be able to change the volume and so on from different points of the game.
                This does not necessarily only include user settings. Thinkig of lowering the background music when some character is speaking.



                long story short:
                I would go for the static approach. But take care not to over exceed it.






                share|improve this answer


























                  1












                  1








                  1







                  In my game projects I always use some static classes (and/or variables) to hold information that is valid through the whole game.
                  This might come in handy especially for audio settings if you want to be able to change the volume and so on from different points of the game.
                  This does not necessarily only include user settings. Thinkig of lowering the background music when some character is speaking.



                  long story short:
                  I would go for the static approach. But take care not to over exceed it.






                  share|improve this answer













                  In my game projects I always use some static classes (and/or variables) to hold information that is valid through the whole game.
                  This might come in handy especially for audio settings if you want to be able to change the volume and so on from different points of the game.
                  This does not necessarily only include user settings. Thinkig of lowering the background music when some character is speaking.



                  long story short:
                  I would go for the static approach. But take care not to over exceed it.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 2 at 8:05









                  Pavel SlesingerPavel Slesinger

                  32918




                  32918






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997024%2fmonogame-game-settings%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      MongoDB - Not Authorized To Execute Command

                      in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

                      How to fix TextFormField cause rebuild widget in Flutter