Friday 18 June 2010

Hurdles when Porting Games to Linux

 A recent Shot of Jaq episode described the many problems that indie game developers face when porting their games to Linux, let's break down the problems into categories:

1. Which libraries do I use?
2. How do I package the game?

So here we go.

Which libraries do I use?

This is the one that people make the most fuss about. When developing a game on Windows, you know full well that if you want to create a 3D enabled window, you have Win32 + Direct3D + DirectSound (or whatever it is now) right there. And it works. It works because the whole Windows game world develops using those APIs and they are well tested. When coming over to develop for Linux, many devs don't know where to look for the equivalents, and when they ask around they get different answers from everyone, because people recommend what they like, not what is the most sensible option. Let me answer the question right now:

1. For graphics, use OpenGL 2.1 (or 1.5 if you don't need GLSL)
2. For sound, use OpenAL
3. For windowing and input, use SDL

Now, before I get ransacked by people with opinions, I'll explain why :)

Graphics

This is the easiest one to decide. OpenGL is the only choice for hardware accelerated graphics on Linux. If you can do without shaders and target 1.5 you can get the lower end hardware, if you need shaders then go for 2.1 rather than 3.x or 4.x because Mesa doesn't support them (yet) and the open source ATI and Intel drivers both support it. You can of course check the version at runtime if you want 3.x or 4.x features, but don't rely on it.

Sound

This is the one that causes the most noise (no pun intended), ALSA? Pulse? OSS? etc. No you want OpenAL. OpenAL gives you a consistent 3D sound API that wraps the underlying complexity of various sound systems.  It's not perfect, but it's definitely your best choice. Hemisphere games came to the same conclusion when porting Osmos. Just go with it and test as much as possible. openal-soft has a number of backends too, so if you don't have Pulseaudio, or whatever, it will still work. The openal-soft developers are really responsive. I had a load of help trying to diagnose a problem with openal + pulse (which was a bug fixed some time ago now).

Windowing and Input

I can tell this will stir up a hornets nest of people saying that straight X is better, and indeed straight X is what the Osmos developers went with. But SDL has been used for a load of games (World of Goo, Penumbra, Quake 4 etc.) it's pretty damn good. Again, it wraps the complexity of the underlying X and handles any quirks for you. Also the SDL developers are responsive to both feature requests and bug reports, and have a really busy mailing list. If you have any trouble, you have somewhere to go and get it fixed. If you don't think SDL is flexible enough, then go with X, but let me assure you - you'll be writing a lot more code, and that code is your problem.

There, done. By offloading the work to these libraries you get a number of advantages:

1. Bugs you find and report (and perhaps even fix) help everyone
2. They deal with the hard work for you, reducing the amount you need to code
3. They are widely available
4. All three of them have nice, consistent APIs

Packaging the Game

Packaging is a pain in the arse if you want to target as much of the Linux-based ecosystem as possible. Generally though, packaging in .deb, .rpm and .tar.gz in both 64 bit and 32 bit versions seems the way to go. Games in The Humble Indie Bundle were packaged in various different ways, but World of Goo had a .deb package that worked the best compared to the fiddling I had to do to get the others to run.

It's probably best to go with the distributions package manager to handle dependencies, especially for the big 3 libraries (GL, AL, SDL) and also FreeType and libvorbis.  That's the approach Hemisphere games took and they seem pretty happy with the result.

Other Libraries

Obviously it's not just graphics, sound, input and windowing you need to worry about, here are some suggestions for other libraries:

1. Fonts - Freetype2
2. Image loading - Take a look at SOIL
3. OpenGL extension handling - GLee is popular, but not included in the Ubuntu repos, GLew does the same job and is in the repos.
4. Physics - Box2D for 2D, ODE for 3D

Friday 11 June 2010

Clearing FileFields in Django's admin

This post is as much a reminder for me as it will be helpful to others. Yesterday I added a couple of FileFields to a Django model, the point of them is to allow overriding of some site images. So the idea is that you can upload images or swf files to these fields, they'll replace the ones on the site, until you are bored of them then you can delete them and the original images will be restored.

After adding the FileFields to the model, they nicely appeared in the Django admin site. I uploaded an image, the override worked perfectly, now to restore the original image...

And that's where you hit a problem. There is no way in the Django admin to clear a FileField, you can replace it, but you can't clear it to NULL. Happily there is a workaround[1]. You first need to create a custom ModelForm for your model which includes an extra checkbox like so:

class MyCustomForm(ModelForm):
    clear_the_image = forms.BooleanField("Clear the image", required=False)

    class Meta:
        model = MyModel

    def save(self, commit=True):
        model_instance = super(MyCustomForm, self).save(commit=False)
        if self.cleaned_data.get('clear_the_image'):
            model_instance.the_file_field = None

        if commit:
            model_instance.save()

        return model_instance


Then in your MyModelAdmin class:

class MyModelAdmin(ModelAdmin):
    form = MyCustomForm


That's it. When you save the form, it will see if you asked to clear the image, if so it will set it to None and then save. Job done.

[1] Adapted from this: http://www.developerit.com/2010/04/17/django-admin-add-a-remove-file-field-for-image-or-filefields