Cómo migrar una aplicación Android SDL2 a SDL3
Finalmente me ví obligado a migrar a SDL3, porque Google Play tiene nuevas regulaciones que obligan a los desarrolladores a subir a Android 14 (API level 34) o superior (en realidad esto está activo desde el 31 de agosto de 2024).
Ese requerimiento significa que en el build.gradle de nuestro proyecto tenemos que colocar los siguientes settings:
minSdkVersion 29 targetSdkVersion 34 compileSdkVersion 34 Luego de unas cuantas peripecias e intentos de hacer que la compilación funcione con SDL2 llegué a la conclusión que no tenía más alternativa que subir a SDL3.
El problema es que los desarrolladores de SDL3 decidieron jugar a Twilight Zone, es decir, cambiarle el nombre a todas las funciones, cambiar los parámetros, y otras cosas divertidas. El proceso de conversión iba a ser toda una aventura, por eso le estuve sacando el cuerpo todo este tiempo.
A continuación la lista de cambios que tuve que hacer, otras migraciones pueden ser más complicadas:
- Problem error: use of undeclared identifier ‘IMG_INIT_PNG’
Ya no necesitamos hacer esto antes de cargar archivos PNG:
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) ) - Problem TTF_RenderText_Solid () ahora tiene un nuevo protype:
SDL_Surface *TTF_RenderText_Solid(TTF_Font *font, const char *text, size_t length, SDL_Color fg);
Ahora necesita la longitud del string. Como yo estoy usando STL, puedo usar std::string::size() - SDL_RenderFillRect () now has a new protype:
Ahora hay que usar SDL_FRect con floats. Mi solución fue copiar y hacer casting, así:
SDL_FRect fRect = {(float) rect.x, (float) rect.y, (float) rect.w, (float) rect.h }; // de esta forma puedo usar el rect original, y luego cuando todo funcione, optimizo. La llamada queda así:
SDL_RenderFillRect(sdlRenderer, &fRect); - Problem SDL_RenderTexture () ahora tiene un nuevo protype:
Ahora hay que usar SDL_FRect con floats. Misma solución. - Problem: error: use of undeclared identifier SDL_FreeSurface (surface)
Ahora hay que usar SDL_DestroySurface (surface) - Problem: error: use of undeclared identifier ‘TTF_GetError
Hay que usar SDL_GetError() - Problem: error: use of undeclared identifier ‘TTF_FontHeight’
Hay que usar TTF_GetFontHeight () - Problem: nativeRunMain(): Couldn’t find function SDL_main in library /data/app/~~gvhpQEv…kE_NraQ==/lib/arm64/libmain.so
Solution: esto no era necesario en SDL2, ahora hay que declarar función main () de la siguiente forma:
#if ANDROID
#include
extern “C”
int main(int argc, char *argv[]) - Problem: TTF_init failed
Probé con freetype 2.9.1 and 2.13.3 y ambos se presenta el mismo problema
El problema fue que cambié: if (TTF_Init() < 0) { a => if (TTF_Init()) debió ser if (!TTF_Init()) - Problem SDL_GetCurrentDisplayMode () tiene un nuevo prototype:
const SDL_DisplayMode* displayMode = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay ()); Yo utilizo displayMode para obtener las dimesiones de la pantalla.
Conclusión: no era tan difícil como pensaba, realmente lo que hay que hacer es resolver un problema a la vez, como siempre. Algunos de estos problemas, como por ejemplo “nativeRunMain(): Couldn’t find function SDL_main in library ” son bien difíciles de resolver, ni Copilot ni Genesis, ni Stackoverflow tienen la solución. La conversión hay que hacerla con cuidado, porque si reimplementas algo incorrectamente el error es bien difícil de entender. Como el cambio con SDL_GetCurrentDisplayMode () lo hice mal la primera vez, el juego mostraba los sprites muy grandes, y luego muy pequeños. No fue obvio desde el comienzo por qué.