4 pasos para optimizar juegos Android en GameMaker

GameMaker-Studio

Justo hoy me ha llegado a casa una tablet china de perfil bajo y no he podido evitar probar algunos de mis juegos y debo decir que me he llevado una decepción por lo mal que andaban.

Lo primero que he pensado es que la tablet debía ser muy mala, pero tampoco tanto, así que he decidido descargar algunos juegos para constatar si era problema de mi código o algo general.

La mayoría iban bastante lentos, pero curiosamente el Geometry Dash (uno de esos juegos de referencia en la actualidad) iba fluido, y ésto ha hecho preguntarme ¿cómo es posible que un juego de arcade lleno de animaciones y colores vaya el doble de fluido que mi sopa de letras? ¿es posible tal nivel de optimización? Ya sé que soy novato, pero he llegado a la conclusión de que no era normal y necesitaba investigar.

Así es como después de mucho rato he encontrado este post que me ha llevado directo al artículo oficial de YoYo Games: Optimising The Draw Pipeline, y entonces, he comenzado a comprender un poco cuál es la chispa que le falta a mis juegos para funcionar fluidos casi en cualquier dispositivo por muy mal hecho que esté mi código 🙂

En el artículo en cuestión te dan 5 proyectos, empezando por una base que funciona muy lenta y lo van mejorando poco a poco hasta multiplicar varias veces el rendimiento. Yo ni corto ni perezoso los he ejecutado todos en la nueva tablet china y a continuación os expongo los resultados.

Proyecto 1

Nos encontramos ante un juego simple en el que se crean varias instancias de un objeto que se mueve aleatoriamente. Cuando se crean concretamente 1000 objetos el dispositivo ya va colapsado (tablet lenovo).

test1

Proyecto 2

Se empieza optimizando en base a las transparencias, ya que éstas gastan muchos recursos:

///object0.Create
draw_enable_alphablend(false);
draw_set_alpha_test(true);
draw_set_alpha_test_ref_value(128);

En este punto todavía no he notado ninguna mejora.

Proyecto 3

Desactivamos el dibujo de la capa de aplicación y activamos el color de fondo (o saldrán rastros en los objetos en movimientos).

///object0.Create
application_surface_draw_enable(false);

///object0.DrawGUI
 texture_set_interpolation(false);
 draw_set_alpha_test(false);
 draw_surface_stretched(application_surface, 0, 0, ww, hh);
 draw_set_alpha_test(true);
 texture_set_interpolation(true);

test3

Proyecto 4

Creando un shader por defecto que se encargue de optimizar el juego… Sólo hay que crear uno y añadirlo en dos objetos, al principio y al final del orden de objetos en la room:

///object_ShaderBegin.Draw
shader_set(shader0);

///object_ShaderEnd.Draw
shader_reset();

///shader0.Fragment
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
vec4 col = texture2D( gm_BaseTexture, v_vTexcoord );
if (col.a < 0.5) discard;
gl_FragColor = col;
}

EDITADO: Este shader obviará las transparencias y causará que los sprites y efectos se vean incorrectamente.

test4

Proyecto 5

Si utilizamos un segundo shader de paso para dibujar la superficie sin transparencias conseguimos picos aún más altos:

///object0.DrawGUI
shader_set(shader1);
texture_set_interpolation(false);
draw_set_alpha_test(false);
draw_surface_stretched(application_surface, 0, 0, ww, hh);
draw_set_alpha_test(true);
texture_set_interpolation(true);
shader_reset();

///shader0.Fragment
 varying vec2 v_vTexcoord;
 varying vec4 v_vColour;

void main()
 {
    vec4 col = texture2D( gm_BaseTexture, v_vTexcoord );
    if (col.a < 0.5) discard;
    gl_FragColor = col;
 }

///shader1.Fragment
 varying vec2 v_vTexcoord;
 varying vec4 v_vColour;

void main()
 {
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
 }

test6

Conclusión

Después de estas optimizaciones se ha conseguido aumentar el rendimiento del proyecto de pruebas casi en 5 veces, de 4 FPS a 17 y de 4 FPS Reales a 21.

Personalmente todavía tengo experimentar más para entender bien qué hace cada línea, pero lo que está claro es que funciona, así que lo primero que he hecho ha sido actualizar mi juego de Hexagon Tribute y he conseguido subir los FPS a casi el doble, algo que no está nada mal.