3 de noviembre de 2009

Patrones de Diseño aplicados a juegos

Mucho material hay en la web sobre este tema y, por lo general, es bastante repetitivo. Si uno lee el libro "Design Patterns" de GoF (altísimamente recomendado) que data de 1995, descubrirá que no hay muchos cambios conceptuales, por decir ninguno. Por lo tanto, la mayoría de la información que encontramos en la red se limita a citar casi textualmente dicha obra, mostrar como se aplican ciertos patrones en ciertos lenguajes o describir algún patrón de creación más reciente.

Es que, conceptualmente, "Patrones de Diseño" es algo muy sencillo de captar:

Son soluciones simples y copadas para problemas usuales del diseño orientado a objetos y que está demostrado que funcionan.

Es decir, cuando ya nos enfrentamos varias veces a cierta problemática, ganamos experiencia sobre el método para resolverla y, ese método, lo documentamos para que nos quede presente en el futuro.

Cuando hacés fideos, ya sabés que la mejor forma es primero hervir el agua, luego poner sal y aceite, luego echar los fideos y cocinar. Estás aplicando un patrón en la cocina, basado en la experiencia previa de otros y que te otorga una solución veloz y eficaz para cocinar fideos.

El chiste no es entender este concepto, sino poder aplicarlo adecuadamente, saber identificar que estamos frente a x problemática y que tenemos x patrón a nuestro alcance para resolverla. Aquí entra en juego el factor experiencia y también un poco de sentido común.

Para no ser extremadamente repetitivo, te voy a dejar algunos links de Patrones de Diseño y, por mi parte, voy a mostrarte como aplicar algunos e la creación de videojuegos. Dado que venimos con algunos tutoriales sobre ese tema y que utilizan Flash y ActionScprit 3, mis ejemplos estarán en este lenguaje y se complementarán con dichas notas.




Singleton

Este patrón pertenece a la categoría de "patrones de creación"
Ya vimos un ejemplo de este patrón en la primer parte del tutorial de creación de un game-engine.
Podemos mencionar otros ejemplos bastante usuales, como los controladore de Mouse y Teclado. Si vos creás tu propia clase encargada de la captura y manejo de los eventos del teclado para tu juego, es más que obvio que vas a desear que exista una sola instancia de esta clase y que sea accesible "globalmente" desde cualquier lugar de tu código. Vas a usar un Singleton.

Composite

Un patrón estructural, cuyo objetivo consiste en formar objetos complejos a partir de otros más simples y similares entre sí.
Un claro ejemplo de aplicación son la GUI.

Strategy

Este patrón busca permitir la elección de distintos algoritmos por el objeto cliente, optando e intercambiando según sus necesidades. Los distintas estrategias heredan de una estrategia abstracta y mantienen su interface, por lo que la ejecución de la misma se mantiene transparente para el cliente.
Un claro ejemplo en juegos es la aplicación de distintos algoritmos de IA según algún estado de juego.




public class IAStrategy {
public function executeIA():void{
trace("no hace nada, debe ser overrideado!!");
}
}

public class IAAggresive extends IAStrategy{
public function override executeIA():void{
trace("¡¡Tomá Guacho, morite!!");
}
}

public class IADefensive extends IAStrategy{
public function override executeIA():void{
trace("¡¡No me pegues, soy Giordano!!");
}
}



Definidas las estrategias, un cliente las utiliza.




import strategies.*; //--- paquete con las estrategias
import GameEngine;

public class Enemy {
private var ia:IAStrategy;

public function Enemy(){
if(GameEngine.instance.dificulty=="GORE"){
this.ia=new IAAggresive() as IAStrategy;
}
else{
this.ia=new IADefensive() as IAStrategy;
}
}

public function update():void{
this.ia.excecuteIA();
}
}


Como vemos, cada vez que un enemigo sea creado, este adoptará una estrategia diferente para manejar su IA acorde a la dificultad del juego (GameEngine es una clase Singleton que contiene toda la data del juego, basándonos en este tutorial). También podemos hacer que la estrategia vaya cambiando dinámicamente (por ejemplo en el update) en vez de que sea seteada al comienzo y permanezca invariable para ese enemigo.


Template Method

Template Method define una superclase que sirve de plantilla (template) de los métodos en las subclases. De esta manera, al no tener que repetir código reiteradamente, se evitan muchos errores.

Un ejemplo bastante practico en juegos puede ser la clase GameModel. Supongamos un clon de SpaceInvaders en el que cada modelo tiene un método update similar al siguiente:




public function update():void{
updateInput();
updateLogic();
updateAnimation();
}



y donde cada modelo en particular, implementará cada uno de esos pasos a su manera. Aplicando Template Method, lo haríamos así:



public class GameModel{
var x:int;
var y:int;

public final function update():void{
updateInput();
updateLogic();
updateAnimation();
}

private function updateInput():void{ }
private function updateLogic():void { }
private function updateAnimation():void{ }
}



Acabamos de crear la clase que funciona como plantilla. Ahora, cuando creemos clases a partir de ella, ya tendrán un compotamiento update predefinido y solo deberemos customizar sus pasos.




public class SpaceShip extends GameModel{
private override function updateInput(){
//---controla el teclado
}
private override function updateLogic() {
//---cambia los estados segun teclado y demases
}
private override function updateAnimation(){
//---dibuja la nave
}
}


public class EnemyShip extends GameModel{
private override function updateInput(){
//--- nada, se manejan por IA
}
private override function updateLogic() {
//---cambia los estados segun IA y demases
}
private override function updateAnimation(){
//---dibuja al Enemigo
}
}



¿Qué más?

Apenas mostre algunos de los muchos patrones que existen y como pueden ser aplicados a la hora de realizar videojuegos. La idea era abrir un poco el panorama y avivarte a que utilices buenas costumbres en tus desarrollos, aunque muchos crean que POO y videojuegos no sean compatibles (enorme error). Si estás interesado en ver cómo pueden aplicarse más patrones en juegos, son bienvenidas las peticiones.

De todas maneras, seguro terminaremos utilizando estos y más en los tutoriales de Desarrollo de Videojuegos.

Hasta la próxima!

Links de interés

Wiki de Patrones de Diseño
Listado de patrones de Wikipedia
Otro artículo parecido a este


No hay comentarios: