Memory game con Flutter

Últimamente, he estado echando un ojo a Flutter. Hay mucha gente que me ha hablado de sus bondades tanto para el desarrollador (haciéndolo más productivo) como para el usuario final (ofreciendo un buen rendimiento).

En lugar de aventurarme a hacer una app de un temática nueva, he preferido volver ha hacer un juego de memoria, exactamente igual que el que hice con dotNet MAUI, de esta manera, podría compararlos y sacar mejores conclusiones.

A continuación os dejo algunos GIF en los que podéis ver el diseño y comportamiento de la app. Y también os informo de los detalles más destacados de la aplicación.

Aplicación en acción

Paquetes utilizados

  • intl: Lo utilizo para implementar la internacionalización de la aplicación. Es decir, añadir los textos en los distintos idiomas.
  • cupertino_icons: Paquete con los iconos utilizada en la app. Muy cómodo para no tener que añadir las imágenes una por una como assets.
  • provider: Es el gestor de estados que utilizo. Dado que he implementado un patrón MVVM, cada provider hace las funciones de ViewModel en cada una de las features.
  • get_it: Simplemente lo uso para el registro y la resolución de dependencias. En mi caso, los servicios de navegación y diálogos.
  • vsync_provider: Util para facilitar la gestión de animaciones desde un provider.
  • lottie: Permite lanzar las animaciones lottie ejecutadas en el popup que se muestra cuando el juego ha finalizado.
  • flutter_native_splash: Paquete para facilitar la creación de una splash a partir de una imagen y un color.

Además, he utilizado el paquete de desarrollo flutter_launcher_icons para facilitarme la creación de iconos en las distintas plataformas.

Controles

A pesar de que en Flutter todo son widget, me gusta aislar algunos como controles, que son normalmente lo que reutilizaré en varias páginas o, simplemente, por su funcionalidad prefiero separarlos como un control.

  • Background: Este control contiene el fondo que aparece en todas las pantallas, con un degradado y aplicando un padding a los controles que aparecen en la página.
  • ThemeButton: Botón que se utiliza en la pantalla de selección del tema, que tiene una imagen de fondo y un botón. Permite personalizar los bordes y la alineación horizontal del botón.
  • TitleText y SubtitleText: Textos con los estilos establecidas para usar como títulos o subtítulos en las distintas pantallas.
  • CustomButton: Botón personalizado, con bordes redondeados, que muestra un indicador de actividad cuando así se le indica.
  • RoundedButton: Botón circular que contiene un icono. Se utiliza en los botones para navegar atrás y cerrar el popup. Al igual que el anterior, puede mostrar un indicador de actividad, en lugar del icono, cuando así se indica.
  • GameCard: Tarjeta que aparece en el tablero del juego. Permite indicar la ruta de la imagen que se va a mostrar, así como un controlador para mostrar y ocultar su contenido.
  • CircleProgessBar: Muestra una barra de progreso circular. Utilizado para indicar el tiempo que queda para descubrir todas las parejas del tablero. Aunque no es necesario, ya que se podría haber usado un widget, se ha implementado pintando líneas directamente con Skia, heredando de CustomPainter.

Nótese, que estos controles no tienen un provider asociado, por lo que, en el caso de necesitarlo, gestiono su estado con un stateful widget.

Features

Aquí se aloja el grueso de la funcionalidad de nuestra aplicación. Para poder implementar el patrón MVVM he utilizado provider, asociando uno a cada página, el cual se crea al navegar a la página en lugar de hacerlo al inicio de la aplicación. De está manera evito tener cada provider como un singleton, ya que me gusta tener una instancia distinta con cada página y no compartan su estado, al no ser que decida la contrario por motivos funcionales.

Todas las páginas tienen un degradado de fondo, que se consigue utilizando en todas ellas el control Background presentado en el punto anterior.

Además, en todas las páginas se ha implementado una animación personalizada siempre que se navega. En la página de origen se ocultan los elementos de una manera progresiva y en la de destino se hace justo lo inverso.

Las features que existen en la aplicación son las siguientes:

  • ThemeSelector: Página inicial en la que se selecciona el tema. Se utilizan ThemeButtons para mostrar los distintos botones.
  • LevelSelector: Similar a la anterior, pero, en vez de optar por ThemeButtons, se han utilizado CustomButtons.
  • Game: En función del nivel seleccionado, se crean tableros con distintos tamaños y se ofrece más o menos tiempo al usuario para descubrir todas las parejas. Las imágenes de las tarjetas varían dependiendo del tema escogido.
  • GameOver: Popup que muestra una animación lottie y un texto, dependiendo de si el usuario ha descubierto todas las parejas o, por el contrario, se le ha terminado el tiempo.

Servicios

Son solamente dos los servicios que encontramos en la aplicación.

  • DialogService: Servicio utilizado para mostrar diálogos de aviso al usuario. Solamente se utiliza en un sitio de la app, al navegar atrás desde el tablero del juego, para preguntar al usuario si realmente desea salir y terminar la partida.
  • NavigationService: Es el encargado de realizar las distintas navegaciones entre páginas.

Más detalles

Es interesante hablar de ciertos detalles que he utilizado.

  • Recursos de textos: En inglés y castellano, seleccionando el idioma del sistema.
  • Modo claro y oscuro: Todos los colores se definen teniendo en cuenta los dos modos. Éstos se pueden encontrar en el archivo colors.dart.

Sensaciones que me deja Flutter frente a MAUI

Lo primero que tengo que decir es no soy un experto en Flutter, ni mucho menos. Estoy aprendiendo haciendo mis primeras apps y seguro que hago cosas de una manera muy compleja que tienen una solución mucho más sencilla, elegante y con mejor rendimiento.

Dicho esto, voy a hablar un poco de las sensaciones que me ha dejado esta primera toma de contacto con Flutter.

  • IDE: He utilizado VS Code, aunque también podría haber elegido Android Studio. Me he decantado por el primero porque ya lo conozco, me siento cómodo utilizándolo y es muy ligero. Nada que objetar a esta maravillosa herramienta, aunque es cierto que el intellisense de Dart puede mejorar. He echado de menos esas sugerencias que ofrece VS 2022 o la potencia de su intellisense a la hora de escribir llamadas a métodos, propiedades…
  • Lenguaje: Aquí no hay opción. Si usas Flutter tienes que usar Dart. No es un lenguaje complicado, por lo que la curva de aprendizaje no es un drama,. No obstante, he echado de menos ciertas funcionalidades de C#, aunque no he encontrado nada que no haya podido hacer, pero he tardado algo de tiempo en hacer cosas que con dotNet son inmediatas.
  • Diseño de interfaz: También se hace con Dart y se parte de la base de que todo es un widget. Hay infinidad de widgets y son muy, pero que muy personalizables. Si hay algo que quieras dibujar y no exista un widget asociado, puedes crearlo tú o buscar algún paquete que te ofrezca dicho control.
  • Control de estados: Personalmente, me gusta mucho la separación de diseño y lógica que se consigue con MVVM. En MAUI, tenemos este patrón per se, pero en Flutter lo he implementado utilizando provider. Es cierto que Flutter trae consigo la gestión de estados mediante stateful widgets, pero me he decantado por provider porque creo que se adapta más a lo que busco. En Flutter hay otros muchos gestores de estados, siendo bloc uno de los más populares. Le he echado un vistazo y tiene buena pinta, sobretodo para proyectos grandes en los que queremos que todo esté muy bien organizado.
  • Hot reload: En mi humilde opinión, este el punto que decanta la balanza a favor de Flutter. El hot reload funciona y lo hacer muy bien. Creas un proyecto, empiezas a depurar y no hacer falta que pares para casi nada. Puedes crear interfaces, añadir funcionalidades, añadir carpetas, ficheros, renombrar…sin necesidad de parar la ejecución. Simplemente guardas y la app se recarga de manera inmediata. Una maravilla.
  • Comunidad: En el poco tiempo que llevo utilizando Flutter, he apreciado que hay mucha comunidad, muchos proyecto open source y muy buena documentación. La comunidad de MAUI y dotNet es maravillosa y hay mucho material, pero es cierto que Flutter esta teniendo un hype brutal haciendo que cada vez haya más y mejor contenido en las redes.

Show me the code!!

Como siempre, aquí os dejo un enlace al repositorio del proyecto para que podáis descargarlo y jugar con él.

Deja un comentario

Este sitio utiliza Akismet para reducir el spam. Conoce cómo se procesan los datos de tus comentarios.