Skip to content

Instantly share code, notes, and snippets.

@DanielUranga
Last active April 19, 2016 10:09
Show Gist options
  • Save DanielUranga/5931284 to your computer and use it in GitHub Desktop.
Save DanielUranga/5931284 to your computer and use it in GitHub Desktop.
Capítulo 3: Desarrollo
Resumen
En este capítulo se describirán las mejoras planteadas sobre la biblioteca elegida (ATHUS) [1] y el desarrollo de una nueva biblioteca para brindar soporte a los desarrolladores de video juegos (LuaWidgets).
Se comienza con un análisis del estado del arte en materia de bibliotecas de desarrollo de videojuegos, tanto a nivel PC, diseñadas específicamente con el fin de generar aplicaciones destinadas para la TVD-T. A continuación, se incluye una descripción del framework de desarrollo de videojuegos ATHUS, especificando nuevas prestaciones propuestas orientadas a simplificar la tarea del desarrollador de videojuegos y mejoras sobre la misma.
Adicionalmente, se describe una biblioteca de componentes gráficos que posibiliten la interacción con el usuario (Widgets) reutilizables para el diseño de GUIs sencillas tanto en el desarrollo de videojuegos, como de cualquier aplicación multimedia interactiva.
1. Introducción a los videojuegos
El desarrollo de videojuegos constituye un trabajo interdisciplinario en el que interactúan profesionales de diferentes áreas del conocimiento, desde los artistas capaces de idear la gráfica e historia conductora hasta los programadores artífices del diseño e implementación real de la aplicación. Así como los diseñadores gráficos utilizan herramientas de software para realizar sus dibujos, los informáticos requieren hacer uso de un conjunto de piezas de software que les permitan desarrollar sus productos eficientemente. Una de éstas, son las denominadas Bibliotecas de Desarrollo de Videojuegos, que brindan a los programadores un repertorio de artefactos capaces de simplificar la tarea y organizar la estructura del Videojuego a ser desarrollado. Existe un bagaje común de conceptos que toda biblioteca de éste tipo debería proveer; el objetivo de esta primera parte del documento, es brindar entonces una descripción general de las características que deberían ser cubiertas por cualquier biblioteca estándar de desarrollo de juegos.
1.1. Desarrollo de videojuegos
Desde la década del 60' en que los videojuegos comenzaron a formar parte del mundo de la computación han tenido un vertiginoso crecimiento sin pausa. A lo largo de los años, y con las sucesivas innovaciones tecnológicas producidas, el diseño de videojuegos ha ido evolucionando y mejorando los productos generados, hasta constituirse hoy como uno de los principales usos de las computadoras modernas.
Las librerías que han adquirido mayor popularidad entre los desarrolladores de juegos (principalmente bidimensionales) debido a su buen rendimiento, facilidad de uso y libre distribución, han sido SDL [2] y Allegro [3], para el lenguaje C++. Desde la popularización de Python como lenguaje multipropósito gracias a su alta legibilidad, la biblioteca PyGame se ha tornado popular. Así también librerías como ClanLib [4] que permite interactuar con nuevas tecnologías tales como OpenGL3, renderizado basado en shaders, soporte para XML, entre otras; y PyGame [5] es una biblioteca para desarrollo en Python que posee soporte para tecnologías actuales como procesamiento multicore.
En la actualidad, bibliotecas como Cocos2d para desarrollos para iPhone, Ogre3D para entornos tridimensionales y Unity para juegos multiplataforma, se han comenzado a imponer en el mercado.
Uno de los lenguajes que ha ido ganando preponderancia en el ámbito del desarrollo de videojuegos simples, es Lua [6]. Este lenguaje dinámico de scripting, ha sido adoptado por varios motores de creación de videojuegos como punto de entrada del programador al desarrollo de la aplicación, debido a su simplicidad y flexibilidad.
SDL (Simple Direct Media Layer)
Es una biblioteca abierta con soporte multi-plataforma que provee una capa de abstracción para simplificar el trabajo al programador de videojuegos. Provee facilidades para el manejo de audio, teclado, mouse, joystick, aceleración 3D para hardware (openGL) y manejo de Sprites en 2D.
Allegro (Allegro low level game routines)
Esta biblioteca se destaca por ser una biblioteca multiplataforma que simplifica el manejo de tareas de bajo nivel, tales como creación de ventanas, carga de datos, dibujo de imágenes, etc;
ClanLib
Dicha biblioteca permite interactuar con nuevas tecnologías tales como OpenGL3, renderizado basado en shaders, soporte para XML, entre otras.
PyGame
Es una biblioteca para desarrollo en Python que posee soporte para tecnologías actuales como procesamiento multicore.
Librerías actuales
Adicionalmente, existen bibliotecas que se han tornado populares debido al dominio de aplicación, por ejemplo Cocos2d para el desarrollo de videojuegos 2D principalmente para dispositivos móviles y Ogre3D para mundos tridimensionales, junto con Unity para videojuegos en PC de alto desempeño.
1.2. Aplicaciones interactivas y video juegos en Ginga
Existen en Latinoamérica dos versiones de soporte para programadores de aplicaciones Ginga [7]. Una para el desarrollo de aplicaciones Java, denominada Ginga-J y otra para aplicaciones desarrolladas en el lenguaje declarativo NCL [8] junto con Lua, denominada Ginga NCL/Lua. Esta última es la que ha sido adoptada en Argentina.
En el caso de la plataforma Ginga-J, existen dos bibliotecas desarrolladas en Brasil para la construcción de videojuegos. Tuga [9] es un middleware ideado para proveer a los desarrolladores de juegos en Ginga-J, una capa de abstracción que simplifique el manejo de sprites, fuentes, personajes y sonidos. Ginga Game [10] es otro producto similar, el cual intenta acercar el desarrollo de juegos para TV Digital al desarrollo de juegos para PC. Al igual que Tuga, fue diseñado sobre Ginga-J y permite a los programadores enfocarse en el código específico del juego, sin preocuparse demasiado por atender otras cuestiones de implementación.
Para GingaNCL/LUA existe sólo una biblioteca para el desarrollo de videojuegos denominado ATHUS, también de origen brasileño. Dicha biblioteca provee a los programadores de NCL/LUA un buen marco de referencia a la hora de implementar y diseñar videojuegos pero omite varias funcionalidades y servicios y en la actualidad su desarrollo ha sido discontinuado, con lo que se hace necesario un producto estable y en desarrollo que cubra estas necesidades.
Adicionalmente, existe una falencia real de un manejo óptimo de interfaces dentro del desarrollo de aplicaciones para TVD-T, en particular aquellas que requieran de interfaces con diversos componentes como etiquetas, distintos tipos de botones, menúes desplegables, etc.
Todas las necesidades expuestas anteriormente, brindan la justificación principal para el objetivo de esta tesis, el cual se resume en el desarrollo de un framework para aplicaciones interactivas y una biblioteca de widgets de interfaz en el entorno de la TV digital.
2. Decisiones tomadas sobre ATHUS
En las siguientes secciones, veremos cómo se implementan cada uno de los módulos encargados de las distintas responsabilidades, como a partir de ellos surgen distintas necesidades y la forma de solucionarlas. Para ello comenzaremos dando una explicación breve de la biblioteca ATHUS.
2.1. ATHUS
ATHUS es un framework para desarrollo de videojuegos sobre TVD-T y soporta dos plataformas: Ginga-J y Ginga-NCL/Lua. La versión NCL/Lua de ATHUS fue la elegida como base del presente trabajo.
ATHUS ha sido implementado en Lua y diseñado bajo el paradigma orientado a objetos. Ofrece un repertorio de clases agrupadas en tres grandes paquetes según su funcionalidad, puede ser View, Core o Interaction.
Ilustración . Diagrama de paquetes correspondiente a la arquitectura de Athus. Pueden observarse los paquetes principales View, Core e Interaction descriptos en esta sección.
Paquete Core
Incluye las clases relativas a la estructura general y al manejo del flujo temporal y espacial del juego. La clase Engine implementa la técnica de DoubleBuffering que almacena cada parte de la escena a renderizar en un buffer para luego volcarlo a pantalla.
El manejo de las animaciones y eventos temporales, se realiza utilizando la clase Animation. Por otro lado, Colision ofrece los algoritmos necesarios para realizar la detección de colisiones entre los objetos del juego. IA ofrece algoritmos clásicos de Inteligencia Artificial reutilizables en diversos tipos de aplicaciones. Finalmente, Tools implementa funciones auxiliares para el desarrollo de aplicaciones en Ginga.
Paquete Interaction
Incluye las clases relativas a la comunicación con el entorno de la aplicación y con el usuario. Está compuesto por Pad (comunicación con el control remoto del STB), Tv (comunicación con la emisora) y Net (gestión de conexiones remotas TCP).
Paquete View
Incluye todas las clases que modelan objetos visibles en el juego. Todo elemento visual que posea entidad propia en ATHUS pertenece a la clase GameObject. Existen diversos tipos de GameObjects tales como Sprites (almacenan una imagen compuesta por uno o varios frames, y propiedades asociadas a ésta), Text (provee facilidades para el dibujado de texto en pantalla utilizando el API provisto por el módulo canvas de Lua) y TileMaps (es un mapa matricial de imágenes construido a partir de la combinación ordenada de pequeñas celdas de imagen). La clase TileSet permite cargar un spritesheet con celdas de dimensión fija, que serán posteriormente utilizadas en un TileMap. Finalmente, Media modela objetos multimedia (audio o video) que han sido definidos previamente en archivo NCL y se pretende utilizar desde el script Lua.
2.2. Componentes de un Video Juego
2.2.1. Clase GameObject
Al encarar el desarrollo de un videojuego, podria pensanrse en desarrollar una clase que representa todo contenga todo lo que hace al juego. Pero una clase muy grande significa incluso que los cambios más triviales pueden tener implicaciones de largo alcance muy difíciles de seguir. Por esto, al poco tiempo una clase gigante recoge  fallos antes de lo que recauda características.
La solución ante este problema es dividir la clase monolítica (se aplica el concepto de Divide y Conquista (cita requerida)), que se extiende por varios dominios diferentes, en un conjunto de clases de componentes. Cada componente encapsula la porción de la conducta de la clase original que es específico para un dominio. La clase monolítica original se convierte en una clase que solo funciona como una fachada para estos componentes.
Los componentes se encuentran más comúnmente dentro de la clase de núcleo que define las entidades en un juego, pero pueden ser útiles en otros lugares también. La clase GameObject es la contenedora de todos los componentes en un determinado estado del juego.
Los Game Objects son los Componentes del Juego, los cuales son cualquier cosa que tenga una representación en el mundo de juego (personajes, objetos, vehículos, misiles, cámaras, volúmenes de activación, luces, etc).
ATHUS tiene la clase GameObject, la cual es la contenedora de todos los Componentes del Juego. Pero en ella se entraron algunos problemas, a los cuales se le planteo una solución. Las mejorar a agregar son:
La forma de obtener la posición de un GameObject es a través del método getPosition() que devuelve una tabla con las posiciones. Para ganar legibilidad se deben agregar los métodos getX() y getY() que devuelvan directamente cada coordenada del GameObject.
gObject = new gameObject.GameObject:new();
-- aumentar X en 30 sin usar mejora
x, y = gObject.getPosition();
gObject.setPosition({x+30, y});
-- aumentar X en 30 usando mejora
gObject.setPosition({gObject.getX()+30, gObject.getY()});
Todo objeto del juego posee una velocidad indicada por un vector de dos dimensiones.
La misma es utilizada para sumarla a la posición actual y producir un desplazamiento en caso de que sea requerido. Sin embargo, dicho código debe ser escrito cada vez que se desea desplazar un GameObject. Como solución proponemos incorporar a dicha clase un método move() que sume la velocidad a la posición actual.
gObject = new gameObject.GameObject:new();
-- desplazamiento sin usar mejora
...
gObject.setPosition({gObject.getX()+3, gObject.getY()});
-- usando mejora
gObject.setXSpeed(3);
gObject.displace();
Otra forma de hacer desplazamientos en con las transformaciones de posición como se describió anteriormente. Queda a gusto del usuario del framework cuál de las alternativas descritas usar.
Generalizando esta idea, se incluirá la posibilidad de que el usuario den a una transformación personalizada sobre un GameObject. Esto podría ser implementado en base al patrón de diseño Strategy [14] creando una nueva clase abstracta que modele una transformación posicional generica, que luego sea heredada por cada transformación concreta que quiera realizarse, por ejemplo, movimiento sinusoidal, etc.
Los GameObjects se sitúan en distintos escenarios durante el transcurso del juego.
Una composición de Sprites permitirá construir una Escena. En general, una escena suele estar compuesta por uno o varios backgrounds combinados, y un conjunto de sprites representando elementos activos del juego sobre ellos.
Ilustración . Composición de una Escena a partir de diferentes Sprites
2.2.2. Sprites
Un Sprite es una imagen bidimensional capaz de ser manipulada independientemente del resto de la escena de la que forma parte. La descripción clásica de un Sprite se basa en una imagen, una posición y demás parámetros requeridos en función de las transformaciones que dicha imagen pueda sufrir (p.ej.ángulo de rotación actual).
Los Sprites, constituyen la unidad gráfica mínima con la que un usuario puede interactuar en un Video juego2D. Un sprite puede jugar tanto el rol de elemento activo en el juego, como de background o imagen de fondo.
Principalmente en el caso de los Sprites que representan un elemento activo del juego, se hace necesario introducir el concepto de Transparencia, con el objetivo de brindar mayor realismo a la aplicación. Sin la implementación de dicho concepto, todos los objetos del juego deberían poseer forma rectangular. Por esta razón, normalmente es posible definir un color especial como transparente, con el fin de indicar a la biblioteca que todo pixel de ese color en el Sprite original no debe ser gracado al renderizar la escena.
Magenta dado por la trupla RGB (255,0,255) ha sido definido como color transparente. En los últimos años, se ha vuelto popular el uso de formatos que permitan almacenar transparencia, como es el caso del formato PNG.
Ilustración . a) Sprite 2D que representa un elemento activo del juego. b) Sprite 2d que representa el background de una escena.
Ilustración . Sprite 2d sobre fondo de color transparente
2.2.3. Transformaciones
Una de las posibilidades que la biblioteca debe brindar, es la de aplicar diversos tipos de transformaciones sobre los Sprites a dibujar. Algunas de las transformaciones clásicas son:
Escalar: Escalar un Sprite consiste en cambiar su tamaño. Para hacerlo, suelen utilizarse técnicas de replicación de pixels o interpolación de los mismos con el fin de no producir un efecto de pixelado sobre la imagen escalada.
Rotar: Dado un ángulo específico, la rotación consiste en cambiar la orientación del Sprite manteniendo algún punto fijo.
Trasladar: Dado un vector de desplazamiento, un Sprite puede ser trasladado en dicha dirección sumando a cada una de las componentes de su posición inicial las componentes del vector desplazamiento.
Reflejar: La transformación de Reflexión de un Sprite, genera una imagen con las mismas dimensiones que la original desplazando todos los pixels que la componen a otra posición equidistante de una recta denominada eje de simetría.
Al ver que en el framework original no poseía una implementación para poder realizar transformaciones, se decidió incorporarlo.
Una de las posibilidades que la biblioteca debe brindar, es la de aplicar diversos tipos de transformaciones sobre los Sprites a dibujar. Algunas de las transformaciones clásicas son:
Escalar: Escalar un Sprite consiste en cambiar su tamaño. Para hacerlo, suelen utilizarse técnicas de replicación de pixels o interpolación de los mismos con el fin de no producir un efecto de pixelado sobre la imagen escalada.
Rotar: Dado un ángulo específico, la rotación consiste en cambiar la orientación del Sprite manteniendo algún punto fijo.
Trasladar: Dado un vector de desplazamiento, un Sprite puede ser trasladado en dicha dirección sumando a cada una de las componentes de su posición inicial las componentesdel vector desplazamiento.
Reflejar: La transformación de Reflexión de un Sprite, genera una imagen con las mismas dimensiones que la original desplazando todos los pixels que la componen a otra posición equidistante de una recta denominada eje de simetría.
Se implementaron en el framework algunas funcionalidades referidas a las configuraciones comunes de las transformaciones, por ejemplo, si la misma es cíclica o no (es decir, si al llegar a un borde el objeto debe ser  trasladado al borde contrario o debe ser detenido ahí).  
Si bien todas las transformaciones mencionadas anteriormente no están implementadas en la extensión que se realizó, se diseñó con el fin de que esto sea posible.
Ilustración . Diagrama de clases simplificado correspondiente a las transformaciones espaciales.
Para que quede más claro este cambio sobre athus podemos ver el comportamiento de estas clases en el framework actual.
En la práctica por ejemplo si deseamos crear una transformación del tipo direccional que avanza de a un pixel con PI grados de inclinación (es decir hacia la derecha) lo que debemos hacer es lo siguiente:
transformation = directionalTransformation.DirectionalTransformation:new(1, math.pi);
Esto aplica la transformacionrecien creada sobre el objeto “gameObject”, resultando en que el objeto se mueve un pixel a la derecha. Con sucesivas llamadas a este método se puede crear la sensación de movimiento.
directionalTransformation:transform(gameObject);
Posteriormente, se definieron transformaciones concretas tales como
DirectionalTransformation (para desplazar el objeto en la dirección indicada por un ángulo dado)
RandomTransformation (para desplazarlo a una posición aleatoria)
SinusoidalTransformation (para mover el objeto sobre una trayectoria sinusoidal).
Ejemplo de Transformaciones espaciales
En este ejemplo se desplaza el objeto sobre una trayectoria sinusoidal en lugar de hacerlo en forma recta (ver Figura 3), utilizando las transformaciones espaciales expuestas en secciones anteriores. El desplazamiento de los sprites que representan el fondo también se realiza con transformaciones, pero se utiliza una transformación direccional simple.
Para utilizar las transformaciones, es necesario agregar su definición:
st = sinTrans.SinusoidalTransformation:new(30,10,10,10,300);
dt0 = dirTransf.DirectionalTransformation:new(10,math.pi);
dt1 = dirTransf.DirectionalTransformation:new(20,math.pi);
Luego de definirlas, la única función que ha de ser modificada es update, para indicar que las transformaciones deben ser aplicadas sobre los Sprites.
function update()
dt0:transform(fondo0);
dt1:transform(fondo1);
st:transform(obj0);
end
A través del método transform, cada transformación desplaza a cada sprite de diferente forma.
Incorporación de nuevas técnicas de manejo de colisiones
Actualmente, ATHUS cuenta con una técnica para el manejo de Colisiones, basada en el chequeo por áreas rectangulares entre los objetos del juego. Tal como se expuso anteriormente, existen otras técnicas que podrían ser implementadas, como la detección por Áreas Circulares y detección por Pixel. Ámbos algoritmos podrían ser implementados en la clase Colision, que actualmente solo cuenta con el metodo boxColisionByPair(obj1, obj2), agregando dos métodos circleColisionByPair(obj1, obj2) y pixelColisionByPair(obj1, obj2) y agregando a la clase GameObject los metodos necesarios para incorporarles descriptores tales como el radio del círculo o la máscara de píxeles a utilizar en dicho chequeo.
//mostrar diagrama de actualizacion
colision = colision.Colision:new();
if colision:boxColisionByPair(obj1, obj2) == true then
print(“Colision detectada”);
end
if colision:circleColisionByPair(obj1, obj2) == true then
print(“Colision detectada”);
end
Incorporación de fuentes basadas en imagen
En la actualidad, el uso de fuentes basadas en imágenes (Font Sheets) se ha tornado de
uso común. Esta característica, aún no soportada por ATHUS, se incorporo mejoras de la
clase Text al permitirle cargar Font Sheets y dibujarse en función de estas.
2.2.4. Creación de menus
En general, toda aplicación interactiva por simple que sea, requiere una sección de configuración (por ejemplo, para seleccionar la cantidad de jugadores, activar o desactivar el sonido, etc). Por esta razón, resulta de interés contar con una clase Menu que pueda ser configurada en base a las necesidades de cada aplicación, cargándole diferentes opciones, y conectando cada una de ellas con determinadas acciones a ser ejecutadas, por ejemplo, permitiendo al programador especificar un puntero a la función que será activada.
Un menú debe contar también con un background determinado (jo o móvil), una fuente determinada y un árbol de opciones anidadas indicando la acción a ejecutar por cada una de ellas.
En caso de querer desarrollar menúes más complejos, surge la necesidad de contar con componentes reutilizables tales como botones, etiquetas, listas, listas desplegables, botones chequeables y otros. Estos componentes gráficos, con los cuales el usuario puede interactuar, son denominados Widgets. Por esta razón, la necesidad de un menú actúa como origen para el desarrollo de una biblioteca completa de Widgets capaz de ser reutilizados no sólo con esten, sino para cualquier aplicación Ginga que los requiera.
2.3. Resumen: Necesidades y su solución
Estas soluciones planteadas dieron origen a la versión argentina de ATHUS llamada ATHUS.ar. En cuanto a la versión original de ATHUS, se describieron las modificaciones que se  tuvieron que implementar para adaptar dicha versión a la versión argentina y las mejoras encontradas sobre ciertos aspectos tales como, la posibilidad de crear una Interfaz de acceso a las clases para brindar mayor usabilidad a las aplicaciones, las implementaciones de los nuevos chequeos de colisiones, tener la posibilidad de crear transformaciones espaciales reutilizables. A continuación se mostrará un resumen mostrando como de esas mejoras se llego a ATHUS.ar.
2.3.1. extenciones de la biblioteca
Transformaciones
Sprites
2.3.2. mejoras
gameObject
Creación de la clase Menu
Bibliografía
x
[1]
J. C. F. da Silva, and T. A. Tavares R. M. Segundo, "Athus: A generic framework for game development on ginga minddleware," Game and Digital Entretainment, Brazilian Symposium , vol. 0, pp. 89-96, 2010.
[2]
B. Pendleton, "Game programing with the sdl," Linux J., vol. 2003, pp. 1-, June 2003.
[3]
2011., "http://alleg.sourseforge.net/," Allegro, vol. A game programming library, 2011.
[4]
2011., "http://clanlib.org," ClanLib Game SDK., 2011.
[5]
2011., "http://pygame.org," Sitio web de PyGame.
[6]
L. H. de Figueiredo, W. Celes. Manual. R. Ierusalimschy, Lua , 51st ed., 2006.
[7]
Televisión digital terrestre - Guía de operación Parte 3: Multiplexación y servicio de información (SI) — Guía para implementación de la ABNT NBR 15603:2007,.
[8]
S. D. Junqueira Barbosa. L. F. Gomes Soares, Programando em NCL , 302nd ed., 2011.
[9]
D. A. Ferreira and C. T. Souza, "“Tuga: Um middleware para o soporte ao desemvolvimento do jogos em tv digital interativa.," vol. ”Disponible en: http://code.google.com/p/tugasdk/., 2009.
[10]
] D. C. Barboza and E. W. G. Clua, "Ginga game: A framework for game development for the interactive digital television," in proceeding of the 2009 VIII Brazilian Symposium on Games and Digital Entertaiment, SBGAMES ´09, (Washingtone, DC, USA), pp. pp. 162-16.
x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment