« ¿60 horas a la semana? | Inicio | El patrón State aplicado al desarrollo de juegos ( II ) »

El patrón State aplicado al desarrollo de juegos ( I )

Vamos a ver un ejemplo de cómo podría implementarse el patrón State, para realizar juegos con lógica compleja y / o reactiva, teniendo en cuenta que la implementación es bastante relajada, y que el ejemplo que se presenta es tan sólo eso, un ejemplo, lo suficientemente sencillo para poder ser explicado en unas pocas líneas, pero lo suficientemente complejo para que empiece a merecer la pena el considerar implementar este patrón. Obviamente, cuanto más complejo sea el comportamiento del juego y / o de sus entidades, esta opción cobrará más cuerpo.

Manos a la obra. Primero veamos qué es el patrón State.

Del libro "Patrones de diseño" ( Gamma et al, Addison Wesley, Madrid, 2003 )

"Permite que un objeto modifique su comportamiento cada vez que cambie su estado interno. Parecerá que cambia la clase del objeto"

Aplicabilidad: Úsese el patrón State en cualquiera de los siguientes dos casos:

1.- El comportamiento de un objeto depende de su estado, y debe cambiar en tiempo de ejecución dependiendo de ese estado.
2.- Las operaciones tienen largas sentencias condicionales con múltiples ramas que dependen del estado del objeto.[…]. El patrón State pone cada rama de la condición en una clase aparte. Esto nos permite tratar al estado del objeto como un objeto de pleno derecho que puede variar independientemente de otros objetos".


Dicho en otras palabras, lo que vamos a intentar es describir el comportamiento de un objeto como una colección de estados, de manera que sea el propio objeto el que maneje su comportamiento mediante transiciones de un estado a otro.

Dicho así, no hay quien lo entienda, pero vamos a intentar ilustrarlo con un ejemplo.

Imaginemos que tenemos que hacer un juego: "Explota la pelota". La especificación del juego es la siguiente: se nos presentará un número indeterminado de pelotas en pantalla, que rebotan en el suelo sin pérdida de energía, y que no rebotan en las paredes ( es decir, si se salen por la derecha de la pantalla, han de volver a aparecer por la izquierda ). Tenemos un tiempo máximo para explotar un número determinado de pelotas ( haciendo clic con el ratón sobre ellas ). Al explotar una pelota aparecerá otra, de manera que siempre habrá el mismo número de pelotas en pantalla. La posición y velocidad inicial de las pelotas es aleatoria. Si no explotamos un número mínimo, perdemos. Si lo conseguimos, se nos ofrece terminar el juego con la puntuación actual, o volver a intentarlo, pero con menos tiempo y teniendo que explotar un número de pelotas mayor. Así hasta que nos plantemos o perdamos.

A bote pronto ( valga la expresión ) tenemos dos entidades claramente diferenciadas: el universo del juego, y la pelota en sí, luego parece lógico pensar que debamos estructurar el juego en dos clases, una que maneje la lógica del juego ( que se encargue de colocar las pelotas en pantalla, compruebe si se han explotado las suficientes, si queda tiempo… ), y otra que maneje el comportamiento de la pelota. Vamos a fijarnos en ésta última.

Evidentemente, la pelota se va a representar con un MovieClip. Luego podemos pensar que lo lógico sería crear una clase Pelota que extienda de MovieClip, y sobrescribir el onEnterFrame, de manera que ese método se encargue de chequear la posición de la pelota en cada frame, haga el chequeo de colisión con el suelo, compruebe si la pelota se ha salido de la pantalla por alguno de los lados, y que coloque la pelota dependiendo de esas circunstancias ( dicho de otra forma, que implemente un mecanismo para manejar la ecuación de movimiento de la pelota ), que detecte cuándo se ha hecho click en la pelota y se lo notifique al universo del juego, que maneje la animación de explosión de la pelota, etc….

Éste no creo que sea ni el momento ni el lugar para discutir sobre si ese enfoque puede considerarse el más apropiado o no. Partamos de la base de que no hay una forma correcta y otras incorrectas de hacer las cosas. Pero veámoslo con espíritu crítico.

Por un lado, vamos a tener una clase con una abanico de responsabilidades muy amplio ( desde comportamientos físicos a mera presentación ). Eso es lo que se denomina baja cohesión. Dicho de otra forma: "zapatero, a tus zapatos".

Además, el comportamiento de la pelota se deberá implementar como un enorme switch o una larga serie de sentencias if ( si ha rebotado con el suelo, haz esto; si te has salido por alguno de los lados, haz esto otro;….. ). Bueno, pues, esto, precisamente, es uno de los casos que se ponen como ejemplo de "éste es el momento para implementar un state". Sobre todo teniendo en cuenta, que aunque éste no sea el caso, el comportamiento de la pelota podría ser reactivo, es decir podría tener que cambiar a lo largo del juego ( cambia el rozamiento con el aire, las propiedades dinámicas del rebote, etc ).

Por hoy es suficiente. En breve veremos lo que es una máquina de estados, y cómo implementarla.

Comentarios

enhorabuena por el articulo!
Yo soy de ese tipo de desarrolladores que conocen muy bien flash pero que les falta metodología o un patro que seguir a la hora de plantear los proyectos. Este tipo de info es como agua de mayo.
Me quedo a la espera de la siguiente entrega.