Videojuegos android

Tutorial videojuegos: Pool de sprites

Comparte este artículo

Hoy aprenderemos a crear Pool de sprites para mejorar el rendimiento

 

Cuando se crea un videojuego uno de los problemas con los que se encuentra un desarrollador de videojuegos es la caida de rendimiento cuando hay muchos sprites. Lo que hacemos todos al crear un videojuego con enemigos es ir creando sprites de enemigos a medida que los vamos necesitando. Cuando un enemigo muere, matamos el sprite para que se vaya al Garbage Collector. Esa forma de trabajar parece la más sencilla y la lógica, pero el rendimiento del juego cae exponencialmente.

¿Por qué noto lags durante el juego?

Si creas sprites en tiempo de juego… estás haciendo algo incorrecto. Los sprites se crean antes de comenzar el juego, si no, lo que nos ocurrirá es que aparecerán saltos ya que crear sprites es algo costoso y probablemente a nuestro motor de videojuegos no le de tiempo a renderizar la pantalla, mover sprites y además leer las texturas para crear los sprites nuevos.

Para solucionar esto viene en nuestra ayuda los pools de objetos. Primero describiremos un poco que es un pool y como se puede crear, luego pondremos un ejemplo de pool en Andengine.

¿Qué son los pools de objetos (en nuestro caso sprites)?

Realmente es un patrón de diseño. Básicamente son una estructura de datos donde metemos un conjunto de sprites antes de comenzar el juego y los vamos sacando según los necesitamos. Además cuando un sprite ya no es necesario lo devolvemos al pool para que pueda reutilizarse más adelante. De esta forma, si nuestro pool es lo suficientemente grande no necesitaremos crear sprites durante el tiempo del juego. El pool lo programaremos de forma que vaya inicializando los sprites con las variables iniciales según vamos reciclandolos. Es decir, nosotros solo nos procuparemos de pedirle un sprite al pool, éste se encargará de darnoslo reciclado (o nuevo) y con los datos inicializados. Si no hubieramos calculado bien el tamaño del pool inicial entonces el pool creará nuevos sprites que añadirá al pool, esto último no es deseable, pero si fuera necesario el pool deberá ser capaz de gestionarlo.

Caso real de un pool de sprites en Andengine usando el patrón de diseño pool

Andengine tiene una clase que nos ayudará en la creación y gestión de pools de sprites. En la clase de ejemplo que he puesto, si os fijáis heredamos de GenericPool para tener todas las características del pool disponible. Los objetos que guardamos en el pool son de tipo GraphicObject (una clase creada por mi) que tienen un metido initialize creado por mi que pondrá las coordenadas, tamaño,  y en general cualquier dato para inicializar el sprite.


import java.util.ArrayList;

import org.andengine.util.adt.pool.GenericPool;

public class ResourcePoolObject extends GenericPool<GraphicObject>{

private ActivityGamePlaying activity;
private int typeObject; // El tipo de Objeto
private int contadorObjetos=0;
public ResourcePoolObject(ActivityGamePlaying activity,int typeObject){
super();

this.activity=activity;
this.typeObject=typeObject;
int pInitialSize = ConstantsGeneric.NUM_POOL_ITEMS;

if(pInitialSize > 0) {
this.batchAllocatePoolItems(pInitialSize);
}
}

/**
  * Called just before a Sprite is returned to the caller, this is where you write your initialize code
  * i.e. set location, rotation, etc.
 */ @Override
 protected void onHandleObtainItem(final GraphicObject objeto) {
                // Inicializamos nuestro objeto llamando al metodo initialize que habremos creado en nuestro objeto
objeto.initialize();
}

  /**
 * Called when a Sprite is required but there isn't one in the pool
 */ @Override
 protected GraphicObject onAllocatePoolItem() {
// Creamos nuestro objeto (en mi caso es GraphicObject)
final GraphicObject objeto = new GraphicObject(activity,typeObject);
objeto.doAttachs();
activity.getScene().sortChildren();   
return objeto;
 }

 /**
  * Called when a Sprite is sent to the pool
 */ @Override
 protected void onHandleRecycleItem(final GraphicObject objeto) { 
 objeto.setIgnoreUpdate(true);
 objeto.setVisible(false);
 }  
}

Luego, durante el juego, si necesitamos un sprite del pool simplemente tendremos que pedirle al pool un objeto de esta forma:

// Suponemos que pool es un objeto tipo ResourcePoolObject (nuestro pool de sprites)
// En mi caso es un pool de sprites frutas, le pido una fruta de tipo "tipo_fruta"
GraphicObject fruta = pool.obtainPoolItem();

// Cuando queramos matar a un sprite hay que pasarle el sprite a reciclar al objeto ResourcePoolObject:
pool.recyclePoolItem(fruta);

Para añadir más versatilidad podríais tener un sprite con varias texturas cargadas y a la hora de inicializar ponerle la textura que quisíerais, de esta forma en un mismo pool podríamos tener enemigos de distinto tipo. O tambien podría hacerse un pool por cada tipo de enemigo.

Las posibilidades son muchas. Disfrutádlo

Juego que usa pool de sprites

Os presento el juego Fruit Tiles. Es un juego que hice hace algunos meses y que usa intensivamente pool de sprites para funcionar. Como veréis salen un montón de frutas en la pantalla que van desapareciendo. Pues ahí se usa el pool de sprites. Si lo descargáis y lo valoráis con 5 estrellas os lo agradeceré mucho! Así podré seguir haciendo tutoriales como este.

Bonus track para jugar

No puedo irme sin recomendaros un juego gratuito de Android perfecto para los amantes de lo retro, probadlo, de verdad, os encantará: Super Cauldron

Podréis crear niveles personalizados o jugar a los que vienen en el juego. Se agradece que votéis con 5 estrellas si os gusta

Os propongo que probéis un juego que he desarrollado con muchas de las cosas propuestas en estos tutoriales, el juego es el Arkandroid. La foto que ilustra este artículo es una captura del juego. En este juego usé la carga de recursos que hoy he explicado en el tutorial, las fases son números que indican el tipo de ladrillo y el movimiento que tiene si lo tuviera.

También te podría gustar...

Si continuas utilizando este sitio aceptas el uso de cookies. más información

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar