Skip to content

Instantly share code, notes, and snippets.

@raysan5
Last active April 6, 2024 14:07
Show Gist options
  • Save raysan5/fdefbe1b8184e0fa80676156bb86964f to your computer and use it in GitHub Desktop.
Save raysan5/fdefbe1b8184e0fa80676156bb86964f to your computer and use it in GitHub Desktop.

FLIPS_choose_game

Game Porting Adventures

This article details my adventures and disadventures while porting my +9 years old XNA games, originally developed for Windows Phone, to multiple other frameworks (SharpDX, PSM, MonoGame...) for PSVita, Android and Desktop platforms.

The article is divided in 3 parts:

PART 1: The Past

At the beginning of 2012 I decided to create emegeme and start developing games. I got some experience with XNA framework so I decided to develop games for the new Windows Phone platform that was recently published and it was supported by the framework.

First game I developed was DART that TARGET, a darts arcade game. It took me about 3 months of work to create all the graphics and write all the code, it was released by April 2012. Sales were terrible.

emegeme_dart_xna_screenshots

DART that TARGET XNA game screenshots. I really put a lot of care in details, you can touch the neons for some sparks!.

cost_estimation_dart_xna

DART that TARGET XNA source code development cost estimation analyzed with scc 3.0.0. A really motivational tool to evaluate my productivity.

Despite DART that TARGET did not work as expected, I decided to develop a second game, FLIPS, a memory cards game. FLIPS development took me about 4 months and it was released at the beginning of September. I put a lot of effort on localization (9 languages supported), it delayed the release a bit.

emegeme_flips_xna_screenshots

FLIPS XNA game screenshots. Again, I put a lot of care in details. I draw the 64 veggies cards available by hand!.

cost_estimation_flips_xna

FLIPS XNA source code development cost estimation analyzed with scc 3.0.0. It does not reflect the amount od work it took me to create all the art!

Again, sales were terrible but thanks to that game I got a job offer to teach some videogames development lessons at a private educational institution, only for a couple of weeks... that turn into a 6 years full-time job!. During that time, I started a new project called raylib but that's another story.

By the end of 2014, I decided to give emegeme another try and, with the help of some of my students, we started working on games development again. By that time raylib was already a thing and some of the development efforts were put on it, actually, some of those efforts were the origin of raygui and several raylib features.

Beside raylib, two videogames project were started, one was Koala Seasons, a raylib game for Android that was never released on that platform but open-sourced and released for web later on.

Second videogame project was a port of FLIPS to other platforms. XNA was discontinued by Microsoft and MonoGame seemed to be the best alternative but it has many dependencies and the custom content processor tool was not ready yet, so, I decided to use SharpDX, a lightweight alternative to support Windows desktop platform; actually, MonoGame was using SharpDX internally at that moment.

FLIPS port from XNA to SharpDX started on November 2014 and it was done in parallel with another two big game changes: a redesign from portrait to landscape mode (to better accomodate on Windows desktop) and a code split for Engine and Game, the engine was called geme. The plan was using that engine for future projects... never happened.

geme_engine_logo_details

geme game engine logo and structure. It was a very simple engine with just a bunch of classes, intended for 2D games.

By the end of 2014 FLIPS was already running on Windows desktop, it was nice, it allowed the project to live a bit longer than on a Windows-Phone-only platform but from a business point of view, Windows desktop was not the best platform for that kind of game (or that was what I thought at that moment). I decided to port the game again to a new platform: PSVita, using PlayStation Mobile (PSM).

PlayStation Mobile platform had been around for some time and it was intended for independent developers, the most interesting feature was that it supported C# to code games (using Mono), so, it seemed a really nice fit for FLIPS.

PSM API was similar in some aspects to XNA but it required more work than SharpDX to port so, this time the port approach was a bit different, instead of replacing all XNA functionality by PSM equivalents, I decided to create an auxiliar library to map XNA to PSM, that library was called XNA2PSM.

I'm not an expert on games porting but during those ports I realized that, usually, porting a game between platforms requires reviewing some common elements. I thing most SDKs provide this kind of base elements:

  • Graphics Device Manager: Functions for Graphic Device initialization and drawing on it.
  • Content Manager: Functions to manage loading/unloading assets data.
  • Inputs Manager: Functions to read and manage inputs, usually Keyboard, Mouse, Gamepad and Touch inputs.
  • Storage Manager: Functions to access some persistent storage system to save and load game info.
  • System-specific features: For example networking, ads, trophies, system-level error messages, etc.

cost_estimation_flips_psm

FLIPS PSM source code development cost estimation analyzed with scc 3.0.0. Interesting to note the increment in code complexity compared to XNA.

Porting FLIPS to PSM took longer than expected but it was finally released on June 2015, after 5 months of development and working on it as a second job, also working full-time as a teacher.

FLIPS_PSM_Trailer.mp4

FLIPS for PSVita (PSM) promotional trailer. Published one month before the platform closing. 😔

Unfortunately, Sony announced that the PSM store was closing by 15 July 2015, so, FLIPS was on the market for about 1 month until it dissapeared forever. All the technologies I had used to make games to that moment had end up disappearing (XNA/SharpDX/PSM) so I decided to focus my efforts on my own technology: raylib.

PART 2: The Present

More than 9 years have passed since I released DART that TARGET and it's been more than 6 years since the last FLIPS port for PSVita PSM. During this time, I've released multiple raylib versions, several code libraries and even a set small tools for videogames development but I hadn't touched those games again... until now.

Recently I published raylib 4.0 and last week I decided to take a small break of C coding and try something different. I decided to port and publish FLIPS and DART that TARGET again.

I decided to use MonoGame for the ports, this framework has improved a lot in the last years and now it supports multiple platform seamlessly, so, I get down to the job and started porting those games again. The process took me about a week to get both games running on Android and Desktop (OpenGL) platforms.

flips_title_screen_en

FLIPS ported to MonoGame (Android and Desktop platforms). This is the title screen where you can select the cards memory game to play or check your veggies-cards collection. There are 64 hand-drawn cards to collect!

Here are the details of the tasks done along this porting week:

Day 1. 15.Nov.2021

FLIPS GitHub Structure

  • FLIPS: Define a proper project structure: My goal was to share as much code as possible between platforms so I decided to setup a solution with two projects (FLIPS.Android and FLIPS.Desktop) and link the source code from a common directory. I included the Content raw data with every project to be compiled by an MSBuild task on project compilation, same approach as the one proposed by MonoGame project templates.

Day 2. 16.Nov.2021

  • FLIPS: Manual Content compilation: I decided to move the Content raw data to a common directory outside of the projects and just keep the compilation config file (Content.mgcb) inside every project; I also tried to configure the output directories for the compiled data. Unfortunately, it didn't work, the MSBuild MonoGame task ignored my configurations and I couldn't get it working so I took another approach: Compile manually the assets for the desired platform and just properly add the compiled assets to the projects, it allowed me to remove the custom MSBuild task from the projects.
  • FLIPS: Remove PSVita specific code: I removed the XNA2PSM library but there were still some #defines around the code for system-specific PSVITA code. I reviewed that code to get a running build (at least on Desktop platform).

Day 3. 17.Nov.2021

  • FLIPS: Code and formatting review: I reviewed most of the code, I did some cleaning and I also I reviewed code formatting. At that time I was not so concerned about clean code and naming conventions as I am today.

Day 4. 18.Nov.2021

  • FLIPS: Review screen and input scaling: The original XNA game was designed for a fixed resolution of 480x800, the PSM port was redesigned for a fixed 960x544. It was required to review that to support multiple resolutions. I just rendered the game to a Texture and then scaled it properly to the full display where the game is running. It also required inputs scaling to accomodate to the original resolution.
  • FLIPS: Storage manager redesign: PSM implementation was specific for PSVita, it just accessed a byte array file and modified required bytes. I like that simple and low-level approach so I decided to keep it that way. I reimplemented the class to work that way but using the System.IO.IsolatedStorage; I got some problems with paths that took me longer than expected but I finally got it working on all platforms.
  • FLIPS: Removed Ads manager: I just decided to remove ads, social networks sharing and trial version for the game. I decided to keep it as a premium simple game.

flips_pairs_level_complete

FLIPS ported to MonoGame (Android and Desktop platforms). This is a pairs level completed, depending on your behaviour (time, flips) you can get between 1 and 4 stars, if you get the 4 stars you unlock a new card from the collection!

Day 5. 19.Nov.2021

  • DART: Complete project review: It was more than 9 years since last time I touched that code, project structure was unnecessarily comple, it had been greatly simplified for FLIPS but never back-ported, so, I decided to do a full review of the code. I removed the unneded classes, I replaced some classes and I did some code formatting and reorganization.

Day 6. 20.Nov.2021

  • FLIPS: Setup Google Play for publishing: I accessed my old developer account on Google Play and I start setting up the project for the release, filling all required information.
  • DART: Redesigned InputManager: I decided to review game inputs, old implementation was using the gestures system only and I added support for Touch and Mouse, to allow playing the game on Desktop platforms. I also reviewed some other classes and I did some code cleaning.

Day 7. 21.Nov.2021

  • Start writing this article.
  • Additional code cleaning and tweaks.

Both games have been submitted to GooglePlay Store at the end of Day 10 (24.Nov.2021), it took me some time to figure out how all the publishing process worked. I had to generate an .aab bundle (instead of .apk), I had to sign the apps and I had to fill all the required submission data. So, I've been able to port my old XNA/PSM games to MonoGame and publish them on Android in just 10 days. What an adventure! :D

game_porting_tools

Tools used to port the games. From left to right: Visual Studio 2019 Community Edition, Notepad++, Beyond Compare, Agent Ransack, Paint.NET and rTexViewer.

PART 3: The Future

With this port I gave my games a second life, now some more people in the world will be able to enjoy them and also, the games could be ported again in the future more easily. I know that, despite I put a lot of care into details, they are not amazing games, they are just some small games I created to learn and enjoy some years ago. It was nice to review that old code again and see how much I learned in the last 10 years.

cost_estimation_dart_mono

DART that TARGET MonoGame source code development cost estimation analyzed with scc 3.0.0. Note that after some cleaning, code was reduced in about 2000 lines; code complexity was also reduced.

DART that TARGET code structure was over-engineered for my taste and it took me some work to review. It used an stack system for the game screens, actually, all panels are game screens that overlay other screens, with several levels of inheritance. Probably that structure is fine for a mid-size or bigger game but I think it was not required on this game. On FLIPS code was greatly simplified, ScreenManager just manages CurrenScreen and nextScreen, all the objects required for every screens are managed internally by every screen, a simpler approach.

I should note that I've been coding mostly in C for the last 8 years, trying to create very simple and maintainable code, that's probably the reason I see many OOP approaches unneeded at this point.

I think the code in those games could be further optimized and simplified but it's really interesting to note the reduction in code complexity, that's a key factor for maintenance, sustainability and code longevity. FLIPS code structure is quite simple with just a few classes and a few systems to control all the processes, also, the different pieces are quite decoupled. It greatly simplifies porting this game to other platforms or even other programming languages in the future.

cost_estimation_flips_mono

FLIPS MonoGame source code development cost estimation analyzed with scc 3.0.0. Code was reduced in almost 6000 lines from PSM version with +700 points reduction in code complexity!.

I considered several possible improvements or paths to explore for the future:

Path 1: Porting to raylib-cs

raylib-cs is a C# binding of raylib. Considering that raylib is highly inspired by XNA, the C# version of the library maps very well to MonoGame, both libraries provide mostly the same functionality.

The approach to this port would be similar to what I did for PSVita PSM with XNA2PSM, I'd design an intermediate library to map XNA/MonoGame to raylib. The interesting use of this mapping library would be allowing other MonoGame simple games to use raylib seamlessly. I analyzed the classes required on this mapping:

monogame_raylib_mapping

Mapping of MonoGame classes to equivalent data structures or functionality provided by raylib. NOTE: Those are the classes I would require for my simple games, other more advance MonoGame games could require additional classes but probably raylib also provided most of them.

Path 2: Porting to WebAssembly

WebAssembly Logo

I've also been investigating if it was possible to port a MonoGame C# game to WebAssembly. Unfortunately, it seems it's not possible yet. Note that it's possible to compile C# to Wasm but all the graphics backend is not supported (or I couldn't find any documentation explaining how to do that). Hopefully that will be possible in a future, similar to what emscripten does with C/C++.

Still, if the game was ported to raylib-cs that uses raylib and considering that raylib can be compiled to Wasm with emscripten and the WebGL Javascript layer is generated on the process, maybe raylib-cs could consume those libraries... I don't know, it will require further investigation.

Path 3: Porting to C/C++

The current code of FLIPS and DART that TARGET is quite simple and contained in about 6000 loc. A complete port to C++ shouldn't be that complex using raylib as a backend.

If the code was ported to C++, it would be possible to compile those games to WebAssembly and run them on a webpage.

Conclusions

After almost 10 years since my first games were published, I've been able to port and publish them again for current platforms.

my games to my own technology (or very close to it).

@TurtleSwift
Copy link

Good read. Any reason you chose MonoGame over FNA?

@raysan5
Copy link
Author

raysan5 commented Feb 1, 2024

@TurtleSwift Thanks! Not really, I have some previous experience with MonoGame and I just didn't consider FNA at the moment of the porting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment