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 renamedSDL_GetKeyboardState()
.SDL_EnableKeyRepeat()
is gone.SDL_EnableUNICODE()
is gone.SDLMod
is nowSDL_Keymod
.- The following key codes have been renamed or removed:
SDLK_KP[0-9]
→SDL_KP_[0-9]
SDLK_[LR]SUPER
→SDL_[LR]GUI
SDLK_PRINT
→SDLK_PRINTSCREEN
SDLK_NUMLOCK
→SDLK_NUMLOCKCLEAR
SDLK_SCROLLOCK
→SDLK_SCROLLLOCK
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!