Sunday, July 6, 2014

Game On

I have a PS3 game controller lying around, so I got the idea to add support for it to an old SDL game code. This code was still using SDL 1.2, which is now a thing of the past. So the first thing to do was quickly porting it over to SDL 2, a more modern game programming API. It even includes a GameController API, and because of that, programming support for game controllers with SDL is remarkably easy.

Initialising initialisation
For initialisation, call SDL_Init() with extra flag SDL_INIT_GAMECONTROLLER. Additionally, you must open the game controller. The game controller is found by first querying the system for the number of connected joysticks.
    SDL_GameController *ctrl = NULL;

    SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER);

    int num = SDL_NumJoysticks();
    if (num <= 0) {
        printf("no joy connected\n");
        return false;
    }
    if (!SDL_IsGameController(0)) {
        printf("it's not a game controller\n");
        return false;
    }
    ctrl = SDL_GameControllerOpen(ctrl);
    if (ctrl == NULL) {
        printf("open failed: %s\n", SDL_GetError());
        return false;
    }
    name = SDL_GameControllerName(ctrl);
    printf("game controller: %s\n", name);
This code is just an example. It assumes the first connected joystick is indeed the game controller that the player wants to use. This is of course ridiculous, and you should really loop over all joysticks and open as many connected devices as possible.

Mapping the mappings
In them old days, supporting game controllers was ... problematic. The thing is, every game controller is different and there is no common standard among manufacturers for numbering buttons and analog sticks. Even a simple D-pad is different between different controllers — think XBox360, PS3, PS4, but even PS2, Logitech, OUYA game controller? SDL 2 solves this incompatibility by mapping the raw device button ids to generic SDL enums. You do need to provide the correct mappings, these can be imported from a flat-file game controller database.
    SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");

    if (SDL_GameControllerMapping(ctrl) == NULL) {
        printf("no mapping for %s\n", name);
        SDL_GameControllerClose(ctrl);
        ctrl = NULL;
        return false;
    }
Finally, enable events so that SDL will generate events for us to collect in the main event loop.
    SDL_GameControllerEventState(SDL_ENABLE);

Moving forward
When SDL game controller events are enabled, you will receive events of type SDL_CONTROLLERAXISMOTION in the event loop. You will find that SDL sends lots of these events, even when just holding the controller. This is just noise on the sensor, and the analog sticks are quite sensitive. Merely touching already registers movement. The ‘axis values’ are a signed 16-bit value, between -32768 and 32767. The SDL documentation says values between -3200 and 3200 are in the ‘dead zone’ where the sticks should be considered at rest.

The SDL_CONTROLLERAXISMOTION event boils down to this:
event.caxis.which     connected joystick number
event.caxis.axis      axis number
event.caxis.value     amount of movement

Click image to enlarge

Analog triggers L2 and R2 register as axis 4 and 5, but they only report value 32767 when pressed, acting like digital buttons. This could be a driver issue (I'm on a Mac) or SDL not properly supporting the triggers. I'm not sure.

Benjamin Buttons
SDL generates SDL_CONTROLLERBUTTONDOWN and SDL_CONTROLLERBUTTONUP events. Inspect event.cbutton.button to see which button was pressed.
The button codes are hard to find in the documentation, but look in SDL_gamecontroller.h to find the enums. The API is modeled after an XBox type controller, for PlayStation the button ‘A’ is a cross, button ‘Y’ is a triangle, etcetera. The ‘guide’ button is the PS logo button.
SDL_CONTROLLER_BUTTON_INVALID = -1
SDL_CONTROLLER_BUTTON_A
SDL_CONTROLLER_BUTTON_B
SDL_CONTROLLER_BUTTON_X
SDL_CONTROLLER_BUTTON_Y
SDL_CONTROLLER_BUTTON_BACK
SDL_CONTROLLER_BUTTON_GUIDE
SDL_CONTROLLER_BUTTON_START
SDL_CONTROLLER_BUTTON_LEFTSTICK
SDL_CONTROLLER_BUTTON_RIGHTSTICK
SDL_CONTROLLER_BUTTON_LEFTSHOULDER
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
SDL_CONTROLLER_BUTTON_DPAD_UP
SDL_CONTROLLER_BUTTON_DPAD_DOWN
SDL_CONTROLLER_BUTTON_DPAD_LEFT
SDL_CONTROLLER_BUTTON_DPAD_RIGHT

Any other business
I have a single player game so programmatically, I took the easy road and just map all buttons and stick movement to key presses, internally translating to a keyboard joystick. This works, but it's not good enough for multiplayer games. It also loses the ability to properly react to stick acceleration; you might want to scale the axis values to have a proper difference between large and small stick movement.

Some tutorials suggest you ignore the ‘dead zone’, but this is wrong because when you fully ignore those events, you are unable to detect when someone suddenly lets go of the joystick. Instead, the dead zone should be mapped to zero movement. You can also keep track of sticks entering/leaving the dead zone, and react correspondingly.

The DualShock 3 controller has pressure sensitive buttons. SDL has no support for measuring the amount of pressure. Nor does it support the sixaxis motion sensor. SDL 2 can do rumble however via its Haptic API.

The cool thing about SDL is that it also ports to other platforms, maybe most notably the Steam OS. Since I'm on OS X I also had a quick look at how to do this joystick & game controller thing in pure Cocoa — not so easy at all. I'm with SDL 2 on this one.

Links
SDL 2 GameControllerDB file
SDL 2 API by Category
How to connect a PS3 controller

Sunday, June 8, 2014

Go Rust Swift, Vala

In the WWDC keynote speech, Apple announced their new programming language named Swift. It looks like a scripting language, but it actually compiles to binary, giving you lots of performance. For years, I've been griping about the need for a programming language that's as easy as scripting, while delivering decently high performance. Lately, we've seen a number of new languages that do exactly this. So, it's time to discuss a few of these new, modern languages.

Go
Go was developed at Google and was first publicly released at the end of 2009. It's no secret that I'm a bit of a fan of Go, and I'll admit that of the four new languages discussed here, it's the only one I actually wrote a decent amount of code in.
Go is awesome for parallel programming. Goroutines and communication channels are plain brilliant. In fact, it completely changes the way you think about parallel programming. Go's duck typing system is marvelous, an enormous sigh of relief after decades of OOP and I just want to hug the creators of Go.
And yet, it has not yet become my primary language of choice. A big reason for that is mandatory CamelCasing. In Go, lower/upper CamelCasing actually controls whether the symbol is being exported or not; a really awkward design decision (golang's only mishap?).
Go is great for systems programming (ie. for UNIX tools, services), however ... it's as clunky as C when trying to parse a config file, and its flag command-line argument parser module isn't great either. Then I tried making a game in Go and simply couldn't get started because there were no stable bindings for the needed libs at hand at the time.
Go has a very “C feel” to it, every time I code in it I feel like I'm constructing a tiny, delicate machine. Everything about Go is excellently engineered. Some clever men with beards really thought things through.
What will golang's popularity be, five years from now? We shall see if it's truly to replace C/C++ as top systems programming language.

Rust
Mozilla's language named Rust started in 2006, but didn't go public until 2010. Rust is quite impressive, but the tutorial kind of lost me once it started on heap allocation, object ownership of memory, control of mutability, references, and confusing syntax involving glyphs. This leads to some pretty horrific code that shouldn't have been that way, in my opinion. Secretly, Rust is trying hard to be like C++.
The tutorial has some notes on features that are currently missing or buggy. In that respect, Rust is not ready for prime time yet. It does show a lot of potential and it did manage to create a buzz in the open source world, so check back once it hits version 1.0.

Swift
Apple's Swift language was announced only last week and is said to have been in development since 2010. At a glance, it's suspiciously a lot like Rust. This is particularly interesting given the fact that Rust is sponsored by rival company Samsung. What's the true story behind this?
Anyway, Swift looks awesome, and it's already miles ahead of Rust. Swift builds upon a foundation laid by Objective-C, all the way from NextStep to OS X and iOS. Cocoa and Cocoa Touch bindings are in place and ready to use. Under the hood Swift uses reference counting for garbage collection, and here lies a major pitfall; you should take care not to create any cyclic references, and/or know the difference between weak and unowned references. If you get this wrong, memory will leak just as it did in Obj-C. [Note that the same is true for Rust and Vala].
Swift lives in an Apple-only world, which should be no surprise — I suppose this compares to Microsoft's strategy regarding Visual Basic, C#, .NET.
There is no doubt that Swift is going to be huge on iOS, and probably also on OS X. Nobody likes Obj-C (apart from some weird guys like me). The matter of truth is, Obj-C is outdated, it has just been obsoleted by Swift. Two years from now, no one will be writing new applications in Obj-C.

Vala
Last but not least, there is Vala, which has been around since 2006 already. Vala is a Java/C#/Mono-like language for developing GNOME applications. It is said Elementary OS's main apps are built in Vala. The Vala compiler converts Vala code to plain C with GObject, which is in turn compiled by a generic C compiler. In a sense, Vala is just syntactical sugar, removing all the bad things that C has (the tedious task of programming intricate details), while keeping all the good (high performance).
Its syntax will be appealing to mostly Java and C# programmers. Personally, I get lost in the soup of keywords. A Vala source can be like a C++ code in disguise. There are just too many keywords; the designers forgot that less is more. It's probably too late now, but my wish for Vala is to be stripped down, simplified, made easier to work with.
Nevertheless it is a great choice for developing GNOME applications, and there is Elementary OS to prove it. Currently it looks like Vala's success is tied to that of GNOME, and it's a bit of a shame because it deserves more attention from a broader audience.
Vala wins the prize for “Best chosen name for new programming language” simply because googling it lands you on the right pages right away.

Links

Thursday, May 29, 2014

Programming is hard

I have always seen programming as something creative, like an art. And like in art, it is hard work to create something beautiful. It's hard to get the details right. If you get it right, then people will like the result, and of course, some may not because tastes differ and you can't make everybody happy. But aside from people's reaction to the picture painted, a painter also gets his satisfaction from mere crafting, using this technique here and that trick there, knowing the internals of his work.
Picture a musician, selecting an instrument to play, a rhythm, writing a melody.

That sure is a romantic view of programming. In reality, it's more of a purely technical process. When you want to accomplish goal G you are going to have to make work A and B together. This might be done with technique C. This is engineering. Apply a trick here, and it is called a hack. Hacks can be dirty hacks, or they can be clever hacks. In a security context, they might even be dangerous hacks.

Some say building applications is like building a house, and there should be blueprints for building software as well. Houses are built from small, simple building blocks. All houses have walls and a roof, a kitchen, a living and a bedroom, yet each house is unique. For each room, you can zoom in and work out the details. Users have the option of changing the wallpaper. And of course, a construction error may take down the entire house.
It's a nice metaphore that works well, but I suspect that whoever thought up that idea is not a programmer.

Programming is a mind game. The programmer builds a model in his mind, writes down the code and tries it. If it doesn't work, she tries to find out where it doesn't work. You may use a debugger or sketch it on paper but mostly the problem is cracked in your mind. Like a game of chess, it takes a lot of concentration trying to think six moves ahead, a single mistake will play out badly sooner or later.

Bugs are rarely ever “happy little accidents” like in Bob Ross paintings. They range from apparently random program crashes to worldwide Heartbleed scale disaster. Slowly the world is waking up, it has become apparent that eventually all software is flawed. Consequently, using the internet is as big a risk as a running across a highway, naked.

Programming is hugely underestimated. Programming is hard. It is really, really hard. The human mind was not made for this job. It is incredible that we have computers at all. Steve Jobs said that everyone should learn to program, because it teaches you to think. I agree a little, but it's like saying “Everyone can paint!” Or, “everyone should learn how to build a house.”

The best way to keep out bugs? Keep It Simple, Stupid. Simplify, simplify. Write code in a clear, consistent style. Add useful comments. Sometimes comment on why you did it this way. Test, test, test. Eat your own dog food.

There is a nice test to see if you've written good code. Open up a source file that you wrote six months ago. If you can't make out how it works within five minutes, then it's just not good enough. Now open up a source code that someone else wrote.

Boom. Oh, the horror.

Note that even this test is flawed, because you might not be seeing what you think you are seeing. Think about it. Programming is hard. And so is building houses.

Monday, April 7, 2014

In exceptional conditions

On the topic of condition variables, wikipedia says: “In concurrent programming, a monitor is a synchronization construct that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become true.”
This is commonly used in producer/consumer-like problems.

The code for programming such a monitor looks like this:
lock(&mutex);
while (!predicate) {
    condition_wait(&mutex);
}
consume(&item);
unlock(&mutex);
This can be implemented, for example, with pthread_mutex_lock() and pthread_cond_wait(). If you would wrap things into a class, it might look like the following:
mutex.lock();
while (!predicate) {
    cond.wait(mutex);
}
consume(item);
mutex.unlock();
However, in a language that uses exceptions, this code would be flawed. Suppose that consume() (or even cond.wait(), however unlikely) throws an exception, then the mutex remains locked. Therefore, in a language like Java, you should write:
mutex.lock();
try {
    while (!predicate) {
        cond.wait(mutex);
    }
    consume(item);
} finally {
    mutex.unlock();
}
This ensures the mutex gets unlocked, even in case an exception occurs.
In Python, the mutex is part of the condition object. This simplifies things somewhat by hiding the mutex under the hood:
cond.acquire()
try:
    while not predicate:
        cond.wait()
    consume(item)
finally:
    cond.release()
C++ does not have a finally keyword — it doesn't need it, because it has RAII (“Resource Acquisition Is Initialisation”). In C++, it should be coded as:
std::mutex mx;
{
    std::unique_lock<std::mutex> lk(mx);
    while (!predicate) {
        cond.wait(lk);
    }
    consume(item);
}
Note that the destructor of std::unique_lock will ensure that the mutex is unlocked. The destructor will run when the stack unwinds, which is also done when an exception occurs.

Although entirely correct, and arguably the most elegant solution, I have to say I find the C++ code unintuitive and difficult to follow. The reason is that there are no explicit statements in this code block for dealing with locking; the mutex is locked by the constructor and unlocked by the destructor, that run automagically. It is almost as if the mutex variable isn't doing anything at all. Annoyingly, this code can not be refactored to resemble the other code fragments, because of RAII. And you are being forced to write it this way now that threads, mutexes, and condition variables are part of the std library; there is no other way in which a condition variable can be used because the other way would be incorrect in C++.
This is one of those cases where C++ shines but somehow it doesn't feel gratifying.