Julien Jorge's Personal Website

ASGP's Android Port Part II: from SDL 1.2 to SDL 2

Sun Sep 15, 2013

Here is the second step in the port of Andy’s Super great Park to Android. As a reminder, ASGP is a C++ game I decided to port to Android with the help of the NDK and the freshly released SDL 2. I have described in Part I, how I managed to find, patch, build and compile the dependencies of the game. Now it’s time to replace the calls to the old SDL API with calls to the new one.

In this part, I will describe the changes I had to do in the game engine in order to get rid of the old SDL API and to replace it with the new one. The note is organized as a progressive description of the modifications, linked to the commits in GitHub. As you will see, updating the code is quite straightforward and no deep changes are required on it outside the calls to the SDL.

At the end of these modifications, the game still won’t run on my phone, actually it won’t even compile as I’ll still have to replace OpenGL direct mode with GLES equivalent and to integrate with some Android behavior (handling touch events, accessing game’s resources…). But this will be the subject of another note. So let’s go for the migration!

Note: if you are also migrating from SDL 1.2 to SDL 2, I suggest that you read the migration guide on SDL’s wiki.

Changes in the joystick API

Let’s start with an easy modification: SDL_JoystickName(int) is gone, SDL_JoystickNameForIndex(int) replaces it. See the commit.

That’s all for the joysticks! Let’s see the mouse.

Changes in the mouse API

The mouse wheel is not a button anymore and must be handled with the new SDL_MouseWheelEvent. Also, SDL_PeepEvents() works with a range of event codes, instead of an event mask as before.

Since the changes would impact every single game we did, I decided to keep the button behavior for the wheel in the engine in order to minimize the effects in the games. Thus I just map the wheel event to the equivalent mouse buttons in the engine. See the commit.

The game engine has a non conventional way of dealing with the mouse’s position as it puts the origin at the bottom left of the window and makes this position to increase when moving upward (it’s how real physicists and mathematicians represent cartasian coordinates ;-). The size of the window is needed in order to adjust the y-coordinate and was previously obtained by calling SDL_GetVideoSurface(). Once again, this function is now gone as it does not fit with the new multiple windows system. As a workaround, I use SDL_GetMouseFocus() to retrieve the window having the mouse, then SDL_GetWindowSize() to retrieve the size of this window. See the commit.

Changes in the keyboard API

The keyboard is the last input device I had to convert. The difficulty comes from the fact that text inputs are now processed with the new SDL_TextInputEvent instead of the old SDL_KeyboardEvent. The new event is by far more useful than the old approach as it allows to work with the text entered by the user instead of working with key codes and scan codes.

Since I do not need to handle text in my game and since the engine is far from able to handle Unicode, I chose again to prefer a quick solution instead of a perfect one. The events are thus handled as if each char they carry was a separate input.

The other keyboard-related changes are easier as they mainly consist into replacing identifiers which have been renamed or became useless in SDL 2:

  • SDL_GetKeyState() is renamed SDL_GetKeyboardState().
  • SDL_EnableKeyRepeat() is gone.
  • SDL_EnableUNICODE() is gone.
  • SDLMod is now SDL_Keymod.
  • The following key codes have been renamed or removed:
    • SDLK_KP[0-9]SDL_KP_[0-9]
    • SDLK_BREAK is gone.

Here is the commit with these changes.

And that’s all it needs to port the input handling of the engine! You may have noticed that there are no touch events there. The reason is that at this moment I focused on having something which compiles and runs well. New features, like handling SDL_TouchFingerEvent, has been integrated later.

Changes in the video API

The video part of the SDL has received a lot of changes with the version 2 and almost everything is different from the old API. Hopefully these changes impact mainly the people who use SDL structures to render their scenes. If you use OpenGL to render your scene, like I do, you won’t have a lot of changes to do :)

So let’s start with the beginning: creating a window. The old SDL_SetVideoMode() is gone and has been replaced with SDL_CreateWindow(), which will create an SDL_CreateWindow. This new function does not automatically create the GL context, thus we have to pass the window to a call to SDL_GL_CreateContext() in order to create it.

Also, SDL_WM_SetCaption() is gone and the title of the window can be given directly to SDL_CreateWindow(). If you still need to change the title of a window, you can use SDL_SetWindowTitle() to do the job.

The game engine tries to find the best dimensions for the window by ensuring that it does not go outside the user’s screen or, if the game runs full screen, by ensuring that the selected video mode is the one that applies a minimal distortion to the sprites. The size of the user’s screen was previously obtained by calling SDL_GetVideoInfo() before creating the window and I have to say that this approach felt kind of strange, as the caller had to ensure it was called before setting the video mode, otherwise it would return the video mode effectively set. Hopefully this function is now gone and SDL_GetDesktopDisplayMode() has been added to do the job. The same goes for SDL_ListModes which is replaced by two functions: first we get the number of available display modes with SDL_GetNumDisplayModes then we call SDL_GetDisplayModes to obtain their details.

Finally, since the engine renders with OpenGL, I had to replace the call to SDL_GL_SwapBuffers() by SDL_GL_SwapWindow().

See the commit of these changes.

That’s all? What’s next?

That’s indeed all I needed to do to go from SDL 1.2 to SDL 2, and thanks to the great documentation accompanying the library, there was no major difficulty in the process. Still, it is not enough to have the game running on my phone, thus the next part will be about the conversion from OpenGL direct mode to GLES, the last missing functionality for the compilation. Then we will build the Android application and start to play!