Marshalling Game Commands
It is a capital mistake to theorize before one has data. Insensibly, one begins to twist facts to suit theories, instead of theories to suit facts.
– Arthur Conan Doyle, Sherlock Holmes
A first step to allow the players to set their input settings is to be able to save the key bindings map to a file on the hard drive and to load those commands back into the map when the game starts.
Data Paths
In Windows, there are three recommended storage locations that application should use:
-
The local application data folder (FOLDERID_LocalAppData) is a file system directory that serves as the data repository for local (non — roaming) applications, i.e. it should be used for data that is specific to the user, the application, and the machine / hardware the application is running on.
-
The roaming application data folder (FOLDERID_RoamingAppData) is a file system directory for data specific to the user and the application, but shared across machines and different hardware.
-
The per machine application data folder (FOLDERID_ProgramData) is a file system directory for data specific to the application and the machine / hardware the application is running on, but independent of the user.
Knowing this, we will store the key configuration file in the local app data folder.
Microsoft recommends the following subdirectory structure to avoid clashes with other applications: ManufacturerName\ApplicationName\ApplicationVersion. The following function retrieves the paths to the above folders and creates the appropriate sub folders. We have talked about how to do this in a previous tutorial already:
Boost
To actually save and load the data, we will make use of the boost library. I regularly use boost in my professional (mathematical) applications and, frankly, its existence made me life a lot easier.
Boost is a set of libraries for C++ that provides support for a multitude of tasks and structures, such as linear algebra, pseudorandom number generation, multithreading, image processing, regular expressions, unit testing, and, important for this tutorial, serialization. All in all, the boost library contains over eighty individual libraries.
Most of the Boost libraries are licensed under the Boost Software Licence, designed to allow Boost to be used with both free and proprietary software projects. Many of Boost’s founders are on the C++ standards committee, and several Boost libraries have been accepted for incorporation into both the C++ Technical Report 1 and the C++11 standard.
You can download boost from here. Make sure to also add the additional library and include paths in your Visual Studio project.
Boost Serialization
In the context of data storage, serialization is the process of translating data structures or objects into a format that can be stored, for example, in a file or memory buffer, or transmitted, for example, across a network, and reconstructed later.
When the file, for example, is read from the hard disk, according to the serialization format, it can be used to create a semantically identical clone of the original object.
This process of storing an object is also called marshalling. The opposite operation, extracting a data structure from a series of bytes, is called deserialization, or unmarshalling.
Boost offers marshalling and unmarshalling via the boost serialization libary.
To use the boost serialization library, we simply add the following headers to our input handler source file:
I won’t go into the details of how marshalling works (not that I really have a lot of knowledge about that anyway), but using it is easy enough.
First, in the header file, we specify what data we want to have serialized:
As you can see, all we have to do is to declare the boost access class as a friend class, to allow the serialization to access private members, and then we define what data to serialize inside the serialize method. The & means input and output, i.e. when we save the data, it reads as
And when we load the data, it reads as:
And that’s it already — almost.
To actually save and load the data, we have to add two little functions to the InputHandler class:
Saving the data to the hard drive is completely easy now:
We simply loop through each command in the key map and write its data to a boost text archive linked to the file on the hard disk. Easy!
Restoring the game commands from the data file is equally easy, but unfortunately, there is a memory leak I can’t seem to fix just yet, maybe there is a bug in the serialization library, the destructor of the singleton constructed when unmarshalling the objects is never called. But here is the function:
The function is easy enough, we open the data file and read the BindInfo and GameCommands and put them back into the key map.
On initialization, all we have to do is to set up the default key maps, should no data file exist, everything else is automatic:
This tutorial was rather short, and we did not explain much, but at least we can now load and save game controls, as we had desired!
You can download the source code from here.
In the next tutorial, we will learn how to add a game menu to let the user choose their key bindings.
References
(in alphabetic order)
- Boost
- Microsoft Developer Network (MSDN)
- Tricks of the Windows Game Programming Gurus, by André LaMothe
- Wikipedia