Como utilizar un Sprite Sheet en Flutter con Flame 13 - Juegos 2D animados

- Andrés Cruz

In english
Como utilizar un Sprite Sheet en Flutter con Flame 13 - Juegos 2D animados

Un sprite no es más que un objeto o personaje y son muy utilizados en cualquier motor de videojuegos como Unity; en el desarrollo de videojuegos, los sprites es donde están incluidos todos los movimientos (estados) de un personaje u objeto; por lo tanto, es común que para un juego 2D existan múltiples imágenes para cada objeto animable. 

nos interesa no solamente procesar una sola imagen, sino, varias de ellas, para ello, utilizaremos una imagen que conste de varias imágenes, como la generada anteriormente.

Un sprite sheet es una imagen que contiene varios sprites o imágenes más pequeñas utilizadas en el desarrollo de juegos en 2D. Los sprites shhets suelen representar objetos , personajes y elementos del juego, y pueden ser estáticos o animados. La hoja de sprites permite que el juego cargue varias imágenes necesarias para el juego de una sola vez, lo que puede mejorar la eficiencia en la carga y el rendimiento general del juego. Al tener todas las imágenes en una sola imagen, facilita la gestión y organización de los recursos gráficos en el desarrollo de juegos en 2D.

Caso práctico

Finalmente, a nivel de nuestro código, crearemos la siguiente clase:

lib/components/player_sprite_sheet_component.dart

import 'package:flame/sprite.dart';
import 'package:flutter/material.dart';

import 'package:flame/flame.dart';
import 'package:flame/components.dart';

import 'dart:ui';


class PlayerSpriteSheetComponent extends SpriteComponent {
  late double screenWidth, screenHeight, centerX, centerY;
  final double spriteSheetWidth = 680, spriteSheetHeight = 472;

  @override
  Future<void>? onLoad() async {
    //sprite = await Sprite.load('tiger.png');

    final spriteImage = await Flame.images.load('dino.png');
    final spriteSheet = SpriteSheet(image: spriteImage, srcSize: Vector2(spriteSheetWidth, spriteSheetHeight));

    sprite = spriteSheet.getSprite(2, 1);

    screenWidth = MediaQueryData.fromWindow(window).size.width;
    screenHeight = MediaQueryData.fromWindow(window).size.height;

    size = Vector2(spriteSheetWidth, spriteSheetHeight);

    centerX = (screenWidth / 2) - (spriteSheetWidth / 2);
    centerY = (screenHeight / 2) - (spriteSheetHeight / 2);

    position = Vector2(centerX, centerY);

    return super.onLoad();
  } 
}

Explicacion del codigo anterior

Como puedes apreciar en el código anterior, definimos el tamaño para cada sprite de nuestro sprite sheet; para la imagen que seleccionamos, sería de 680 píxeles x 472 píxeles:

Para ello, usamos un par de propiedades:

late double spriteSheetWidth = 680.0, spriteSheetHeight = 472.0;

Es importante notar que, debes de especificar el tamaño acorde al sprite que estés utilizando.

Cargamos el sprite sheet:

var spriteImages = await Flame.images.load('dino.png');

Y definimos el spriteSheet para que pueda ser manipulado mediante una propiedad; es en este paso que, utilizamos las dimensiones individuales de cada estado:

final spriteSheet = SpriteSheet(image: spriteImages, srcSize: Vector2(spriteSheetWidth, spriteSheetHeight));

Finalmente, ya es posible consultar de manera individual cada posición de uno de los pasos del sprite sheet:

sprite = spriteSheet.getSprite(1, 1);

Existen sprite sheet con tamanos distintos para cada frame o sprite, por lo tanto, debes de estar seguro que el sprite sheet que estas usando tienen los mismos tamanos para cada uno de los sprite, en este ejemplo es de 680z472 px.

Cargar un Sprite

Tambien es posible cargar sprite usando la función de load; se usa la función loadSprite de la clase Flame para cargar el sprite: sprite = await Flame.images.load('imagen.png');

Una vez cargado el sprite, podrías utilizar el componente SpriteComponent para renderizarlo en el juego como si fuera un componente; esto puede parecer poco pero, al usar los componentes de Flame, podemos usar carácteristicas como el sistema de colisiones, entrada de datos y en general, cualquier funcionalidad disponible en una clase PositionComponent.

Aquí te dejo un ejemplo de cómo cargar un sprite en Flame:

import 'package:flame/components/sprite_component.dart';
import 'package:flame/flame.dart';
class MyGame extends BaseGame {
 SpriteComponent _spriteComponent;
 MyGame() {
   _loadSprite();
 }
 void _loadSprite() async {
   var image = await Flame.images.load('ruta/a/la/imagen.png');
   _spriteComponent = SpriteComponent.fromImage(0, 0, image);
   add(_spriteComponent);
 }
}

Este código creará un nuevo juego (MyGame) y cargará un sprite utilizando la función load de Flame, y lo renderizará en el componente SpriteComponent.

Recuarda que este material es parte de mi curso y libro en Flame para la creación de juegos en 2D.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.