Sprint 2 Results: Universal Windows Platform (UWP) Build of Tunnel Lords
This sprint was productive with completing a clean install of Windows 10 on my development computer, re-organizing Tunnel Lords to support multiple platform builds (UWP and generic Windows), getting a partial build of Tunnel Lords working within UWP, and completing some class refactoring.
Additionally, I spent a lot of time reading on Microsoft’s UWP documentation and started on programming a nice game tutorial screen for Turnnel Lords, which is still far from complete.
After convincing my wife that I needed a new computer, we ended up just upgrading my current development computer to Windows 10. While I'd really like a shiny new machine, this one has a lot of life left and still works fast and reliably for my uses. So we saved the money. I did a clean installation of the new operating system and had to reinstall everything on the new machine, which took a lot of time. As always, there were a few hiccups with the upgrade, but everything seems to be running smoothly now. After spending the last year talking about how I dislike the way Windows 10 looks/feels, it hasn't been too bad using. It isn't noticeably slower than Windows 7, so that is nice. I'm turning into that guy that just complains about anything new related to technology since I don't want to spend the brainpower to learn it… :)
Building Tunnel Lords for UWP
Once everything was compiling on Windows 10, I took a stab at getting Tunnel Lords running within the Universal Windows Platform (UWP) framework. I came across several snags.
At first, I didn't understand that UWP uses a different version of .Net framework than conventional desktop applications. It uses .Net Core, which actually compiles into native code as opposed to using the JIT (Just In Time) compiler. This should give it a nice performance boost, and I actually like this over using the JIT (I think?). The problem is that if I build my class libraries leveraging .Net 4.6.2 (or any .Net outside of .Net core), they cannot be used by the UWP build of Tunnel Lords. Besides compiling into native code for Windows, .Net core can be used on Linux and MacOS and is open source. Sounds very awesome indeed! .Net Core is updated in your projects through Nuget, which is a little different as well.
I ended up solving the mismatch between .Net Framework 4.6.2 and .Net Core by making a second project for each of the class libraries. There is now a GameUtilities project that compiles with .Net 4.6.2 and a GameUtilitiesUWP project that compiles for UWP using .Net Core. The UWP version just links to all the source code files and doesn't actually contain anything unique. This is basically how I handled compiling code for both the PC and Xbox 360 with XNA. The benefit of XNA was it would automatically link any files I created for the PC build to the Xbox project, saving time. I'm unsure how to make this hook happen on my own and am doing the work manually. This isn't a big deal though since Tunnel Lords is mature and I'm not adding many new code files anymore. It would have been a real chore earlier in development.
I managed to link the MonoGame content project to both the UWP and generic Windows build, so I only have to add new content in one place and MonoGame will handle building it for either environment. Not much different between the environments in this case, but it works the same for Linux or Android or MacOS. Nice work MonoGame!
I had LOTS of problems with the MonoGame UWP template project. I ended up using the C# UWP app project from Visual Studio, and then manually adding the references to MonoGame. This took a while since I've never integrated MonoGame (or XNA) into a project manually before. I even tried using the current non-stable build of MonoGame (ver 3.6), but it didn't work either. I think it is buggy, but there could also be some operator error since it is my first time working with UWP.
I have a MonoGame running within a UWP frame. Important step forward!
The current problem is MonoGame failing to properly read my custom XML data when calling Content.Load on the UWP build; When I read in XML data that only contains C# types (like Dictionary, string, int, etc), it works fine. When I try reading in my own custom data class (like Dictionary<string, MineData>), MonoGame throws an error. The content processor appears to be writing the XML content properly as .xnb files, but cannot read the .xnb file into the game. It throws the error on Content.Load. I think the problem is the ContentTypeReader is unable to understand my custom data types. However, I don't know why the non-UWP build of the game is able to read the XML data and the UWP version is unable. Perhaps I messed something up when adding the MonoGame references to the UWP project?
An exception of type 'Microsoft.Xna.Framework.Content.ContentLoadException' occurred in MonoGame.Framework.dll but was not handled in user code
Additional information: Could not find ContentTypeReader Type. Please ensure the name of the Assembly that contains the Type matches the assembly in the full type name: Microsoft.Xna.Framework.Content.DictionaryReader`2[[GameUtilities.Input.InputCommands, GameUtilities, Version=126.96.36.199, Culture=neutral, PublicKeyToken=null],[GameUtilities.Input.KeyList, GameUtilities, Version=188.8.131.52, Culture=neutral, PublicKeyToken=null]] (Microsoft.Xna.Framework.Content.DictionaryReader`2[[GameUtilities.Input.InputCommands, GameUtilities],[GameUtilities.Input.KeyList, GameUtilities]])
If unable to solve it soon, I'll probably post on the MonoGame website asking for help.
UWP .Net Framework compatibility issues
Beyond causing all the headache of creating multiple projects due to .Net Core, .Net Core does not contain everything available within .Net Framework 4.6.2.
- The Console class does not exist on UWP. I was using Console to write output data when certain errors occured. I had to switch these to .Net Debug, but I think it will work close to the same.
- The StringComparer class does not include the properties InvariantCulture or InvariantCultureIgnoreCase. I just switched to using OrdinalIgnoreCase when comparing strings instead of InvariantCultureIgnoreCase.
- UWP does not contain the class System.Diagnostics.Process. I was using System.Diagnostics.Process.Start to open the player's browser to Itch.IO when they selected purchase game. This will be handled by a different mechanism on UWP anyways, so no loss here.
So while .Net core framework is missing some parts of the traditional .Net framework, the issues were easy to workaround.
GameUtilities Refactoring & Instructions Screen
I spent some time cleaning my class library code. Some of this code was written by me 2 years ago (or more) and it was written poorly. I can tell my coding style has matured over time. I spent time renaming a lot of the methods and cleaning poorly written algorithms. I noticed the poor code while building up the Instructions screen. I'm setting the instruction screen to show on first play through or when selected from the main menu. The screen still needs a lot of work in the coming weeks though.
I have family visiting later this week and expect work to be busy before then. Progress will probably be slow.
- Fix Content read error for custom types serialized as XML.
- Read through more large chunks of the Universal Windows Program documentation related to Tunnel Lords
- Stretch Goal: Start testing touch screen code
- Stretch Goal: Finish the dedicated instructions screen
- Stretch Goal: Design code for saving/loading Tunnel Lords settings data on UWP