Conditional code for multiple platforms

Dear @RonGilbert,

Having formed part of the iOS testing effort, I saw how you were forced by circumstance to add some platform-specific functionality. I would imagine that the same is true for all other platforms, since they have different capabilities, features, and conventions.

My question to you is, how do you handle and maintain all this custom code? I mean, do you have multiple branches of the codebase, each diverging progressively as development proceeds and new features are added? Or do you have a single source base with a bunch of “if (platform == iOS) … else if (platform == XBox) …” etc.?

dZ.

It’s a single code base. Some of it is done at run-time if statements as you mentioned. Some of it is done using

#if defined(PLATFORM_XBOX)

to compile different sections of code. This is common around sections that are very platform dependent. Xbox has a very different system for achievements than Steam does (for example).

The touch vs controller vs mouse has to be decided at runtime, since some platforms can use 2 (Switch can use controllers and touch). Steam mouse and controllers. Android can use all three.

2 Likes

Wow! I’m sure you know what you are doing, but it sounds like it must be a pain to maintain and debug! :scream:

dZ.

As a programmer, I can confirm that’s a common practice, using #defines to compile different code sections. We use this approach to compile different versions of the same program, by assigning a different value to the defined variable.
At the end, it’s not so difficult to maintain, you can search the sections of your interest and amend the code.

I also can confirm this practice but with an huge single code base this is not always easy so in general this should be done very careful to keep the code maintainable.

The compile time condition can also be meaningful to include platform dependent source files. This can be helpful to keep a source file small and uncluttered.

#if defined(MAC)
    #include "foo_mac.h"
#elif defined(WIN)
    #include "foo_win.h"
...
#else
    #include "foo_linux.h"
#endif
1 Like

If you use an object oriented language you can encapsulate the code. For example you could introduce a class “Achievements” that contains the platform dependent code. The rest of your code uses only this class. So you know where to look if you want to change the achievement system (or if you need to support a new platform). With this approach the code remains maintainable.

Different versions e.g. of an game can also be easily managed by a version control system like Git (Git - Tagging). For instance, you can quickly compare different versions at source level of the whole game.

For instance, in case of the file format of the saved game has changed a newer game will probably continue to read successful a saved game created by an older version of the game and this check can be done at run-time.

For instance, in case of the file format of the saved game has changed a newer game will probably continue to read successful a saved game created by an older version of the game and this check can be done at run-time.

… and may the heavens have mercy on you if you forget to version your save files

1 Like