Jump to content
  • Advertisement
Thomas Izzo

What are some good tips for programming a game that is "port"-able?

Recommended Posts

Hi there,

I'm currently working on a game engine and mechanics for a game I'm designing. This internal code is relatively generic in the sense its doesn't rely on any platform specific APIs (that I'm aware of). While I've started looking around at graphic rendering APIs and what not, I've not made a decision to settle onto anything hard yet. 

As I continue developing this game, I'm curious if anyone has any tips and tricks to avoid locking myself into certain APIs in the event I would someday like to port the game to another platform in which I would need to interact with different APIs. For example, I'm still not sure on the art style and whether or not I want to do a 2D pixel game or a 3D-esque top down style. I might have to change my render API eventually if I don't like the art direction.

I'm currently wrapping all APIs into C++ classes for modularity and am using C standard typedefs to ensure correct data types across platforms. However, is there anything else I should watch out for?

Share this post


Link to post
Share on other sites
Advertisement
Quote

OpenGL is more portable, but for mobile devices you will use GL ES, which is more constrained.

Just to add to this, Apple has recently deprecated OpenGL and OpenGL ES on its platforms. They can still be used for now, but they've more or less been superseded by Metal on macOS/iOS. So that's something else to factor in when thinking about graphics APIs.

Share this post


Link to post
Share on other sites
4 hours ago, Zakwayda said:

Just to add to this, Apple has recently deprecated OpenGL and OpenGL ES on its platforms. They can still be used for now, but they've more or less been superseded by Metal on macOS/iOS. So that's something else to factor in when thinking about graphics APIs.

Now that Apple platforms have semi-official support for Vulkan it makes Vulkan the graphics API to target if cross-platform support is important for you. It is still not supported on all platforms (eg. Xboxes still support only DX and Sony has their own APIs too) but porting from Vulkan to another low-level API is actually not that difficult as opposed to porting from, say, OpenGL to DX11.

Another option would be to look at a library like LLGL which abstracts away most (but not all) of the API differences and gives you a somewhat unified API to work with.

Share this post


Link to post
Share on other sites

Just to add, handling text differs on unix based systems and windows   - im talking about end of the line character, the same applies for socket programming

Share this post


Link to post
Share on other sites

Best advice I can give you is to start out by developing your code on multiple platforms simultaneously.  When you do that, you will discover tons of tiny surprises along the way that you need to adjust to keep the code clean on all platforms.  Fixing issues as they appear is quick and easy.  But, putting off discovery until after lots of code has been written, you are signing yourself up for lots of unpleasant surprises (and rewrites).

Share this post


Link to post
Share on other sites

Keep it simple and build a core library that contains all these interface API code and/or split your code into modules so that each module is responsable for just one single kind of system. This makes it easier to port classes to other platforms as the "public" interface never changes to code setup on that core system while you could work on the core and it dosen't effect the rest of the game.

Also don't overcomplicate features and code while writing your system ever think about if you really need just that OS API function or could it be replaced by something self written. Keeping this question in mind gives ya a small set of OS dependent features that are

  • Filesystem Access
  • Threads/Locking
  • Window Management & System Messages
  • Audio
  • Graphics
  • Network
  • Input

Accessing the filesystem as same as threads and locking could be done via STL but I decided to go for the hard way and was suprised that those implementations are very small and fast and you could do some tricks in C++ for example that make using your API more convinient.

Drough::Thread<byte* (Drough::string)> FileFetcherThread(FileFetcherFunction);
FileFetcherThread.Start("Test.txt");

for example is my version of a templated thread.

Window Management was really simple too because you need just a few OS function calls to setup a window correctly and have it's visual style, size and position changed took me 4 hours of work until anything worked fine.

Audio and Graphics is a little bit more tricky as this depends on the underlaying API, so I decided to skip DirectX support and focus on Vulkan/OpenGL (no need for me to go for Apple platform here), while I wrote my wrappers for GL and Vulkan by myself, there was a Tool I made that grabs the specs from Khronos GitHub and creates interface classes for. There is then just a little OS API code needed to load/bind function pointer to those interface while anything else is then managed by GL/Vulkan itself.

The most annying part is Audio because you either need a plugin system or set to just one Audio API on each platform while building your code through code compiler. This maybe the only topic where I would accept to use plugins while in my opinion plugins elsewhere (like in OGRE) are a sign of bad or too general code architecture.

Networking took me a while too because there is a difference between Windows and UNIX platforms you need to be aware of while general socket access is similar on Windows, UNIX and Playstation/Nintendo SDK, Windows is using a "wait until something happened" model for asynchronous sockets, while UNIX follows the "wait until nothing happens anymore" model.

Last but not least input (if not handled through OS messages that I highly recommend to not use) is a special kind too. Without DirectX I even hadn't access to use DirectInput/XInput so the path to go here was using the HID driver interface (used for accessing USB devices). HID is mostly standard but access is different from platform to platform while you need Windows Driver SDK on Windows, there are some Libraries and also a Kernel Level Driver on UNIX while Playstation/Nintendo handles that through there API directly.

Anything else about tooling and build pipeline was already discussed above. Something worth to mention, I wrote my own tooling using C# (because .NET/Mono runs on every platform too) to handle build files

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!