Con Flutter, podemos realizar todo tipo de aplicaciones sobre todo enfocadas al ámbito móvil, pero, también podemos utilizar el mismo proyecto para desarrollar no solamente en Android e iOS, si no, de escritorio para Linux, MacOS y Windows, y también para desarrollo web realizando cambios sutiles en el proyecto a nivel de código, aunque, Flutter va mucho más allá con Flame.
Flame, es un motor para crear juegos en 2D con Flutter; su instalación es extremadamente sencilla ya que, Flame no es más que un paquete pub; por lo tanto, con esto, podemos crear juegos en 2D con Flame para móvil, escritorio y web.
Con Flame, podemos crear componentes, que vienen siendo los equivalentes a los widgets en Flutter y en donde los componentes no son más que un elemento de nuestro juego, como un jugador, un enemigo, el fondo, un consumible, etc; y cada componente, contiene la implementación para el funcionamiento del mismo; por ejemplo, en el caso de un player o jugador, contiene la lógica para moverlo, cambio de animaciones, control de las vidas, consumibles, etc; y mediante una clase maestra, podemos organizar toda la lógica de estos componentes.
Este libro es mayoritariamente práctico, iremos conociendo los fundamentos de Flame en base a pequeños ejemplos hasta lograr conocer lo suficiente de la librería para crear un juego en 2D sencillo.
Flame es un motor de juego 2D de código abierto construido en el lenguaje de programación Dart y se utiliza junto con el framework de Flutter como un plugin más; por lo tanto, podemos usarlo para crear juegos en dispositivos móviles, de escritorio y web.
Este motor de juego proporciona herramientas y componentes para manejar la lógica del juego, la animación de sprites, la detección de colisiones, la entrada del usuario mediante eventos taps, teclado, joystick y la física del juego; como la gravedad, saltos, caidas, etc.
Con Flame, se pueden crear juegos 2D con gráficos impresionantes y un alto rendimiento en dispositivos móviles y de escritorio; por lo tanto, con un solo proyecto, podemos usarlo para llevar nuestro juego para las distintas plataformas soportadas por Flutter.
Flame también dispone de una serie de plugins que podemos usar para manejar el audio entre otros:
En resumen, se puede utilizar Flame con Flutter para crear y desarrollar juegos 2D con gráficos atractivos y un alto rendimiento en dispositivos móviles y de escritorio, dándoles a los desarrolladores una herramienta valiosa para crear una amplia variedad de juegos y aplicaciones.
Con Flame, podemos crear componentes, que vienen siendo los equivalentes a los widgets en Flutter y en donde los componentes no son más que un elemento de nuestro juego, como un jugador, un enemigo, el fondo, un consumible, etc; y cada componente, contiene la implementación para el funcionamiento del mismos; por ejemplo, en el caso de un player o jugador, contiene la lógica para moverlo, cambio de animaciones, control de las vidas, consumibles, etc; y mediante una clase maestra, podemos organizar toda la lógica de estos componentes.
Este libro es mayoritariamente práctico, iremos conociendo los fundamentos de Flame en base a pequeños ejemplos hasta lograr conocer lo suficiente de la librería para crear juegos senillos en 2D; como peudes ver en cada una de las secciones que componen el curso y libro, creamos diversas aplicaciones que tienen características en comunes como el uso de los sprites, sprites animados, sprites sheet, animaciones, colisiones, entrada… pero, viendolo desde enfoques distinto, lo cual es crucial para entender de una manera prática cada una de las funcionalidades de Flame y obtener un mejor entendimiento de todo el potencial de Flame.
Este curso tiene un enfoque práctico, conociendo los aspectos claves de la tecnología y pasando a la práctica, implementando de a poco pequeñas características y funcionalidades que pueden ser adaptadas a un juego real; por lo tanto, puedes ver el curso como un conjunto de guías o tutoriales en las cuales aprenderemos a manejar poco a poco Flame.
El curso y libro tienen un total de 14 secciones/capitulos, se recomienda que leas en el orden en el cual están dispuestos y a medida que vayamos explicando los fundamentos de Flame en base a ejemplos; una vez domines la librería, puedes consultar las secciones en el orden que desees.
En el curso, veremos en base a ejemplos reales, como animar sprite, vairar animaciones e implementar la lógica para tus primeros juegos en 2D.
Puedes ver cada una de las introducciones del curso y libro en:
Tanto el curso como el libro aun se encuentra en desarrollo.
Por aquí tienes el listado completo de clases que vamos a cubrir en el libro y curso:
Vamos a crear un proyecto en Flutter y agregar Flame.
Vamos a mostrar un sprite/imagen en Flutter con Flame.
Vamos a mostrar un circulo en Flutter con Flame.
Vamos a mostrar un rectángulo en Flutter con Flame.
Vamos a mostrar un circulo en Flutter con Flame.
Vamos a conocer el uso básico de la función de update.
Vamos a mostrar una imagen mediante un componente.
Vamos a modificar la posición de un sprite.
Conoceremos cómo usar el teclado para la clase FlameGame.
Conoceremos cómo usar el teclado a nivel de componente.
Vas a realizar el movimiento del sprite mediante las teclas asdw y flechas.
Vamos a conseguir imágenes para el juego.
Vamos a aprender a generar nuestros sprite sheets.
Vamos a cargar un sprite sheet en la aplicación de Flutter.
Vamos a hablar de los factores claves para generar un listado animado de sprites en base a posiciones.
Vamos a crear la función para generar un sprite animado.
Vamos a realizar algunas pruebas con la función anterior cargando una animación.
Vamos a definir el resto de las animaciones que se encuentran disponibles en el sprite sheet.
Vamos a trabajar con el evento tap a nivel de la clase tipo Game.
Vamos a trabajar con el evento tap a nivel del componente.
Vas a realizar un cambio de animación cada vez que se realice un toque en la pantalla.
Vas a implementar el movimiento en el eje de las X y varias la animación en consideración.
Vamos a implementar la velocidad constante usando el dt al momento de desplazarse.
Vamos a combinar teclas para correr.
Vamos a dibujar un círculo mediante un PositionComponent.
Vamos a mover el círculo a un extremo.
Vamos a conocer cómo manejar las colisiones entre el círculo y los extremos de la pantalla.
Vamos a invertir la dirección de desplazamiento del círculo al colisionar con los bordes de la pantalla.
Como reto, debes de al menos analizar cómo podemos colisionar entre figuras y aplicar alguna lógica.
Vamos a colocar un contador de colisiones.
Conoceremos como usar las colisiones en los sprite.
Vamos a crear un nuevo proyecto y presentar la estructura base del nuevo proyecto.
Vamos a generar círculos cada cierto tiempo generados de manera aleatoria.
Vamos a evitar que el player se salga de la pantalla.
Vamos a cambiar la animación cuando el player entra en contacto con el borde de la pantalla.
Vamos a ajustar el ángulo de los círculos al generar los mismos.
Vamos a implementar un sencillo esquema de gravedad sobre el player.
Vamos a remover los círculos de colisión cuando ya no sean visibles.
Vamos a implementar la habilidad de salto usando la gravedad para el carácter.
Vamos a crear una clase con las primitivas que luego vamos a sobrescribir.
Vamos a convertir los círculos en meteoritos animados.
Vamos a generar un contador para las colisiones.
Introducción
Vamos a aprender a cambiar el color de fondo de la ventana.
Vamos a aprender a cambiar el color de fondo de la ventana.
Vamos a establecer una imagen de fondo mediante una clase aparte.
Vamos a realizar algunas pruebas variando el tamaño de fondo del componente.
Vamos a conocer como se carga un componente y escuchar cuando él mismo ha sido cargado; aparte de, consultar sus propiedades.
Vamos a actualizar el juego para que no pueda escapar por los bordes impuestos por el fondo y no por la ventana.
Vamos a aprender a mover la cámara en base a la posición del player.
Vamos a adaptar el componente de meteorito para que se adapte a la posición de la cámara y tamaño de la ventana.
Vamos a introducir algunos conceptos claves y herramientas a utilizar.
Vamos a crear un mapa con Tiled Map Editor.
Vamos a crear la estructura de un proyecto base en Flutter Flame.
Vamos a cargar el mapa anterior en un nuevo proyecto en Flutter con Flame.
Con la capa de objetos definida antes, vamos a usarla para crear PositionComponent.
Vamos a realizar algunos cambios en el código fuente de la app para adaptarlo al mapa tile.
Vamos a realizar algunas adaptaciones para detectar cuando el player esta saltando.
Vamos a realizar modificaciones adicionales para modificar el desplazamiento y adaptar el salto.
Vamos a modificar la animación de salto para que no se mantenga en un loop.
Vamos a realizar algunas pruebas para el desplazamiento del player con los tiles y el componente de hitbox del player.
Vamos a actualizar el mecanismo de desplazamiento horizontal del player al del vector de velocidad.
Vamos a crear componentes individuales de hitbox para el player.
Vamos a agregar el componente de meteorito en el juego.
Vamos a cambiar la inicialización de la posición del player.
Vamos a actualizar el esquema creado para realizar el desplazamiento.
Vamos a actualizar el esquema creado para realizar el desplazamiento.
Vamos a presentar el uso de los overlays para superponer widgets.
Vamos a crear el overlay para el game over.
Vamos a mostrar la comunicación entre los componentes y el overlay.
Vamos a mostrar la comunicación entre los overlays y los componentes.
Vamos a conocer algunas funciones claves para usar los overlays.
Vamos a conocer el problema del conteo con las colisiones entre el player y los meteoritos.
Vamos a conocer los tipos de colisiones y cómo adaptarlo al juego.
Vamos a crear una función para reiniciar parámetros del player.
Vamos a crear un contador de vidas en el overlay.
Vamos a reiniciar el nivel al detectar que el player quedó sin vida.
Vamos a implementar la función de pausar el juego.
Vamos a colocar un botón para reiniciar el nivel.
Vamos a modificar la implementación del movimiento para que la actualización de la propiedad de position se realice solo en la función de update.
Vamos a crear una función para bloquear los movimientos del player.
Vamos a crear una función para volver al player como invencible.
Vamos a modificar el mapa, para colocar algunos consumibles.
Vamos a implementar el consumo de items.
Vamos a pintar los consumibles en el mapa.
Vamos a implementar la lógica para ganar una vida.
Al momento de hacer el reload del juego, debemos de recargar los consumibles.
Vamos a solventar el problema que dejamos de antes al momento de sobrescribir los consumibles.
Vamos a implementar la lógica para la invencibilidad del usuario y de ganar.
Vamos a realizar algunos cambios en la función de reiniciar el juego.
Vamos a bloquear los movimientos del player fuera del entorno del mapa.
Vamos a colocar una imagen de fondo.
Vamos a corregir el problema de que el player puede quedar desnivelado al pisar los tiles.
Vamos a usar la función de clamp para controlar la velocidad de caída del player.
Hablaremos sobre el siguiente desarrollo a llevar a cabo.
Calculamos otro hitbox para el player y removemos el de foot.
Comenzamos implementando los nuevos cambios.
Vamos a terminar la implementación anterior.
Explicamos el detalle de los centros de colisión.
Explicamos cómo calcular la normal de la colisión.
Explicamos cómo calculamos la separación entre colisiones.
Explicamos cómo calculamos el producto escalar.
Crearemos los archivos y configuración base para el proyecto.
Vamos a crear las animaciones del player.
Vamos a implementar el movimiento del player al presionar las teclas.
Vamos a mostrar otra implementación para el movimiento.
Vamos a solventar el problema de cuando dejamos de desplazarnos el player apunta siempre hacia la misma dirección.
Crearemos el mapa para nuestro juego.
Vamos a utilizar el mapa anterior en el proyecto.
Vamos a definir el apartado de los objetos en el mapa para que puedan ser colisionables.
Vamos a usar definir que la cámara siga al player y definir límites.
Vamos a implementar la lógica para las colisiones iniciales.
Vamos a ver otra implementación para manejar las colisiones.
Vamos a conocer la implementación final.
Vamos a conocer otra variante del esquema anterior, en la cual, prescindimos de una propiedad.
Vamos a trabajar en la colisión doble.
Vamos a definir los límites de la pantalla con el player.
Vamos a colocar el player en su posición en base a lo establecido en el mapa.
Vamos a variar el tamaño del hitbox del player.
Vamos a implementar la función de correr.
Crearemos la clase base para los enemigos con la función de cambio de posición.
Crearemos una clase para crear un enemigo en pantalla.
Vamos a cambiar el sprite del enemigo por un zombie.
Vamos a tratar el problema que el player escapa del mapa y cae al vacío.
Vamos a crear el archivo en el cual, mantendremos el tipo de movimiento, el patrón y la cantidad de enemigos.
Vamos a implementar la función para mover al enemigo por patrones.
Vamos a terminar las implementaciones anteriores y probar.
Vamos a crear la capa de enemigos en el mapa.
Crearemos la capa de esqueleto.
Vamos a usar la capa de enemigos del mapa.
Hablaremos sobre el proyecto.
Vamos a conocer cuales son las imágenes iniciales vamos a usar.
Vamos a crear la clase base para las plantas.
Vamos a crear la estructura para la primera planta.
Vamos a crear la estructura para la segunda planta.
Vamos a agregar una planta por un toque.
Vamos a diseñar el mapa para nuestro juego.
Vamos a cargar el mapa en el componente.
Vamos a realizar los cambios necesarios para manejar dado un tap en el componente de seed, agregar una planta desde FlameGame.
Vamos a agregar una planta desde SeedComponent dado un click.
Vamos a alinear las plantas agregadas en base a la posición del SeedComponent.
Vamos a escalar el tamaño de las plantas para que ocupe el tamaño del SeedComponent.
Crearemos la clase para definir el zombie.
Crearemos un componente tipo zombie para agregar en el mapa.
Crearas otro componente de zombie.
Vamos a realizar la lógica para definir los zombies por niveles.
Vamos a realizar la lógica para agregar zombies en el mapa.
Vamos a crear la lógica para saber si un canal está ocupado o no.
Vamos a colocar la animación de las plantas en modo ataque al detectar un zombie en el canal.
Vamos a crear las bases para crear el proyectil para la planta.
Vamos a realizar la implementación para disparar.
Vamos a variar la posición inicial de la planta.
Vamos a definir las propiedades de vida y daño en los componentes de zombies y plantas.
Vamos a realizar la implementación en la cual, la planta ataca al zombie mediante el proyectil.
Vamos a detener al zombie apenas esté en contacto con la planta para que luego inicie el ataque.
Vamos a realizar la implementación en la cual, el zombie ataca a la planta.
Vamos a crear un par de animaciones más para mostrar otros estados del zombie.
Vamos a modificar el hitbox del zombie para que no ocupe dos canales.
Vamos a bloquear el espacio ocupado por un zombie para no poder sembrar en ella.
Vamos a habilitar el componente de cámara y mundo al juego.
Vamos a crear el componente para implementar el evento drag.
Vamos a implementar el evento drag.
Vamos a implementar el drag de la cámara.
Vamos a agregar las plantas y zombies al mundo.
Vamos a dar una implementación del desarrollo que vamos a realizar.
Vamos a calcular el factor de reescalado.
Vamos a acomodar el escalado con el fondo y los soles.
Vamos a acomodar el escalado con el seed.
Vamos a acomodar el escalado con las plantas.
Vamos a acomodar el escalado con los zombies.
Vamos a crear el overlay para mostrar las plantas seleccionables.
Vamos a crear la lógica para mostrar una planta seleccionada.
Vamos a mostrar un borde para la imagen seleccionada.
Vamos a crear el componente para manejar los soles.
Vamos a variar el movimiento de las plantas en el eje de las X para que sea ondulado.
Vamos a crear un contador para los soles.
Vamos a crear un overlay para los soles.
Vamos a realizar el descuento por el costo de las plantas al agregarlas en el campo.
Vamos a agregar un detalle visual a las plantas en el overlay para cuando no existan soles, colocar una opacidad a la planta.
Vamos a generar los soles en el espacio del mapa.
Vamos a crear el contador con un container que se superponga a las plantas en el overlay para poder agregar plantas cuando se cumpla un tiempo desde la última interacción.
amos a crear un widget reutilizable para el desarrollo anterior.
Vamos a mostrar la animación del overlay al momento de agregar la planta en el mapa.
Vamos a bloquear el acceso a las plantas al momento de que inicie la animación.
Vamos a corregir una de las imágenes del juego.
Vamos a corregir una de las imágenes del juego.
Al agregar una planta se bloquean todas las plantas, vamos a hacer este bloqueo de manera individual.
Vamos a colocar que la duración de carga para cada planta es individual y personalizable.
Vamos a acomodar los bordes de la planta para que el overlay se ajuste correctamente si está o seleccionada.
Implementaremos la opción de pausar el juego.
Implementaremos la opción de reiniciar el juego.
Veremos una presentación del evento Drag que será necesario para poder desplazar la cámara.
Vamos a crear el proyecto en Flame.
Vamos a descargar e instalar las capas para el fondo parallax en el proyecto. https://craftpix.net/freebies/free-cartoon-parallax-2d-backgrounds/
Vamos a crear un componente para superponer los fondos.
Vamos a conocer cómo desplazar las capas del parallax.
Vamos a conocer cómo desplazar cada capa a velocidades distintas y lograr la sensación de profundidad y con esto, el efecto parallax.
Crearemos ahora un componente aparte en un archivo para el fondo parallax.
Crearemos la clase base para el player. https://www.deviantart.com/ottojoy/art/Shark-Sprites-434969176
Crearemos la animación del player en base al sprite sheet.
Crearemos el hitbox base para el player.
Implementamos en movimiento hacia los lados y arriba/abajo para el player.
Vamos a implementar que el player rota 90 grados por vez al presionar la tecla R.
Vamos a hacer el flip vertical en la rotación a la derecha/izquierda.
Hablaremos sobre la importancia de tener una estructura sólida, limpia y escalable para desarrollar las distintas funcionalidades del juego.
Presentaremos parte de la solución a llevar a cabo para la creación de dulces en cualquiera de los lados de la pantalla.
Vamos a implementar la primera parte del archivo de ayuda para construir un alimento por pantalla.
Vamos a implementar la primera parte del archivo de ayuda para construir un alimento por pantalla.
Explicamos de manera básica el componente de alimento.
Empezamos a crear las bases del componente de alimento.
Calcularemos la posición de incidencia del dulce.
Vamos a definir la lógica para agregar los dulces en el main.
Vamos a remover los dulces que no sean visibles en la pantalla.
Vamos a verificar unas cotas máximas al momento de generar las posiciones.
Vamos a crear el hitbox para la boca del player.
Vamos a detectar la colisión entre la boca y el alimento.
Vamos a reproducir la animación de masticando por un tiempo determinado especificado en el alimento.
Vamos a colocar una regla adicional en la cual el player no pueda consumir alimentos mientras mastica.
Vamos a colocar una regla adicional en la cual el player solamente pueda consumir alimentos en el mismo ángulo del alimento.
Vamos a crear una propiedad adicional para manejar el puntaje personalizado para cada dulce.
Vamos a implementar las propiedades para manejar las estadísticas y la lógica para actualizarlas.
Creamos el overlay para las estadísticas.
Vamos a implementar las bases (los métodos y sus parámetros) para los tipos de juegos.
Vamos a implementar las bases (los métodos y sus parámetros) para los tipos de juegos.
Implementamos la primera jugabilidad, si el player pierde un dulce, pierde.
Implementamos la segunda jugabilidad, en la cual el player tiene que conseguir una cantidad determinada de puntos.
Implementamos la tercera jugabilidad, en la cual el player solo puede consumir un tipo de dulce.
Implementamos la cuarta jugabilidad, en la cual el player no puede consumir un tipo de dulce.
Vamos a implementar un argumento adicional para verificar si el dulce fue consumido o perdido.
Vamos a crear la estructura para probar la implementación anterior.
Probaremos la 1 implementación.
Probaremos la 2 implementación.
Aplicaremos algunos cambios en la estructura de la aplicación.
Probaremos la 3 implementación.
Probaremos la 4 implementación.
Vamos a crear una función para manejar todos los niveles del juego.
Vamos a crear una función para cargar los niveles y hacer el reset.
Vamos a crear el overlay para el fin de juego.
Vamos a mostrar el overlay anterior en base a algunas acciones.
Vamos a implementar las acciones del jueogo, pausar y reiniciar.
Crearemos el overlay para seleccionar niveles.
Crearemos el overlay para seleccionar la jugabilidad.
Vamos a mostrar el nivel y tipo de juego en el overlay de estadísticas.
Vamos a mostrar el nivel y tipo de juego en el overlay de estadísticas.
Vamos a implementar desde la función de GameOver evaluar la lógica según el tipo de juego seleccionado.
Implementamos la lógica para ir al siguiente nivel.
Hablaremos sobre los huds a desarrollar en esta sección y daremos una demostración.
Vamos a implementar el joystick.
Vamos a implementar la movilidad del player mediante el joystick.
Vamos a implementar un botón para ser usado en la pantalla táctil o mediante un ratón.
Vamos a implementar la rotación mediante el botón virtual.
Vamos a guardar de manera persistente el nivel y tipo de juego y que se cargue el último estado al abrir la aplicación.
Vamos a eliminar las instancias de los alimentos al hacer el reset.
Vamos a hablar sobre posibles cambios que puedes realizar para adaptar el juego a pantallas de pequeñas dimensiones.
Hablamos sobre el paquete que vamos a utilizar.
Vamos a realizar algunas pruebas con el paquete de gamepads.
Vamos a implementar las reglas para que podamos emplear el gamepad en el juego.
Presentaremos el uso del paquete con el cual, podemos manejar los audios en Flame.
Definimos el sonido de fondo.
Definimos el sonido para las acciones.
Vamos a conocer cómo reproducir sonidos en bucle.
Vamos a conocer cómo reproducir sonidos en bucle.
Juego 2 - Dino Jump: Consumibles
Vamos a colocar el plugin para manejar el audio y colocar los audios iniciales.
Vamos a implementar un sonido para cada instancia del zombie.
Vamos a colocar un sonido para cada zombie.
Vamos a hablar sobre un problema con los sonidos en ambiente de desarrollo.
Vamos a detectar cuando acaba el juego, esta función es necesaria para la siguiente implementación que veremos en el siguiente video.
Vamos a reproducir un sonido global cuando existan zombies en los canales.
Colocaremos los audios para el juego.
- Andrés Cruz
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter
Acepto recibir anuncios de interes sobre este Blog.
!Cursos desde!
4$
En Academia
Ver los cursos!Libros desde!
1$
Ver los libros