UNIVERSIDAD AUTONOMA METROPOLITANA148.206.53.84/tesiuami/UAMI13844.pdf · DIAGRAMA DE NAVEGACIÓN...
Transcript of UNIVERSIDAD AUTONOMA METROPOLITANA148.206.53.84/tesiuami/UAMI13844.pdf · DIAGRAMA DE NAVEGACIÓN...
UNIVERSIDAD AUTONOMA METROPOLITANA
UNIDAD:
Iztapalapa
DIVISIÓN:
CBI
GRADO:
Licenciatura
TÍTULO DEL TRABAJO:
Diseño, análisis e implementación de un juego de video
NOMBRE DEL PARTICIPANTE:
Isaac de la Vega Gutiérrez
NOMBRE DEL ASESOR:
____________________________
Humberto Cervantes Maceda
México, D.F. 13 de septiembre de 2006
CONTENIDO
1INTRODUCCIÓN............................................................................................................................................ 6
2DESARROLLO DE VIDEOJUEGOS............................................................................................................. 7
2.1DEFINICIONES PARA EL DESARROLLO DE VIDEOJUEGOS........................................................ 9
2.2 LOS ORÍGENES DE LA IDEA DE UN JUEGO..................................................................................12
2.3 EL ENFOQUE DEL JUEGO.................................................................................................................13
2.4 DOCUMENTACIÓN DE VIDEOJUEGOS..........................................................................................15
2.5 EL DOCUMENTO DE DISEÑO.......................................................................................................... 17
INTRODUCCIÓN..............................................................................................................................17MECÁNICAS DEL JUEGO.............................................................................................................. 18
PRIMERA IMPRESIÓN............................................................................................................... 18LA MANIPULACIÓN DE LA MATERIA...................................................................................20ETIQUETAS Y SU INTERACCIÓN............................................................................................20EL TIEMPO Y LA DIFICUTAD.................................................................................................. 21ARMAS Y SU CONTROL........................................................................................................... 21LA PUNTUACIÓN, EL NIVEL COMPLETADO Y EL FIN DE JUEGO.................................. 22
INTELIGENCIA ARTIFICIAL..........................................................................................................22LA DIFICULTAD CON LAS ETIQUETAS.................................................................................22COMPORTAMIENTO DE LOS AGENTES PATÓGENOS....................................................... 22AFECTACIÓN DE LA MATERIA DEBIDO A LOS AGENTES............................................... 23
ELEMENTOS DEL JUEGO.............................................................................................................. 23ARTÍCULOS................................................................................................................................. 23PERSONAJES...............................................................................................................................25SISTEMAS DE MENÚS...............................................................................................................25
2.6CONSTRUCCIÓN Y DEFINICION PARA EL PROTOTIPO 1 DE AMORPHE BIOS......................25
LA PERSPECTIVA DEL DISEÑADOR DEL JUEGO................................................................253GRÁFICAS 3D EN LOS VIDEOJUEGOS....................................................................................................30
3.1 HERRAMIENTAS................................................................................................................................ 31
3.2DEFINICIONES..................................................................................................................................... 32
3.3 OPEN GL...............................................................................................................................................33
3.4 MODELADO 3D Y OPEN GL............................................................................................................. 35
3.4.1LOS ARCHIVOS GENERADOS POR UN MODELADOR.........................................................353.4.2ARCHIVOS .OBJ Y OPEN GL......................................................................................................37
LECTURA DE VÉRTICES...........................................................................................................37TRAZADO DE VÉRTICES.......................................................................................................... 38
TRAZADO DE VÉRTICES 1/2............................................................................................... 39TRAZADO DE VÉRTICES 2/2............................................................................................... 40
2
LECTURA DE LAS CARAS........................................................................................................41TRAZADO DE LAS CARAS....................................................................................................... 42ILUMINACIÓN Y MATERIALES...............................................................................................43
TRAZADO DE LAS CARAS CON ILUMINCACIÓN...........................................................44NORMALES................................................................................................................................. 45
TRAZADO DE LAS NORMALES..........................................................................................463.4.3CARGA DE TEXTURAS...............................................................................................................47
SCRIPT OREJ 1/2.................................................................................................................... 48SCRIPT OREJ 2/2.................................................................................................................... 49LECTURA DE VÉRTICES Y CARAS....................................................................................51
4ANÁLISIS Y DISEÑO DEL SISTEMA........................................................................................................ 54
4.1OBTENCIÓN DE REQUERIMIENTOS............................................................................................... 54
COMPORTAMIENTOS PRINCIPALES.......................................................................................... 54ACTORES..........................................................................................................................................55
CASOS DE USO PRINCIPALES................................................................................................. 55EXPANSIÓN DE CASOS DE USO............................................................................................. 57
ADMINISTRAR PARTIDAS...................................................................................................57ADMINISTRAR ARMAS Y ADITAMENTOS...................................................................... 57GENERAR GUI........................................................................................................................57ADMINISTRACIÓN DE INTELIGENCIA ARTIFICIAL...................................................... 58CONTROLAR INTERFAZ PRINCIPAL.................................................................................58
TABLA DE REQUERIMIENTOS FUNCIONALES................................................................... 59TABLA DE REQUERIMIENTOS NO FUCNIONALES.............................................................61CASOS DE USO PRINCIPALES................................................................................................. 62CASOS DE USO REFINADOS....................................................................................................63
4.2 ANÁLISIS DE REQUERIMIENTOS................................................................................................... 64
OBTENCIÓN DE LAS ABSTRACCIONES CLAVE..................................................................64DIAGRAMAS CRC...................................................................................................................... 64MODELO DE DOMINIO DEL PROBLEMA.............................................................................. 66DIAGRAMA DE NAVEGACIÓN................................................................................................67DIAGRAMAS DE SECUENCIA..................................................................................................67
MOSTRAR CONTAMINACIÓN............................................................................................ 67MOSTRAR PUNTUACIÓN.................................................................................................... 68ACTIVAR COMPORTAMIENTO DE PATÓGENOS EN LA SUPERFICIE DE LA MATERIA.................................................................................................................................68CONSTRUIR ETIQUETAS..................................................................................................... 69
5LIBRERÍAS PARA DESARROLLO DE SISTEMAS MULTIMEDIA........................................................71
5.1 DESCRIPCIÓN DE LIBRERÍAS MULTIMEDIA............................................................................... 72
5.2SDL......................................................................................................................................................... 73
5.2.1INICIALIZACIÓN DE SDL........................................................................................................... 755.2.2EL PROBLEMA DE LA PORTABILIDAD...................................................................................755.2.3SDL VIDEO.................................................................................................................................... 80
3
5.2.4MÉTODOS PARA DESPLEGAR SUPERFICIES........................................................................ 825.2.5OTRAS CARACTERÍSTICAS POR LAS QUE SDL ES CONVENIENTE.................................84
5.3EL MANEJO DE EVENTOS................................................................................................................. 86
Wating.......................................................................................................................................86Polling....................................................................................................................................... 87Direct.........................................................................................................................................87
5.4ADD-ONS PARA SDL.......................................................................................................................... 88
5.5SDL CON OPEN GL..............................................................................................................................88
6TÉCNICAS DE INTELIGENCIA ARTIFICIAL APLICADAS A VIDEOJUEGOS....................................92
LA ILUSIÓN DE INTELIGENCIA..........................................................................................93REQUISITOS ACADÉMICOS................................................................................................ 94
6.1MÁQUINAS DE ESTADO FINITO (FSM)...........................................................................................94
6.1.1TABLAS DE ESTADOS DE TRANSICIÓN.................................................................................976.1.2REGLAS EMBEBIDAS................................................................................................................. 976.1.3CLASES DE BASE Y EL PATRÓN SINGLETON.....................................................................1006.1.4CAMBIOS DE ESTADO: EL MÉTODO INEFICAZ..................................................................1026.1.5IMPLEMENTACIÓN DE ESTADOS..........................................................................................1036.1.6CAMBIOS DE ESTADOS: MÉTODO CON FSM......................................................................107
...................................................................................................................................................................109
6.2MOVIMIENTOS AUTONOMOS........................................................................................................110
¿QUÉ ES UNA ENTIDAD AUTÓNOMA?...........................................................................1116.2.1CAPA DE LOCOMOCIÓN: EL MODELO DE MOVIMIENTO................................................1116.2.2CAPA DE DIRECCIÓN: COMPORTAMIENTOS DIRIGIDOS................................................ 115
BUSCAR (SEEK)................................................................................................................... 115HUIR (FLEE)..........................................................................................................................116LLEGAR (ARRIVE)...............................................................................................................116PERSEGUIR (PURSUIT).......................................................................................................117EVADIR (EVADE).................................................................................................................120
6.2.3 EL MÉTODO DE CÁLCULO DE FUERZAS............................................................................1206.2.4PROBLEMAS CON LOS COMPORTAMIENTOS DIRIGIDOS...............................................123
SIN SOBREPOSICIÓN.......................................................................................................... 123EL EFECTO DE TEMBLORINA.......................................................................................... 125
7CONCLUSIONES........................................................................................................................................ 128
8APÉNDICE A Imágenes de AmorpheBios v0.7.......................................................................................... 131
9APÉNDICE B Dibujo...................................................................................................................................134
9.1MODELADO 3D..................................................................................................................................134
9.2SPRITES Y TEXTURAS..................................................................................................................... 140
4
10APÉNDICE C 3D Engine / Game Engine..................................................................................................143
11BIBLIOGRAFÍA........................................................................................................................................ 145
5
1 INTRODUCCIÓN
Acerca del diseño, análisis e implementación de juegos1 se ha escrito mucho, sin embargo las posibilidades de crear, innovar o perfeccionar juegos siguen siendo campo de cultivo para los nuevos y jóvenes creadores, cuyo resultado es constantemente esperado por el consumidor aficionado a estas aplicaciones. El grado de complejidad en la implementación de un juego ha sido una característica muy difundida entre los programadores, reputación que ha prevalecido desde los inicios comerciales de estas aplicaciones en la década de los 70’s hasta nuestros días, sin duda esta complejidad no es producto de un mito, sino de una realidad. Seguramente durante muchos años continuará esta reputación, mientras tanto los diseñadores y programadores de juegos seguirán lidiando con tareas de muy alto y muy bajo nivel, teniendo la esperanza de que en algún momento un solo lenguaje portable (multiplataforma) para programar juegos pueda ser utilizado por las distintas compañías alrededor del mundo, una esperanza que debido a los beneficios económicos obtenidos de este tipo de software esta cada vez más lejana.
El propósito de este proyecto terminal es mostrar una metodología confiable para la creación de un juego, por otra parte describir todos los procesos que se requieren para la creación del mismo, desde que nace en la mente de un creador de juegos, su concepción, pasando por su definición, análisis y diseño hasta su implementación. No puede dejar de mencionarse que queda fuera de los alcances de este proyecto demostrar que esta metodología generará una aplicación entretenida y divertida, que es el objetivo último en la creación de este tipo de software, pero con este objetivo contemplado, el proyecto tendrá el compromiso de acercarse a esta meta durante todo el proceso de desarrollo.
El proyecto iniciará mostrando el proceso de concepción y análisis del diseño de un juego, con base en este diseño se elaborará un documento de diseño que servirá para iniciar la primera aproximación para una implementación del software. Esta primera aproximación servirá para elaborar documentos directamente relacionados con el proceso de implementación según el criterio de análisis y diseño de sistemas (como es el caso del documento de requerimientos).
En la segunda etapa del proyecto se generará la implementación a partir de este análisis utilizando alguna de las librerías multimedia de distribución libre, posteriormente se desea mostrar el principio de desacoplamiento al trasladar la aplicación de una librería a otra. Esta implementación será la línea de desarrollo “trunk”, permitirá contemplar las necesidades para la construcción de un GameEngine desde cero y quedará como base para un futuro proyecto que desee construir un Engine propio del juego.
En una tercera etapa se investigará, implementará y asociarán algunas técnicas de Inteligencia Artificial (IA) indispensables para cumplir con las características del documento de diseño (también contempladas en el documento de requerimientos). Finalmente se integrarán todas las técnicas y características descritas en una línea de desarrollo “branch”, para construir el prototipo del juego sobre un 3D Engine de distribución libre.1 Por brevedad se utilizará indistintamente el término juego, videojuego o juego de video
6
2 DESARROLLO DE VIDEOJUEGOS
Como un área relativamente joven en el área de computo (aproximadamente 30 años de existencia), los juegos han demostrado ofrecer alternativas de entretenimiento y diversión con altos beneficios en términos económicos. La diversidad y libertad en los distintos géneros han incluso propiciado la posibilidad de transmitir cultura y aprendizaje.
La juventud de este extensa rama de desarrollo computacional no permite especificar el impacto social, económico y cultural aún, pero la demanda de consumo que se tiene en nuestros días no permite detenerse a reflexionar sobre estas características, en cambio obliga a los diseñadores de juegos mayor cantidad de conocimiento y equipos más grandes de producción para satisfacer las necesidad de los productos.
El desarrollo base de cualquier juego de actualidad es concretado por grupos de individuos de disciplinas artísticas, computacionales, financieras, etc., sin embargo en la mayoría de los casos, la idea principal proviene de una sola persona, este individuo análogo al Director de cine se le denomina: Diseñador de juegos.
En este capítulo se mostrará el proceso de descubrimiento para la creación de un juego cuya jugabilidad es propuesta por un diseñador de juegos. Durante este proceso la imaginación del diseñador es utilizada para la creación de ideas concretas y simples que permitan esclarecer la jugabilidad del juego, (término que se explicará más adelante), su temática y los criterios de puntuación entre otras características más específicas.
El capitulo comienza mostrando algunas definiciones, problemáticas y características relativas al desarrollo de juegos utilizadas a través de todo el documento.
El primer objetivo será la creación de una idea concreta conocida como enfoque del juego, este enfoque conciso y sencillo es utilizado como base para la creación de otros documentos de mayor extensión y como punto de partida para la discusión en un posible equipo de desarrollo. El enfoque del juego es creado según tres orígenes (o mezclas de ellos) muy conocidos en el campo de desarrollo de juegos: jugabilidad, historia o tecnología. El enfoque del juego es muy útil para mantener el control y límites durante el desarrollo, al final de todo el proceso de implementación se puede medir el grado de control del proyecto dependiendo del parecido entre el prototipo y el enfoque original. La mayoría de los creadores de juegos que han elaborado un buen diseño, han enfatizado la importancia y trascendencia de esta idea, cuanto mayor creatividad e ingenio tenga el diseñador del juego, mayores posibilidades se tendrán para obtener un enfoque del juego interesante que se mantenga hasta el final de la implementación.
El segundo objetivo es la creación de un documento de diseño, este documento es el de mayor importancia para el equipo de programadores que desarrollarán el juego en etapas posteriores al primer prototipo, sin embargo puede ser útil para esclarecer ideas en diseñadores novatos como es este el caso. Los
7
recursos gráficos y definiciones de características específicas son algunas de las herramientas que permiten ayudar a acelerar el proceso de descubrimiento del juego. Crear un documento de diseño previo al prototipo se hace necesario, pues gracias a este documento es posible construir un diagrama de flujo que describe el proceso de construcción de prototipos iterativos (de crecimiento gradual), basados en la información de dicho documento.
El último objetivo de este capítulo será obtener este diagrama de flujo que describe la construcción del prototipo.
.
En la figura 2-1 se muestra el proceso requerido para la creación del diagrama de flujo:
8
Figura 2-1
Proceso de desarrollo de un juego
2.1 DEFINICIONES PARA EL DESARROLLO DE VIDEOJUEGOS
Para puntualizar el contexto de desarrollo comenzaremos con definir el término jugabilidad, según Richard Rouse III un prestigiado diseñador de juegos es lo que hace “nuestra forma de arte única”.
La jugabilidad se define como la forma en como se juega determinado juego.
Es común encontrar en los procesos de desarrollo de software un documento de diseño que permita establecer claramente los requerimientos de la aplicación, no es la excepción en el caso de los juegos, sin embargo una característica indistinguible para un documento de diseño de un juego es la jugabilidad, gracias a esta característica se necesita de un proceso previo al documento de diseño, tan indispensable para el desarrollo de software convencional, el diseño del juego.
En el diseño del juego también se encuentran características como la puntuación del jugador, el criterio de ganar o perder, como se controlará el juego, que información interactuará con el jugador y opciones de la modificación del nivel de dificultad entre otras.
Siendo estrictos con la definición de jugabilidad podemos identificar claramente entre características tecnológicas y de diseño, cuanto más grande sea el desarrollo del juego más necesaria es esta identificación.
9
Figura 2-2
El diseñador del juego y su interacción con distintas disciplinas
En el lenguaje coloquial la expresión diseño del juego se usa de manera indiscriminada para aquellos que participan en la realización de un juego: artistas, programadores, depuradores, etc. pero en el campo de desarrollo de juegos, el diseñador de juegos es el individuo encargado de crear el diseño del juego. El diseñador de juegos es aquel que establece el fondo y forma de un juego en específico junto a su jugabilidad. Por su naturaleza creativa puede o no participar en una, alguna o todas las actividades que envuelven su proyecto sin dedicarse de forma única a alguna de ellas, con el fin de obtener los resultados más cercanos a su idea original junto al equipo de trabajo. Es obvio notar la gran demanda de personal muy especializado en ramas como IA, modelado en tercera dimensión, diseño de texturas o música lo que dificulta formar equipos tan específicos y comprometidos, mucho se menciona que cada grupo desarrollador tiene su particular metodología para resolver esta problemática. En la figura 2-2 podemos visualizar algunas de las distintas disciplinas y su interacción con el diseñador del juego.
Al crear un nuevo diseño de un juego otras características deben ser consideradas y balanceadas si se desea construir una aplicación divertida; por un lado tenemos características específicas al tipo de jugabilidad y por otro las innovaciones del diseño del juego. El la tabla 2-1 se encuentran comparadas algunas de estas características, como ejemplo de problemática en el diseño del juego podemos observar la necesidad de construir aplicaciones creativas y diversas sobre paradigmas.
JUGABILIDAD DISEÑO DEL JUEGO
Juego para solitarios o en equipo
Creatividad y diversidad
Información mostrada al jugador
Paradigmas
Control intuitivo
Público al que va dirigido
Características psicosociales
Tabla 2-1
Características de la jugabilidad y del diseño del juego
La idea principal del diseñador del juego debe contemplar los paradigmas y al mismo tiempo insertar nuevos conceptos sin que ello represente un problema de jugabilidad. Algunas de las características que son casi una regla para la elaboración de juegos de calidad son extractos de características de juegos de gran éxito, sirven de guía para el diseñador de juegos para indicarle en que momento y hasta donde es posible romper con los paradigmas:
Mundos consistentes: se refiere a la percepción del jugador
10
Límites del juego: con cuanta claridad se muestra lo que se puede y lo que no se puede hacer en el juego
Límites del juego: con cuanta claridad se muestra lo que se puede y lo que no se puede hacer en el juego
Buscar soluciones factibles de resolver: anticiparse a la lógica del jugador
Dirección: objetivo del juego
Retos constantes
Identificación con los personajes
Grado de interacción: se desea la máxima interacción posible
Avance frustrado: hacerle pensar al jugador que el es más inteligente que el juego
¡¡Sorprender al jugador!!
Memoria del juego: característica que se ha hecho indispensable sobre todo en las últimas décadas ya que se han propiciado juegos de muy extensa duración, los diseñadores están obligados a crear dispositivos de almacenamiento permanente para los avances del jugador
2.2 LOS ORÍGENES DE LA IDEA DE UN JUEGO
Cuando el espectro de posibilidades de creación queda limitado por los paradigmas esperados por los jugadores parece ilógico pensar en la diversidad de géneros que se han creado, sin embargo surge la necesidad de definir los orígenes de un juego, es entonces cuando otras perspectivas del desarrollo surgen y con ellas su diversidad.
11
Existen tres orígenes del diseño del juego descritos en la tabla 2-2:
Origen del diseño
Descripción
Jugabilidad El más común de los orígenes y se refiere al tipo de vista que el jugador tendrá en el mundo, se representa en 2D o en 3D,
limitaciones tecnológicas que se conocen
Tecnología El menos común se refiere a aspectos de software (como el Engine con el que se
cuenta) y hardware (las interfases)
Historia Menos común que la jugabilidad pero ha tomado fuerza con los años con libretos más
sofisticados y sólidos
Tabla 2-2
Origen del diseño del juego
La mezcla de estos tres orígenes han sido la vanguardia recientemente y de mayor importancia se ha vuelto la relación entra cada una de ellas. Específicamente la concepción del juego de este proyecto se encuentran dos elementos de origen: jugabilidad e historia.
En los primeros instantes en que se pensó acerca de la creación de un juego el objetivo era generar una jugabilidad intuitiva pero que no se hubiera visto, una mezcla de tipos de jugabilidad con un sustento en una pequeña historia que genere curiosidad e interés.
2.3 EL ENFOQUE DEL JUEGO
En el proceso de desarrollo de software convencional existen métodos que permiten abstraer casi directamente requerimientos de una necesidad hacia la implementación, sin embargo que sucede cuando el software no tiene definidas todas las necesidades de implementación en sus inicios, como es el caso de un juego que propone una nueva jugabilidad. Para comenzar por descubrir estas necesidades es necesario crear una descripción conocida como enfoque del juego, el diseñador Richard Rouse III proporciona una guía de preguntas para facilitar este procedimiento. A continuación se muestra el proceso de descubrimiento del enfoque del juego de este proyecto.
¿Qué consideras de este juego lo más importante?La mezcla de velocidad (característico de un juego tipo “shooter” 2D) y
12
destreza, con esta mezcla se espera lograr una mayor interactividad al ser construida en un mundo 3D
¿Qué pretendes lograr con tu juego?Mostrar algunos de los elementos que conforman las imágenes 3D, además de demostrar la necesidad de implementar juegos en mundos 3D para una mayor y natural interacción con la lógica humana
¿Qué tipo de experiencia tendrá el jugador?Completará misiones siendo el protagonista en la creación de la vida, sumergiéndolo en una historia breve contada a través de las misiones, donde se encargará de reanimar seres vivos extintos
¿Qué tipo de emociones evocarás?Curiosidad, adrenalina, sugestión, y adicción, el jugador estará constantemente ocupado
¿Qué recordará y permanecerá en el jugador?La necesidad de resolver o mejorar los retos, necesidad de un conclusión al combinar los distintos fragmentos de historia relatada a través de los niveles. Recordará las emociones originadas al observar cuerpos orgánicos en detalle
¿Qué hace este juego único, qué lo diferencia de otros?
La combinación de dos distintos modos de juego, que de manera natural se relacionan cuando se desea obtener un nivel de interacción mayor
¿Qué tipo de control utilizará?En principio se utilizará la interfaz estándar de una PC, sin embargo se desea diseñar y construir una interfaz especializada
13
Estas respuestas son suficientes para poder crear el enfoque del juego. La definición del enfoque servirá como herramienta de trabajo para el equipo de desarrollo, deberá dar flexibilidad a cambios pero establecer límites a intereses externos.
AMORPHE BIOS es un juego de estrategia y habilidad mental, una mezcla de rompecabezas y disparador en primera persona en un mundo en tercera dimensión. El
jugador creará objetos orgánicos buscando la combinación adecuada en gastos de recursos auxiliares con un tiempo limitado de construcción. Esta aventura lo trasladará a mundo micro y macro cósmicos. Resolverá misiones que le mostrarán vestigios de algunos objetos inanimados esperando a ser resurrectos. Al completar una
serie de objetos se deberán seleccionar en orden o contexto para crear un ser vivo. Al final de cada misión se le mostrará un pequeño mensaje acerca de la evolución de la vida en el planeta tierra, oculto en parte del ADN del ser vivo que fue creado. Se le dará la posibilidad de múltiples desenlaces dependiendo
el criterio y velocidad del jugador.
2.4 DOCUMENTACIÓN DE VIDEOJUEGOS
La necesidad de documentar durante el proceso de desarrollo de un juego es un efecto colateral del incremento del tamaño de los equipos, la época donde una sola persona era suficientemente talentosa para implementar todo el desarrollo, la documentación era innecesaria. Mientras los equipos de desarrollo aumentan (la tendencia es que sigan aumentando), mantener el enfoque del proyecto es más complicado. La diversidad de especializaciones de las distintas áreas que conforman un juego hacen más complicada la tarea de documentar clara y correctamente, los documentos de referencia se hacen más necesarios junto a prototipos que indiquen el funcionamiento de un sistema, de esta forma varias piezas de la documentación se hacen útiles: el documento de diseño, el diseño artístico, el documento de diseño técnico y numerosas referencias que interactúan para la creación del contenido del juego. En este sentido, la documentación puede ser una clave para “mantener las riendas” del proyecto.
La documentación ha demostrado ser útil no solo para la parte de producción del juego, sino para las improvisaciones del diseño por si mismo. Chris Crawford diseñador prestigiado de juegos, menciona la importancia de sus proyectos al momento de documentar, con el fin de refinar y mejorar sus propias ideas. Independientemente del tamaño del proyecto o ambiciones, la documentación será indispensable.
14
Como diseñador de juegos el documento más indispensable y que conforma todos los elementos núcleo del juego es el conocido como documento de diseño, consecuentemente a la elaboración de este documento (junto a su respectivo prototipo del juego) se elaborará documentación más especializada en las distintas disciplinas: artística, tecnológica, administrativa, etc.
A continuación se mencionan las clasificaciones de documentación más comúnmente encontradas en proyectos comerciales:
● Documento de concepto o propuesta: utilizado en empresas o franquicias
● Análisis competitivo: ventas y análisis del mercado
● Documento de diseño: también conocido como de especificaciones funcionales describe detalladamente la jugabilidad
● Organigramas: opciones del juego fuera de su jugabilidad (menús)
● Historia: para juegos cuyo enfoque esta basado en un historia
● Guión: solo si existe el documento anterior
● Historia artística: bosquejos y descripciones artísticas de los elementos visuales del juego
● Un minuto del juego: describe en detalle una pequeña sección de la jugabilidad
● Tarjetas sinópticas: elementos gráficos que pueden estar contenidos dentro del documento historia
● Documento de diseño técnico: hermano de documento de
15
diseño, describe elementos específicos a la implementación (detalles de programación)
● Documentos de mercado, administración y negocios: son documentos que buscan la creación de productos para generar altos niveles de ventas
En este caso particular, el proyecto no tiene implicaciones comerciales por ello se describirá el documento de diseño que es una extensión del enfoque del juego de AmorpheBios, en el capitulo 4 detalles referentes a la implementación del juego serán abordados desde el punto de vista de análisis y diseño de sistemas.
2.5 EL DOCUMENTO DE DISEÑO
INTRODUCCIÓN
AMORPHE BIOS es un juego de estrategia y habilidad mental, una mezcla de rompecabezas y disparador en primera persona en un mundo en tercera dimensión. El jugador creará objetos orgánicos buscando la combinación adecuada en gastos de recursos auxiliares con un tiempo limitado de construcción. Esta aventura lo trasladará a mundos desde el microcosmos hasta el macrocosmos. Resolverá misiones que le mostrarán vestigios de algunos objetos inanimados esperando a ser resurrectos. Al completar una serie de objetos se deberán seleccionar en orden o contexto para crear un ser vivo. Al final de cada misión se le mostrará un pequeño mensaje acerca de la evolución de la vida en el planeta tierra, oculto en parte del ADN del ser vivo que fue creado. Se le dará la posibilidad de múltiples desenlaces dependiendo el criterio y velocidad del jugador.
El jugador debe reconstruir muestras de materia sub-orgánica tridimensional dentro de un laboratorio de tecnología avanzada. Esta materia sub-orgánica luce degradada y corrupta, el jugador se encarga de reconstruir cada materia sub-orgánica para darle vida. El jugador podrá controlar la vista de la materia tridimensionalmente encontrando sus defectos y faltantes. Una misión consiste en relacionar los distintos segmentos sub-orgánicos colectados. Al completar alguna relación, un conjunto de ADN’s son suficientes para descifrar un fragmento de la historia de esa vida y se completa una misión. Al construir y relacionar la materia sub-orgánica el jugador es atacado por agentes patógenos virus, bacterias, en general contaminantes. Con la tecnología avanzada disponible deberá ser capaz de controlar o destruir los niveles porcentuales de los agentes. Al transcurso de las misiones el nivel de microcosmos aumenta gradualmente hasta llegar al nivel de complejidad orgánica del jugador. Al final deberá descifrar el código genético más susceptible a agentes patógenos, el código genético de un homo sapiens.
16
Mediante dos aditamentos podrá controlar a los agentes patógenos: un destructor y un anti-patógeno. El jugador puede cambiar los modos del juego construcción y ataque. El destructor es una mira que ofrece un rango total de disparo al jugador. Con el anti-patógeno podrá controlar el porcentaje de agentes patógenos no destruidos para evitar el 100% de contaminación. Mientras es atacado, algunas piezas tridimensionales son seleccionadas para colocarse en la muestra sub-orgánica, la generación de etiquetas es realizada al azar al principio de cada muestra.
Los jugadores estarán motivados por conocer los distintos niveles orgánicos que conforman esa vida y su nivel de detalle, estarán constantemente ocupados relacionando figuras geométricas tridimensionales y con una tensión variante para controlar los ataques que sufrirá la materia sub-orgánica.
MECÁNICAS DEL JUEGO
PRIMERA IMPRESIÓN
Al igual que los juegos de rompecabezas la primera impresión del jugador debe ser la necesidad de construir un molde tridimensional, las piezas del rompecabezas estarán conformadas por una serie de etiquetas tridimensionales de geometría definida (cónicas, esféricas, cúbicas y tetrahédricas) y una figura tridimensional con una gran presencia en pantalla llamada materia, la materia presenta regiones incoloras que indicarán sus defectos y faltantes. Estas regiones son presentadas una a una al jugador en el rango de vista que se abarque con la cámara. A cada presentación la etiqueta faltante parpadea gradualmente hasta desaparecer y mostrar una nueva etiqueta en otra región. La materia debe tomar color y forma bien definidos al completar sus etiquetas. Al terminar con las etiquetas mostradas en el rango de visión del jugador, este estará obligado a rotar la figura para la búsqueda de nuevas etiquetas. En la figura 2-3 se muestra un ejemplo de una materia completada 100%.
17
Figura 2-3
Materia original
En la figura 2-4 se puede observar un modelo de visor que indica las posiciones válidas para colocar etiquetas sobre la materia, esta vista nunca es mostrada el jugador.
La figura 2-5 muestra un instante de tiempo en el que una sola geométrica del visor es mostrada el jugador.
18
Figura 2-4
Modelo de generación del visor
Figura 2-5
Vista instantánea del visor
La figura 2-6 contiene las distintas etiquetas disponibles para el jugador listas para ser colocadas en la región del visor.
LA MANIPULACIÓN DE LA MATERIA
El jugador podrá manipular todos los ángulos de visión la materia, además de ocupar gran parte de la visión del jugador. La manipulación se efectuará mediante los comandos “arriba”, “abajo”, “izquierda” y “derecha”. Al estar en la posibilidad de rotar la materia en cualquier dirección, el jugador la manipulará y encontrará la generación automática de ciertas etiquetas con un limite de tiempo, esta vista automática es la que llamaremos visor. El visor se colorea con una geometría, a la búsqueda exhaustiva de las etiquetas faltantes a la vista del jugador. El jugador intentará coincidir con la geometría de las etiquetas y la mostrada por el visor en un tiempo determinado. La generación de etiquetas se realizará al azar sobre la materia, a partir de ella se obtendrán todas las etiquetas necesarias para completarla eliminando la posibilidad de faltantes.
ETIQUETAS Y SU INTERACCIÓN
Al inicio el número de etiquetas que se presentarán será de 4, a la acción de utilizar una etiqueta en alguna zona de la materia le llamaremos construcción, debido a la variedad de selección utilizaremos 4 comandos “selecciona pieza 1”, …, “selecciona pieza 4” para su manipulación. La forma de la etiqueta deberá coincidir con el de la materia, en caso contrario se emitirá un mensaje de ERROR en la sección de la materia.
19
Figura 2-6
Etiquetas y materia
EL TIEMPO Y LA DIFICUTAD
Existirá un limite de tiempo que genera la creación y liberación de agentes patógenos atacando a la materia. La liberación de los agentes se genera de manera gradual, dando la sensación al jugador de un próximo ataque masivo. Al tener una temporización natural y otra por la lentitud del jugador al colocar las piezas, se generará un ataque masivo que incrementa los niveles de contaminación radicalmente. La física del movimiento de la materia estará controlada por su peso, mayor cantidad de agentes mayor peso en la materia alentando su manipulación.
ARMAS Y SU CONTROL
Se utilizarán 4 GUI’s expresadas porcentualmente, la cantidad de anti-patógeno con la que cuenta para cada caso de materia denominada cura, conocer el nivel de contaminación de la materia evitando llegar al 100% llamada contaminación y la cantidad de etiquetas que le restan para completar la materia resto. La última GUI representará la cantidad de materias completadas, al llegar al 100% permiten la creación de una materia más compleja biologicamente, la GUI se denomina vivos. Una GUI para el manejo de los errores llamada error y una GUI para el manejo de la puntuación llamada puntuación.
En la figura 2-7 se muestran algunos de las distintas GUI's necesarias para la interacción con el jugador.
20
Figura 2-7
Algunas GUI's
LA PUNTUACIÓN, EL NIVEL COMPLETADO Y EL FIN DE JUEGO
Puntuación: si el jugador coloca una etiqueta en la geometría correspondiente genera puntuación a su favor, si el jugador destruye un patógeno genera puntuación a su favor, si el jugador utiliza el anti-patógeno genera puntuación en su contra.
Fin del juego: si el jugador no construye más del 50% de etiquetas en un cierto limite de tiempo el juego termina, si los patógenos clonan más del 50% de las etiquetas el juego termina, si el porcentaje de contaminación es del 100% el juego termina.
Nivel completado: un nivel es completado si el jugador logra construir más del 50% de las etiquetas sin llegar a el nivel de contaminación del 100%.
INTELIGENCIA ARTIFICIAL
LA DIFICULTAD CON LAS ETIQUETAS
La serie de etiquetas presentadas aumentará de 4 a 6 ó de 6 a 8 si el jugador presenta tiempos de construcción muy cortos. La información de las GUI resto mostrará al jugador que a menos cantidad porcentual de resto menor tiempo de generación de agentes, con ello mayor cantidad de etiquetas en un mismo tiempo aumentará la tensión del jugador y complejidad de la construcción.
COMPORTAMIENTO DE LOS AGENTES PATÓGENOS
Los agentes se encontrarán con dos situaciones de comportamiento: Regiones sólidas de la materia, dependiendo de la distancia relativa a una etiqueta se quedará donde esta para intentará penetrar o se moverá hacia la etiqueta más cercana para entrar en la materia Regiones etiquetadas, entrarán directamente en la materia. En la figura 2-8 se muestra una pequeña ola de ataque de los patógenos
21
AFECTACIÓN DE LA MATERIA DEBIDO A LOS AGENTES
La manipulación libre de la materia se verá afectada por la cantidad de agentes que se encuentren en su superficie alentando el movimiento y dificultando la colocación de las etiquetas. Cuanta mayor cantidad de agentes destruya mayor facilidad de movimiento en la materia
ELEMENTOS DEL JUEGO
ARTÍCULOS
Todos los destructores contienen los movimientos descritos en la mecánica del juego. El destructor se muestra como una mira (blanco) de un disparador en primera persona. La forma de la mira del destructor incita al jugador a saber sobre sus futuras capacidades.
Destructor: disparador discontinuo que permite eliminar agentes patógenos al apuntar hacia ellos
Destructor mejorado: disparador con mayor anchura de disparo discontinuo
22
Figura 2-8
Ataque de patógenos
Destructor sólido: disparador tipo rayo LASER continuó con mayor anchura de disparo
Los anti-patógenos no tienen movimiento como se describe en la mecánica del juego. Los anti patógenos son purificadores de la materia y permiten detener el proceso de contaminación de patógenos activados.
Anti-patógeno: reduce el tiempo de contaminación de los agentes
Anti-patógeno mejorado: mayor reducción del tiempo de contaminación
La materia es el elemento visual más representativo y detallado que es manipulado mediante los comandos descritos en la mecánica del juego, según el avance del jugador la figuras presentadas son de mayor complejidad biológica.
Las etiquetas son figuras tridimensionales solo manipuladas por los comandos descritos en la mecánica del juego, presentan 4 distintas formas geométricas con un color asociado: esfera, cubo, cuadrado y tetraedro.
Ejemplos de organismos consecuencia de la construcción de múltiples materias:
Amonite: consecuencia de la mezcla de una célula, plancton y trilobite en la
figura 2-9 se muestra una vista de esta materia
23
Figura 2-9
Materia Amonite
Humano: consecuencia de la mezcla de un ojo, corazón y cerebro
PERSONAJES
En esta primera etapa de deseará construir un nivel de prueba con tres tipos de materia que al final originarán un organismo conocido como Amonite. Al final de la misión se presentará una “cut-scene” breve acerca de la evolución de los seres vivos que dio como origen la creación del trilobite. El desarrollo y desenlace es fácilmente adaptable a un libreto no lineal, con múltiples bifurcaciones para ofrecer una distinta progresión al jugador. El escenario de construcción deberá mostrar un ambiente más hostil al progreso del juego, denotando el sentido de putrefacción que rodea a la materia.
SISTEMAS DE MENÚS
Pantalla de bienvenida con tres opciones: nuevo juego, cargar juego y especiales manipuladas con la interfase de estándar para PC Pantalla de pausa: permite detener la progresión del juego teniendo sin perder en el fondo de la pantalla con las opciones: salir, cargar y reiniciar juego
2.6 CONSTRUCCIÓN Y DEFINICION PARA EL PROTOTIPO 1 DE AMORPHE
BIOS
En el desarrollo de un prototipo para AmorpheBios se cuenta con dos visiones de desarrollo:
➢ La perspectiva del diseñador del juego: documento de diseño
➢ La perspectiva de análisis y diseño de sistemas
Aunque a primera vista ambas perspectivas parecen no estar relacionadas, durante el proceso de desarrollo se descubren analogías entre una visión y otra, más aún una visión sirve de herramienta a otra. Hasta este momento es insuficiente la información para comenzar un desarrollo de análisis y diseño de sistemas, por ello solo se describirá la visión del diseñador del juego definida por el documento de diseño y en el capitulo 4 se retomará.
LA PERSPECTIVA DEL DISEÑADOR DEL JUEGO
Muchos diseñadores de juegos son experimentados programadores que conocen a fondo las limitaciones técnicas con las que cuentan, al elaborar un juego el diseñador debe olvidar su compromiso tecnológico y diseñar en términos de un mundo ideal. Como ya se ha mencionado, la creación de juegos es un área
24
relativamente joven, es de suponer que aún no existen metodologías estándar para la creación de la jugabilidad en general, por ello se describe esta rama como de “naturaleza impredecible y de gran riesgo”. Sin embargo no todo es impredecible y riesgoso algunas herramientas han mostrado su eficacia y estabilidad a lo largo de los años, una de ellas es los prototipos iterativos y la otra es los lenguajes orientados a objetos (OO), juntos han servido para acelerar el proceso de construcción así como organizar multidisciplinariamente las distintas áreas de programación que conforman al juego, ambas características son necesariamente utilizadas en este proyecto. Los diseñadores de juegos han agregados términos que describen con mayor precisión el desarrollo de un juego, describiéndolo como un proceso orgánico. Algunas de las características para lograr un buen prototipo son:
● Sin documentos de diseño hasta tener al menos un prototipo del juego
● Despreocupación sobre los niveles, enfoque en la jugabilidad
● Prototipo completo ---> Documento de diseño
● Documento de diseño <---> Ajustes mínimos hasta refinar la jugabilidad
● Desarrollo incremental
En la figura 2-10 se muestra de forma resumida el desarrollo planeado para AmorpheBios:
25
Figura 2-10
Etapas de desarrollo de AmorpheBios: perspectiva del diseñador del juego
En el final de la figura 2-10 se alcanza el prototipo 1, este debe cumplir con los siguientes requisitos:
Disfrutarse por el propio diseñador
El reto y la creatividad del juego se encuentran en él
El siguiente proceso consiste en replicar y extender el concepto del prototipo, es en este momento cuando se puede elaborar el documento de diseño
Al obtener el prototipo 1 , generalmente programado por unas cuantas personas entran en actividad muchas otros individuos de áreas artísticas y de programación para elaborar un editor de niveles y así construir las misiones o mundos del juego. El ciclo más común requerido para la elaboración de niveles se muestra en la figura :
De manera concreta:
El editor de niveles se encarga de extender y complementar el enfoque del juego
El editor de niveles es un tipo de implementación que se acerca más al software convencional
Definir el nivel de funcionalidad del editor de niveles para encontrar un equilibrio con su tiempo de desarrollo
26
Figura 2-11
Editor de niveles: perspectiva del diseñador del juego
Generalmente es un programa con errores pero funcional
Las mejores herramientas de hoy día son una adecuada mezcla de programas de licencia y editores propios. Un buen equipo de desarrollo sabe complementar un tipo con el otro para ahorrar tiempo y no terminar desarrollando aplicaciones más complejas que el juego en realidad. Una herramienta como el editor de niveles debe permitir manipulaciones y ajustes estáticos y gráficos, al igual que las otras funcionalidades mencionadas.
Este capítulo permite concluir que el proceso de descubrimiento de un juego al proponer una nueva jugabilidad es subjetivo, aún sin involucrar características artísticas (de gran importancia actual), la subjetividad esta ligada a las habilidades, limitaciones y contexto del diseñador entre otras características. Los tres objetivos contemplados; el enfoque del juego, el documento de diseño y la creación de un diagrama de flujo para el prototipo del juego, fueron completados en su totalidad, este proceso llevo alrededor de 2 meses de trabajo.
Esta etapa de desarrollo es de suma importancia debido a que se establecen limites que abarcan aspectos creativos y de innovación en procesos subsiguientes.
A pesar de la recomendación de diseñadores experimentados de crear el prototipo y luego el documento de diseño, fue necesario en este caso crear primero el documento de diseño debido a la inexperiencia de desarrollo, en futuros proyectos se podrá omitir esta elaboración pues la experiencia permitirá evaluar y predecir algunas problemáticas.
Para acelerar el proceso de desarrollo en diseñadores novatos es recomendable iniciar implementando juegos de jugabilidad conocida, así el proceso de descubrimiento queda excluido y solo se puede elaborar un diagrama de flujo para directamente iniciar el proceso de análisis y diseño del sistema tal como se plantea en el capítulo 4.
Aunque no se contempló la posibilidad de crear el editor de niveles se muestra el diagrama de flujo, pues esta aplicación es mucho más común para la mayoría de los juegos (es implementada con procesos de software parecidos a los de cualquier aplicación administrativa) se muestra el ciclo más comúnmente utilizado para la elaboración de esa etapa al final del capítulo.
Una de las llamadas tareas de alto nivel de abstracción necesarias para la construcción del juego involucran el diseño del juego, esta tarea de alto nivel fue completada en este capítulo, gracias a esto es momento de completar otras tareas para lograr una implementación, por la naturaleza del diseño del juego y las características técnicas que se especifican es necesario conocer como construir juegos 3D, por ello el siguiente capitulo se encargará de mostrar algunas de las técnicas utilizadas para manipular, desplegar y cargar imágenes 3D. Como es de esperarse esta tarea se refiere a un bajo nivel de abstracción, al terminar de analizar y desarrollar ambas tareas se estará en posibilidades de comenzar una implementación.
27
3 GRÁFICAS 3D EN LOS VIDEOJUEGOS
Existen en la actualidad muy pocas limitaciones tecnológicas para la creación de juegos con alto grado de refinamiento artístico y gráfico, la complejidad de lograr efectos muy elaborados e impresionantes es sin duda uno de los motivos del tiempo tan prolongado de desarrollo de un juego, hoy día se hace necesario contar con ellos casi de forma obligada. En el capitulo anterior pudimos encontrar algunos prototipos visuales que permiten orientar al programador sobre las necesidad gráficas y artísticas que se requieren, por este motivo en este capítulo se presentan alternativas utilizadas para lograr la visualización, manipulación y creación de las gráficas 3D.
En este capitulo se encuentran definiciones relativas a imágenes 3D así como su relación con librerías y lenguajes de programación. Posteriormente se muestran algunas de las herramientas necesarias para la captura de imágenes tridimensionales a través de un lenguaje de programación orientado objetos2. Estas herramientas incluyen el uso de paquetería que permita crear modelos tridimensionales, algunos de estos paquetes son 3D StudioMax, Maya, BLENDER entre otros. A partir de estas herramientas se crean archivos de texto que definan la geometría del objeto, mediante un “parser”3 sencillo se reconstruye el objeto haciendo uso de librerías conocidas como API4.
El capítulo inicia definiendo algunos conceptos utilizados en la visualización de imágenes 3D.
El primero objetivo de este capitulo es analizar las distintas opciones de formatos de texto para describir un modelo 3D, así como el formato mismo. Utilizando este conocimiento, se pretende crear un formato de texto que describa de la forma más sencilla posible la geometría del objeto 3D (un formato a la medida). Este formato de texto será implementado utilizando “scripts”, se creará el “parser” y se reconstruirá el objeto.
El segundo objetivo de este capitulo será introducir técnicas que permitan refinar la visualización del objeto así como proporcionar mayor información gráfica utilizada para el “debugging”, como ejemplos de ellos encontramos la sombras suavizadas o planas, la creación de normales para verificar iluminación entre otras.
2 Conocido en la literatura por sus siglas POO3 Un programa que se encarga de realizar un análisis gramatical sobre archivos con formatos predefinidos4 Acrónimo de Aplication Program Interfase
28
En la figura 3-1 se encuentra el proceso de desarrollo descrito:
3.1 HERRAMIENTAS
El desarrollo gráfico requiere utilizar un gestor de ventanas, en este caso se utilizo GLUT5, librería de distribución libre que ayuda a reducir la cantidad de código y tareas para poder ejecutar un juego (en general una aplicación multimedia) sobre un sistema operativo.
El desarrollo de juegos esta íntimamente relacionado con aplicaciones en tiempo real, donde tiempo real en el contexto de la computación se refiere a producir una secuencia de imágenes o animaciones en respuesta a alguna entrada como "joysticks", presión de teclas o cualquier otra cosa que sirva como entrada, estos eventos externos son controlados y verificados utilizando el paradigma de programación conocido como programación orientada a eventos, estos eventos son transmitidos a través de ventanas del sistema operativo, GLUT se encarga de administrar estos eventos.5 Aunque los gestores de ventanas no son indispensables en el desarrollo del juego, es recomendable su uso al principio del
desarrollo, ya que permite abstraer la complejidad de programar ventanas, si el lector conoce el WinAPI es inútil utilizar GLUT y es de hecho la forma más óptima de programar ventanas en el sistema operativo WINDOWS
29
Figura 3-1
Proceso de captura de gráficas 3D
En resumen la utilización de GLUT sirve para controlar los eventos y gestionar las ventanas que son necesarias para correr un juego sobre un sistema operativo, ¿cuándo se utilizarán las gráficas 3D?
Para la parte gráfica se recurre a otra librería de mucho mayor estabilidad, más específicamente se le conoce a este tipo de librerías como API: DirectX de Microsoft y OpenGL de Silicon Graphics son algunas de las más conocidas. Por su estabilidad, flexibilidad y licencia GPL limitada, se eligió a OpenGL como el API para la creación de gráficos. Es ahora conveniente mencionar que la librería GLUT debe su nombre al API OpenGL y es acrónimo de GL Utilities.
La paquetería encargada de crear los modelos 3D es BLENDER, elegida por su distribución libre y cuenta con distintas opciones para la creación formatos de texto que describan la geometría.
3.2 DEFINICIONES
Las siguientes definiciones son consecuencia del término Render. Render o rendering se conoce al acto de tomar una descripción geométrica de un objeto tridimensional y convertirla en una imagen en pantalla bidimensional. El API OpenGL es el encargado de llevar a cabo este proceso. Algunos efectos que se logran al “rerendear” en la pantalla con dicho API son:
•Perspectiva: ángulos entre líneas que dan la ilusión de tres dimensiones, el objeto puede estar construido por líneas con caras ocultas, las caras ocultas ocurren con los objetos sólidos y a este fenómeno se le conoce como “eliminación de superficies ocultas”, ambos comportamientos son manipulados por el algoritmo de z-buffer y de caras ocultas de OpenGL respectivamente
•Sombreado y color: OpenGL las sombras pueden ser FLAT o SMOOTH (lisas o suaves) y el color es puramente sólido
•Sombras y luz: el efecto de las fuentes de luz colocadas en una escena en OpenGL, las fuentes de luz son puntuales y como máximo se crean 8
•Mapeo de texturas: aplica una imagen fotográfica (del nivel de realismo deseado) a alguna superficie poligonal definida en OpenGL
•Niebla: efecto que modifica la forma en que la luz se propaga, además de modificar la sensación de atmósfera y espacio
•Mezclas y transparencias: imágenes superpuestas que dan la sensación de reflejos
30
•Anti aliasing: aliasing es un efecto generado en pantalla debido a la formación de figuras con pixeles, para mayor definición de la figura se desea eliminar el efecto aliasing, OpenGL provee también esta capacidad
3.3 OPEN GL
OpenGL se define como “una interfase de software para hardware de gráficos”. En esencia es una librería de gráficas 3D y modelado extremadamente portable y rápido. No es un lenguaje de programación, se parece mas a una librería de rutinas ejecutables de C.
Es posible obtener y utilizar la librería gratuitamente, pero si se desea comercializar una aplicación realizada con OpenGL necesita la licencia de SGI (Silicon Graphics).
Para cada plataforma existe una implementación de OpenGL:
SGI OpenGL: para Windows, opengl32.dll, localizado en el directorio
Windows/sistem32 del sistema
Mesa: una implementación no oficial de OpenGL, open source
Algunas definiciones y convenciones para el uso de OpenGL.
✔ Sistema coordenado: vertical eje Y, horizontal eje X y apuntando hacia afuera de la pantalla eje Z, en la figura 3-2 se muestra una vista del sistema coordenado
31
✔ Clipping: indica el valor mínimo y máximo de las variables x,y,z que definen el sistema coordenado
✔ Viewports: mapea coordenadas cartesianas en coordenadas de pantalla (desde un punto de vista muy general)
✔ Proyección: las coordenadas en 3D son proyectadas en un espacio 2D la pantalla, las proyecciones pueden ser ortográficas (rectangular clipping) o perspectivas (agrega el efecto de distancia y profundidad como el clipping es parecido a una pirámide de base rectangular se le conoce como frustum a este tipo de proyección)
✔ Double buffering: capacidad para ejecutar el código para un dibujo al tiempo de rerendear en un buffer independiente del de la pantalla (utilizado para animación o mejorar rendimiento)
32
Figura 3-2
Sistema coordenado en OpenGL: verde eje X, rojo eje Y
3.4 MODELADO 3D Y OPEN GL
3.4.1 LOS ARCHIVOS GENERADOS POR UN MODELADOR
Los programadores de juegos encuentran sus limitaciones más importantes al modelar en 3D o dibujar, ya que esta tarea es sumamente laboriosa y artística, queda fuera de los alcances del programador concretarla en su totalidad. En un proyecto de dimensiones pequeñas el programador debe ofrecer prototipos artísticos que al menos tengan el grado de funcionalidad y estilo deseado, no son un trabajo estrictamente profesional en términos de gráficas pero son indispensables para implementar un juego.
Toda compañía desarrolladora de juegos tiene un estándar para el manejo de sus archivos que describen algún modelo en 3D (antiguamente simples bit maps “sprites” que aún son más utilizados para las GUI’s), la diversidad de archivos para describir estos modelos esta soportada por el programa BLENDER6, con él podemos exportar formatos populares como son:
VRLM: acrónimo para Virtual Reality Modeling Language (Lenguaje para Modelado de Realidad Virtual), un ejemplo de un circulo formado por 10 aristas generaría un archivos de este tipo con extensión .wrl
DXF: archivos con extensión .dxf El formato de cada archivo ofrece sus ventajas y desventajas, por simplicidad y de manera temporal
el formato propuesto para utilizarse en los siguientes capítulos es el .obj de videoscope. La elección temporal de video scope es justificada por la simplicidad de su análisis y el pequeño parser que se necesitara para obtener la información contenida. Como ejemplo ilustrativo se lista el archivo exportado por BLENDER extensión .obj de un cubo simple.
6 BLENDER es un programa modelador 3D que incluye un motor de juegos, todo este programa fue codificado utilizando el API OpenGL
33
cubo_simple.obj
3DG1
8
1.000000 1.000000 -1.000000
1.000000 -1.000000 -1.000000
-1.000000 -1.000000 -1.000000
-1.000000 1.000000 -1.000000
1.000000 1.000000 1.000000
0.999999 -1.000001 1.000000
-1.000000 -1.000000 1.000000
-1.000000 1.000000 1.000000
3 4 0 7 0xcccccc
3 0 3 7 0xcccccc
3 2 6 7 0xcccccc
3 2 7 3 0xcccccc
3 1 5 2 0xcccccc
3 5 6 2 0xcccccc
3 0 4 1 0xcccccc
3 4 5 1 0xcccccc
3 4 7 5 0xcccccc
Son tres secciones que incluye este tipo de formato y se detallan a continuación.
● Magic Word: 3DG1 informa al lector del archivo el tipo de formato que se encuentra a continuación, esta palabra es mas conocida como MAGIC WORD
● Número de vértices y la descripción de cada vértice: Antes de listar todos los vértices contenidos en el modelo 3D se informa la cantidad de vértices totales que conforman al modelo, en este caso 8. El formato de punto flotante clásico de los vértices, análogo a la especificación de vértices en OpenGL (x,y,z) = 1.000000 1.000000 -1.000000
● Polígonos y colores: El cubo_simple.obj no solo esta formado por vértices sino también por polígonos (caras), la especificación de estas caras se hace con base en los vértices anteriormente definidos, 3 4 0 7 0xcccccc. La primera columna significa el numero de aristas que tiene nuestro polígono, las siguientes tres columnas significan la conexión de vértices (contados desde 0) para formar el polígono, en este caso vértice 4, vértice 0 y vértice 7 forman un polígono. La última columna no la utilizaremos por el momento pero significa el color de
34
esa cara
En la figura 3-3 mostramos el RENDER del modelo de un cubo simple en BLENDER7.
3.4.2 ARCHIVOS .OBJ Y OPEN GL
Se muestra la creación del parser para el formato .OBJ descrito en la sección anterior para poder ser leído por OpenGL. Todo el enfoque que se seguirá a partir de aquí es utilizando programación orientada a objetos (POO) con C++, se asume que el lector conozca bien los conceptos de la POO y el lenguaje C++.
LECTURA DE VÉRTICES
Para la lectura de los vértices se utiliza el namespace llamado std, específicamente
utilizaremos la clase vector para la introducción de las tres coordenadas en un solo
objeto, además se crea la clase Vertice que genera objetos con tres elementos
flotantes (x,y,z), este código es la función de captura de los vértices del archivo
“cubosimple.obj”:
7 El término RENDER es utilizado para resumir el proceso necesario de pintar o trazar en la pantalla una imagen a partir de una descripción geométrica del modelo 3D (o 2D), existen distintos tipos de RENDER provistos por los programas modeladores como BLENDER, estos tipos de RENDER dependen del algoritmo utilizado para lograr ese trazado en pantalla, en este caso se utilizó el algoritmo provisto por los desarrolladores de BLENDER llamado Blender Internal (también se puede utilizar el Vaf Ray y Rendering Engine aunque no he verificado su optimización ). El grado de optimización de un RENDER significan con cuanta calidad y en que tiempo se logra trazar en la pantalla los modelos
35
Figura 3-3
Cubo simple en BLENDER
//SE DECLARA GLOBALMENTE
using namespace std;
vector <Vertice *> lista;
//DENTRO DE UNA FUNCION QUE LEE ARCHIVO
ifstream archivoVertices(nombreArch.c_str());
std:: string basura;
int num_vertices,i;
float x1,y1,z1;
archivoVertices >> basura; // magic word
archivoVertices >> num_vértices; // lee numero de vértices
for(i=0; i<num_vertices; i++)
{
archivoVertices >> x1 >> y1 >> z1; // lee coordenadas
Vertice *v1 = new Vertice(x1,y1,z1);
lista.push_back(v1); // guarda coordenadas en la lista de vértices
}
TRAZADO DE VÉRTICES
Con los objetos Vertices (tantos como lo indique el numero del archivo), es necesario
recorrer la lista de vértices para desplegarlos con glVertex3f(x,y,z), la lista de vértices
es global y accesible desde cualquier método en la clase principal. El recorrido de los
vértices se logra mediante un iterador, el código de este recorrido se inserta en la función
display que es la encargada de realizar el render:
36
TRAZADO DE VÉRTICES 1/2
//iterador de tipo Vertice con nombre it
std:: vector<Vertice *> :: iterator it;
Vertice *v0,*v1,*v2;
glPointSize(10.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,1,1);
//DEFINICION DE LA PESPECTIVA DE LA CAMARA
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0f,1,1,-5);
//ACTUALIZACION DEL MOVIMIENTO DE LA FIGURA
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,20.0,0.0,0.0,0.0,0.0,1.0,0.0);
glRotatef(alfa, 1.0f, 0.0f, 0.0f);
glRotatef(beta, 0.0f, 1.0f, 0.0f);
...
37
TRAZADO DE VÉRTICES 2/2
...//TRAZADO DE LOS VERTICES
glBegin(GL_POINTS);
for(it=listaLados.begin(); it!=listaLados.end();it++)
{
v0 = lista.at( (*it)->dameLado0() );
v1 = lista.at( (*it)->dameLado1() );
v2 = lista.at( (*it)->dameLado2() );
//PARA VERIFICAR LA CORRECTA CAPTURA DE LOS VERTICES PUEDDES
//UTILIZAR LA SALIDA ESTANDAR DE CONSOLA
//cout <<(*it)->dameX() << "," <<(*it)->dameY() << "," <<(*it)->dameZ() << endl;
}
glEnd();
glFlush();
glutSwapBuffers();
En la figura 3-4 podemos observar el trazado de los vértices de el mismo cubo simple
modelado en BLENDER.
Se puede verificar la geometría del objeto utilizando el parámetro GL_LINE_LOOP o
GL_POLYGON al iniciar el trazado de los vértices.
38
Figura 3-4
Vértices del cubo simple
LECTURA DE LAS CARAS
El formato del archivo en su segunda parte de polígonos y colores debe estar con formato
de caras de tres aristas (tres vértices por cara), es precisamente este formato conocido
como triángulos el que se sigue como estándar para la creación de los modelos en OpenGL
y más adelante veremos porque. Al obtener este formato de caras triangulares,
guardaremos solo la información referente a los vértices en una clase vector del namespace
std, con una variable global asociada a una clase llamada Cara. La clase Cara colecciona
tercias de enteros que son las descripciones de relación entre vértices, este código se
agrega al método de captura del archivo después de llenar la lista de vértices:
vector <Cara *> listaLados;
int num_vertices,i, lado1, lado2, lado3
i=0;
while(!archivoVertices.eof())
{
archivoVertices >> basura;//se esperan siempre tres
archivoVertices >> lado1 >> lado2 >> lado3;
archivoVertices >> basura;//hexadecimales
i++;
Cara *l1 = new Cara(lado1,lado2,lado3);
listaLados.push_back(l1);
}
39
TRAZADO DE LAS CARAS
Al igual que se hizo con los vértices se utilizara un iterador en el método display para la
colocación de los vértices asociados entre si según el contenido de la listaLados.
//ITERADOR Y VARIABLES VERTICES
std:: vector<Cara *> :: iterator it2;
Vertice *v0,*v1,*v2;
for(it2=listaLados.begin(); it2!=listaLados.end();it2++)
{
glBegin(GL_TRIANGLES);
v0 = lista.at( (*it2)->dameLado0() );
v1 = lista.at( (*it2)->dameLado1() );
v2 = lista.at( (*it2)->dameLado2() );
glVertex3f( v0->dameX(), v0->dameY(), v0->dameZ());
glVertex3f( v1->dameX(), v1->dameY(), v1->dameZ());
glVertex3f( v2->dameX(), v2->dameY(), v2->dameZ());
glEnd();
}
Ahora el parámetro de glBegin() es GL_TRIANGLES que muestra la definición anterior de
polígonos de tres aristas para toda el modelo 3D. Para este momento nuestro cubo ya es
un sólido y luce como en la figura 3-5:
40
Y su modelo en alambre (utilizando el parámetro GL_LINE_LOOP) para la verificación de
polígonos de 3 aristas se muestra el figura 3-6:
ILUMINACIÓN Y MATERIALES
Este es el último proceso para la construcción del cubo agregando luz y material. Sin
embargo este proceso no es tan sencillo como los anteriormente realizados. Para lograr la
iluminación requerimos introducir una instrucción glNormal3f(x,y,z) a cada vértice para
indicar el sentido de reflexión de la luz, sin este parámetro la luz simplemente será
absorbida por el objeto teniendo como resultado una imagen completamente oscura y sin
color. El cálculo de las normales de vértices se extiende al calculo de las caras de tres
41
Figura 3-5
Cubo sólido
Figura 3-6
Aristas del cubo
aristas, es decir toda una cara contiene la misma normal produciendo el efecto de
sombreado GL_FLAT (sombras planas). Para el cálculo de las normales basta con
implementar operaciones vectoriales de suma, resta, magnitud y producto cruz entre dos
vectores descritos en 3D, por comodidad se utiliza el sobrecargado de operadores +, - e =
en la clase Vértice. De nuevo el método display se utiliza para construir la sombra del
objeto:
TRAZADO DE LAS CARAS CON ILUMINCACIÓN
for(it2=listaLados.begin(); it2!=listaLados.end();it2++)
{
glBegin(GL_TRIANGLES);
v0 = lista.at( (*it2)->dameLado0() );
v1 = lista.at( (*it2)->dameLado1() );
v2 = lista.at( (*it2)->dameLado2() );
//VERTICE AUXILIAR PARA EL CALCULO DE LA NORMAL DE LOS
VERTICES ACTUALES
Vertice normal = (*it2)->calculoNormal(*v0,*v1,*v2);
//LOS SIGUIENTES TRES VECTORES TENDRAN LA MISMA NORMAL
glNormal3f(normal.dameX(),normal.dameY(),normal.dameZ());
glVertex3f( v0->dameX(), v0->dameY(), v0->dameZ());
glVertex3f( v1->dameX(), v1->dameY(), v1->dameZ());
glVertex3f( v2->dameX(), v2->dameY(), v2->dameZ());
glEnd();
}
42
En la figura 3-7 se puede observar la distinta iluminación y reflejo de la luz en cada cara del cubo utilizando el color rojo ya mostrado en la figura 3-5:
NORMALES
Cuanto más información gráfica es agregada a la pantalla (lo que comúnmente se
denomina escena) mayor información de depuración es necesaria, por este motivo se
implementa el método que despliega las normales del cubo simple para comparar su efecto
de iluminación, como es un proceso de depuración es necesario deshabilitar las luces de la
escena:
43
Figura 3-7
Luz y material en el cubo simple
TRAZADO DE LAS NORMALES
glDisable(GL_LIGHTING);
for(it2=listaLados.begin(); it2!=listaLados.end();it2++)
{
v0 = lista.at( (*it2)->dameLado0() );
v1 = lista.at( (*it2)->dameLado1() );
v2 = lista.at( (*it2)->dameLado2() );
Vertice normal = (*it2)->calculoNormal(*v0,*v1,*v2);
glBegin(GL_LINE_STRIP);
glVertex3f( v0->dameX(), v0->dameY(), v0->dameZ());
glVertex3f( v0->dameX()+normal.dameX(), v0->dameY()+normal.dameY(), v0->dameZ()+normal.dame());
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f( v1->dameX(), v1->dameY(), v1->dameZ());
glVertex3f( v1->dameX()+normal.dameX(), v1->dameY()+normal.dameY(), v1->dameZ()+normal.dame());
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f( v2->dameX(), v2->dameY(), v2->dameZ());
glVertex3f( v2->dameX()+normal.dameX(), v2->dameY()+normal.dameY(), v2->dameZ()+normal.dame());
glEnd();
}
glEnable(GL_LIGHTING);
Ahora en cada vértices del modelo se encuentran las normales, estas son iguales para cada
vértice que conforma esa cara, debido a que se deshabilita la luz al trazado de estas líneas
aparecen a través del cubo aunque este sigue siendo sólido. En la figura 3-8 se muestra el
trazado de las normales.
44
3.4.3 CARGA DE TEXTURAS
La última parte en el proceso de carga que se describirá es el texturizado. La textura de un objeto 3D no forma parte de la descripción geométrica el objeto, análogamente a una caja de regalos se puede describir como un forro o envoltura que envuelve a la geometría, la envoltura puede ser unidimensional (muy raramente utilizado) o bidimensional (cualquier imagen de formato BMP, JPEG, etc.).
Un programa modelador de 3D puede generar archivos que exporten la geometría junto a la textura asociada, formatos .OBJ, .DXF, .X entre otros soportan la característica. Es conveniente utilizar el formatos que hayan alcanzado popularidad comercial .MD2 de Quake o .3DS de 3DstudioMax son ejemplos de ellos, sin embargo la popularidad no es proporcional a facilidad de "parsear" estos archivos, por ello para esta primera etapa de desarrollo se propone un formato muy simple de “parsear” que ahorre tiempo de desarrollo y es un formato conocido como .OREJ propuesto por la Escuela Superior de Informática de Ciudad Real y la Universidad de Castilla La Mancha.
Para la implementación del formato es necesario crear un "script" PHYTÓN que es directamente soportado por el programa BLENDER, pequeñas modificaciones fueron necesarias al "script" v0.31b, a continuación se muestra el código:
45
Figura 3-8
Normales del cubo simple
SCRIPT OREJ 1/2
PATH= "c:/" #ruta donde se coloca es archivo de salida .orj
object = Object.GetSelected() # Lista de Objetos de que forman parte de la escena
objname = "montana"
meshname = object[0].data.name
mesh = NMesh.GetRaw(meshname)
filename = PATH + objname + ".orj"
file = open(filename, "w")
std = sys.stdout # Asociamos stdout al fichero .orj
sys.stdout = file
print "OREj"
print len(mesh.verts)
print len(mesh.faces)
# Escribimos toda la lista de vértices (v x y z)
for vertex in mesh.verts:
x, y, z = vertex.co
print "v %f %f %f" %(x, y, z)
# Escribimos toda la lista de caras (f v1 v2 v3 ...)
for face in mesh.faces:
print "3v",
#Se elimina el reverse para poder obtener
#los vértices en orden correcto
#face.v.reverse()
for vertex in face.v:
print vertex.index,
...
46
SCRIPT OREJ 2/2
...# Lista de parametros uv de cada cara (t u1 v1 u2 v2...)
for face in mesh.faces:
nvertex = 0
#Se elimina el reverse para poder obtener
#los vértices en orden correcto
#face.v.reverse()
print "t",
for vertex in face.v:
print face.uv[nvertex][0], face.uv[nvertex][1],
nvertex = nvertex+1
sys.stdout = std
file.close()
print "Fichero salvado:", filename
47
El archivo .ORJ del cubo simple de la sección anterior con textura tiene el siguiente formato:
OREj
8
12
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 0.999999 1.000000
v 0.999999 -1.000001 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
3v 4 0 3
3v 4 3 7
3v 2 6 7
3v 2 7 3
3v 1 5 2
3v 5 6 2
3v 0 4 1
3v 4 5 1
3v 4 7 5
3v 7 6 5
3v 0 1 2
3v 0 2 3
t 0.0247408747673 0.0209262371063 0.0247411727905 0.0209262371063 0.975259065628 0.0209259986877
t 0.0247408747673 0.0209262371063 0.975259065628 0.0209259986877 0.975259184837 0.0209262371063
t 0.975259184837 0.971444129944 0.975259184837 0.971444129944 0.975259184837 0.0209262371063
t 0.975259184837 0.971444129944 0.975259184837 0.0209262371063 0.975259065628 0.0209259986877
t 0.0247411727905 0.971444249153 0.0247411727905 0.971444487572 0.975259184837 0.971444129944
t 0.0247411727905 0.971444487572 0.975259184837 0.971444129944 0.975259184837 0.971444129944
t 0.0247411727905 0.0209262371063 0.0247408747673 0.0209262371063 0.0247411727905 0.971444249153
De las tres secciones mencionadas en el formato .OBJ (wavefront) se conservan las dos primeras, en el lugar de luces y materiales se describe la textura. Cada bloque de información significa vértices, caras (siempre formadas por 3 vértices) y texturas (dos coordenadas por cada vértice) respectivamente. En este ejemplo utilizaremos el formato BMP para la textura, el menos óptimo en términos de compresión y más simple de decodificar. Por motivos de optimización la imagen BMP deberá ser de tamaño de múltiplos de 2.
48
Cargar este archivo hacia OpenGL significa parsear vértices, caras y coordenadas de textura. Para simplificar la lectura de la textura bidimensional (imagen .BMP) se utiliza la librería GLAUX.H.
LECTURA DE VÉRTICES Y CARAS
std:: string basura;
int num_vértices, num_caras, lado1, lado2, lado3;
float x1,y1,z1,x2,y2,x3,y3;
archivoVertices >> basura; // magic word
archivoVertices >> num_vértices; // lee numero de vértices
archivoVertices >> num_caras; //lee numero de caras
for(int i=0; i<num_vertices; i++)
{
archivoVertices >> basura;
archivoVertices >> x1 >> y1 >> z1; // lee coordenadas
Vertice *v1 = new Vertice(x1,y1,z1);
lista.push_back(v1); // guarda cordenadas en la lista de vértices
}
for(int i=0;i<num_caras;i++)
{
archivoVertices >> basura;//se esperan siempre tres
archivoVertices >> lado1 >> lado2 >> lado3;
Cara *l1 = new Cara(lado1,lado2,lado3);
listaLados.push_back(l1);
}
if(!archivoVertices.eof())
{
for(int i=0;i<num_caras;i++)
{
archivoVertices >> basura;
archivoVertices >> x1 >> y1 >> x2 >> y2 >> x3 >>y3;
Textura *t1 = new Textura(x1,y1);
Textura *t2 = new Textura(x2,y2);
Textura *t3 = new Textura(x3,y3);
listaText.push_back(t1);
listaText.push_back(t2);
listaText.push_back(t3);
}
}
49
Mapeo de las coordenadas de textura sobre el modelo:
glNormal3f(normal.dameX(),normal.dameY(),normal.dameZ());
glTexCoord2f(listaText.at(i*3)->dameX(),listaText.at(i*3)->dameY());
glVertex3f( v0->dameX(), v0->dameY(), v0->dameZ());
Alternativamente se especifica la normal para la iluminación de la escena, el orden de la normal y la coordenada de textura no importa, pero si deben preceder a la coordenada del vértice.
Este capítulo permite concluir que la elección del API Open GL es conveniente por su simpleza de utilización, es una librería muy bien diseñada con un grado de optimización altísimo pues puede soportar la carga de casi cualquier objeto 3D. Para el aprendizaje de Open GL fue necesario utilizar pequeños programas estructurados, el cambio de estos programas hacia un lenguaje OO es inmediato gracias a la estabilidad del API. De la misma forma GLUT mostró estar optimamente diseñado para soportar nativamente un lenguaje estructurado o OO lo cual permite sacar provecho de su uso y ahorrar tiempo de desarrollo.
A partir del conocimiento del formato WAVEFRONT fue fácilmente creado el “script” a la medida OREJ, sin embargo muchas limitaciones son rápidamente previstas al continuar utilizando una metodología tan informal para la creación del “script” (creado solo con el criterio de simplicidad), para demostrarlo se menciona que existen muy distintas técnicas de modelado 3D en las paqueterías encargadas de esta tarea, por lo que si se cambia una técnica o se aumentan características a la actualmente utilizada es muy probable que sea costoso el tiempo de adaptación del “script”, por este motivo en la práctica es más común utilizar formatos de descripción geométrica populares que si contemplan las distintas técnicas de modelado. Es conveniente conocer las técnicas de lectura de archivos de descripción geométrica, pues en la elaboración de un motor gráfico es indispensable contar con un modulo que prevé esta tarea y sea lo más flexible posible.
La parte algorítmica más complicada requerida para el despliegue de modelos 3D es la parte de texturas. Aún sin considerar que existen técnicas de despliegue de texturas más elaboradas y muy necesarias de implementar (como los “mip maps8”) o despliegue de sombras suaves que requieren de técnicas algorítmicas más sofisticadas y que no fueron implementadas en este proyecto.
Se logró completar la tareas de depuración y despliegue de manera optima tal y como se tenia planeado, quedando tareas de mayor complejidad como las mencionadas en el párrafo anterior para futuras modificaciones.
8 Técnica que se encarga de cargar una misma textura con distintas resoluciones dependiendo la distancia de vista con respecto al despliegue
50
4 ANÁLISIS Y DISEÑO DEL SISTEMA
Tal y como se menciono al final del capítulo 2, en este capitulo es posible mezclar dos aspectos en el proceso de desarrollo del juego; la tarea de alto nivel de abstracción (el diseño del juego) y la de bajo nivel (el uso de imágenes 3D). Con ambos procesos completados es posible definir características más específicas de la implementación del juego utilizando criterios de programación como es el caso del análisis y diseño de sistemas.
En este capítulo se utilizan las herramientas: diseño del juego, despliegue gráfico y el análisis y diseño del sistema. Estas tres herramientas son utilizadas para crear un primer prototipo del juego, no se pretende implementar todos los casos de uso pero si tener un grado de visualización funcional y encontrar las analogías entre un software convencional y un juego que permitan acelerar el proceso de desarrollo.
El capítulo inicia realizando la obtención de requerimientos del sistema a partir del documento de diseño, posteriormente se analizan los requerimientos utilizando diagramas UML9 y finalmente se implementa el juego a partir de este documento. A diferencia del capítulo 2, donde el diseñador del juego propone un cierto proceso de desarrollo en este capítulo se intentará seguir otro proceso de desarrollo desde el punto de vista de los programadores (basados en la propuesta del diseñador del juego), al final de este capitulo se verificarán las analogías y diferencias entra ambas visiones.
4.1 OBTENCIÓN DE REQUERIMIENTOS
COMPORTAMIENTOS PRINCIPALES
Administrar partidas (iniciar, pausar, reanudar, terminar, guardar, configurar)
Administrar etiquetas (estado de la etiquetas)
Administrar armas y aditamentos (destructor, anti patógeno, proyectiles)
Generar GUI (visor, resto, contaminación, lista, errores, puntuación, pausa, entre otros)
Administrar de IA (enemigos)
Controlar materia (manipulación de materia, aplicación de etiquetas, patrón de etiquetado para cada materia)
9 Unified Modeler Lenguage
51
ACTORES
● Jugador: se encarga de manipular y controlar todos los elementos jugables de la interfaz principal, así como seleccionar las opciones en los menús de la interfaz principal ó interfaz inicial
● Tiempo: se encarga de temporizar a los agentes patógenos, los niveles de contaminación, el visor
● Comportamientos autónomos del sistema (CAS): se encarga de controlar el comportamiento de los enemigos del jugador, así como respuestas automáticas a determinadas estadísticas del sistema
CASOS DE USO PRINCIPALES
NOMBRE DE CASO DE
USO
PRIORIDAD NUMERO DESCRIPCIÓN
Administrar partidas B 1 Este caso de uso permite mostrar las distintasopciones que AMORPHE BIOS provee en susdistintas interfases: ventana inicial, ventana deconfiguración y ventana de interfaz principal
Administrar etiquetas E 2 Este caso de uso se encarga de generar lasetiquetas que serán colocadas sobre la materia,verificar que estén disponibles para el usuariocuando todavía resten e informar al sistema si
han sido utilizadas o noAdministrar armas y
aditamentosA 3 Este caso de uso se encarga de controlar los
movimientos y ataques de las armas destructor yanti-patogeno
Generar GUI E 4 Este caso de uso se encarga de informar aljugador sobre las reacciones de AMORPHE
BIOS frente a sus acciones, como lo son: errores,contaminación, lista, resto, visor y puntuación.
Controla las distintas opciones para lasinterfases del sistema
Administrar IA A 5 Este caso de uso permite controlar elcomportamiento autónomo de los enemigos delsistema en función de las acciones del jugador,
el tiempo y GUI, así como controlar elcomportamiento del recorrido del visor
Controlar materia E 6Este caso de uso se encarga de mostrar enpantalla los elementos gráficos según las
ordenes del jugador, así como establecer elpatrón de recorrido del visor a través de su
superficie
52
EXPANSIÓN DE CASOS DE USO
ADMINISTRAR PARTIDAS
NOMBRE DE CASO DE USO IDENTIFICADOR DE CASOS DE USO
DESCRIPCIÓN
Iniciar nueva partida B1a Este caso de uso permite iniciar una nueva partida
Cargar partida B1b Este caso de uso permite cargar una partida previamente almacenada
Configurar opciones B1c Este caso de uso permite configurar lasopciones de una partida. (Niveles de
dificultad, etc.)Poner en modo pausa A1d Este caso de uso permite cambiar el
estado de una partida a modo pausaReanudar partida B1e Este caso de uso permite abandonar el
modo pausa y reanudar una partidaGuardar partida B1f Este caso de uso permite almacenar una
partidaTerminar partida B1g Este caso de uso permite finalizar una
partida
ADMINISTRAR ARMAS Y ADITAMENTOS
NOMBRE DE CASO DE USO IDENTIFICADOR DE CASOS DE USO
DESCRIPCIÓN
Controlar destructor A3a Este caso de uso permite controlar elmovimiento del destructor hacia la
derecha y hacia la izquierdaControlar anti-patógeno A3b Este caso de uso permite controlar la
aplicación del anti-patógenoControlar proyectil A3c Este caso de uso permite controlar el
movimiento, dirección y colision de losproyectiles disparados por el destructor
GENERAR GUI
NOMBRE DE CASO DEUSO
IDENTIFICADOR DE CASOS DE USO
DESCRIPCIÓN
Mostrar errores deljugador
E4a Este caso de uso permite informar sobre lasacciones invalidas del jugador al colocar unaetiqueta equivocada en un determinado visor
Mostrar contaminación E4b Este caso de uso permite informar sobre losniveles de contaminación de la materia
Mostrar lista deorganismos
E4c Este caso de uso permite las distintas materiascompletadas a través de los distintos niveles
53
Mostrar puntuación E4d Este caso de uso permite informar sobre lasacciones válidas y exitosas del jugador
Mostrar resto de lasetiquetas
E4e Este caso de uso permite informar sobre lacantidad de etiquetas que faltan para completar
la materiaMostrar fin de juego E4f Este caso de uso permite informar al jugador
cuando el nivel de contaminación es totalMostrar fin de nivel E4g Este caso de uso permite informar al jugador
cuando el nivel de construcción ha sidocompletado
Mostrar emergencia deconstrucción
E4h Este caso de uso permite orientar al jugador ladirección de colocación indicada por el visor en
una región no visible para el jugador
ADMINISTRACIÓN DE INTELIGENCIA ARTIFICIAL
NOMBRE DE CASO DEUSO
IDENTIFICADOR DE CASOS DE USO
DESCRIPCIÓN
Liberar patógenos A5a Este caso de uso permite liberar los agentes
patógenos hacia la materiaControlar patógenos A5b Este caso de uso permite controlar el
comportamiento de los patógenos al contacto
con la superficie de la materia, al ser destruidos
y al introducirse en la materiaControlar residente hostil A5c Este caso de uso permite controlar el
comportamiento de cada jefe de nivel al final de
cada nivelActivar visor A5d Este caso de uso permite controlar el
tiempo deespera del visor para la espera de la
colocaciónde etiquetas asi como su recorrido sobre la
materia
CONTROLAR INTERFAZ PRINCIPAL
NOMBRE DE CASO DEUSO
IDENTIFICADOR DE CASOS DE USO
DESCRIPCIÓN
Movimiento de materia E6a Este caso de uso permite controlar elmovimiento de la materia en un mundo
tridimensionalConstruir con etiquetas E6b Este caso de uso permite controlar la selección
de las distintas etiquetas presentes
54
TABLA DE REQUERIMIENTOS FUNCIONALESNOMBRE DE CASO DE
USOID RF DESCRIPCIÓN
Administración de partidas B1-1 El sistema debe permitir cargar una partida previamente almacenada
B1-2 El sistema debe permitir iniciar una nueva partida
B1-3 El sistema debe permitir la modificación de las opciones configurables del juego, como los niveles de
dificultad, etc.cuando el jugador se encuentra en modo pausa o
cuando esta en la ventana inicial
B1-4 El sistema debe permitir cambiar el estado de una partida a modo de pausa. Una vez iniciada la partida es
posible cambiar a este modo en cualquier momento
B1-5 Cuando el juego se encuentra en modo de pausa, el sistema debe permitir abandonar el modo pausa para
reanudar la partida. Una vez iniciada pausada la partida es posible regresar a la partida
en cualquier momento
B1-6 Cuando el juego se encuentra en modo de pausa, el sistema debe permitir guardar la partida actual
B1-7 Cuando el jugador es derrotado o bien cuando el juego se encuentra en modo de pausa, el sistema debe
permitir terminar una partida
Administrar etiquetas E2-1 Al iniciar un nivel, el sistema debe generar un recorrido aleatorio para el visor sobre campos
preestablecidos en la materia
E2-2 El sistema debe generar una etiqueta en el mismo lugar y del mismo tipo que se colocó en el visor, según el
GUI resto
Controlar destructor A3a-1 El sistema debe detectar el contacto del ataque del residente hostil con el destructor
A3a-2 El sistema debe limitar el movimiento del destructor al espacio ocupado en cada materia
Controlar proyectil A3c-1 El sistema debe destruir a los agentes patógenos y dañar al hostil al contactos con los disparos
Mostrar resto de etiquetas E4e-1 El sistema debe completar un nivel cuando el jugador haya terminado de colocar el total de las etiquetas
E4e-2 El sistema debe incrementar el grado de dificultad al disminuir el resto de etiquetas
55
Liberar patógenos A5a-1 El sistema debe aumentar la liberación de patógenos al disminuir el nivel de resto de etiquetas
A5a-2 El sistema debe aumentar la cantidad depatógenos generado en cada liberación
dependiendo del tiempo que tarde en disminuir su nivel de resto. Mientras mas rápido disminuya el resto
de etiquetas mayor cantidad de patógenos son liberados
Controlar patógenos A5b-1 El sistema debe calcular la distancia de los patógenos al visor para determinar un comportamiento
A5b-2 Si la distancia calculada es pequeña, el sistema debe realizar el movimiento de los patógenos al visor
A5b-3 Si la distancia calculada es grande, el sistema debe realizar la introducción indirecta de la patógenos hacia
la materia
A5b-4 Si la distancia calculada es cero, el sistema debe realizar la introducción directa de los patógenos a la
materia
A5b-5 Si los patógenos no tienen distancia por calcular, el sistema debe iniciar el comportamiento de
contaminación de la materia
Controlar residente hostil A5c-1 Al contacto con la materia el sistema debe controlar a el residente hostil, según el nivel de dificultad
seleccionado por el jugador
A5c-2 El sistema deberá soportar las reacciones del destructor a los ataques del residente hostil
Activar visor A5d-1 El sistema debe permitir activar el visor para iniciar una recorrido aleatorio sobre la materia
A5cd-2 El sistema debe disminuir el tiempo de espera del visor al paso de tiempo del nivel
A5cd-3 El sistema debe ofrecer una búsqueda exhaustiva el visor con distribución homogénea para las distintos
tipos de etiquetas soportados
56
TABLA DE REQUERIMIENTOS NO FUCNIONALES
NOMBRE DE CASO DEUSO
ID RF DESCRIPCIÓN
Administración de partidas B1-101 Los tiempos de espera entre las distintasopciones de las ventanas deberán ser lo más
cortos posibles para envolver en mayor medida el
jugador
B1-102 Los menús de las distintas ventanas deberáncontener la misma estética del enfoque del juegosin perder el estándar del control de ventanas conel fin de obtener interfases cómodas e intuitivas
Administrar etiquetas E2-101 Esta generación deberá obtenerse en un tiempoque sea lo mas corto posible para iniciar un nivel
inmediatamente
E2-102 La estética de las etiquetas variará según el tipode materia que se este construyendo para
diversificar el juego cada vez que inicie unamisma materia
Controlar destructor A3a-101 Se permitirá la manipulación del destructor(también se incluye al antipatógeno) aún sin lapresencia de patógenos para mayor libertad de
juego
A3a-102 La respuesta del destructor deberá ser lo másrápida y precisa posible para ofrecer ventaja al
jugador
Generar GUI E4-101 La actualización de los valores de todas las GUI’s
deberá ser en el tiempo más corto posible paraayudar a la inmersión el jugador y evitar su
frustración
Liberar patógenos A5a-101 Se deberá verificar la cantidad y calidad visual de los agentes patógenos para alcanzar las
cantidades más grandes de patógenos posibles ala vez, sin que afecte el rendimiento del juego
Controlar materia E6-101 La respuesta de la materia y las etiquetas ante lasacciones del jugador deberán ser los más rápidasposibles para optimizar la jugabilidad y sumergir
al jugador en el mundo
57
CASOS DE USO PRINCIPALES
58
System
B1: Administrar partidas
E2: Administrar etiquetas
A3: Administrar armas y aditamentos
E4: Generar GUI
A5: Administrar IA
E6: Controlar materia
Tiempo
Jugador
CAS
CASOS DE USO REFINADOS
59
System
E2: Administrar etiquetas
Tiempo
Jugador
CAS
E4a: Mostrar errores del jugador
E4b: Mostrar contaminacion
E4c: Mostrar lista de organismos
E4d: Mostrar puntuacion
E4e: Mostrar resto de las etiquetas
A3a: Controlar destructor
A3b: Controlar antipatogeno
A5a: Liberar patógenos
A5b: Controlar patógenos
E6a: Movimiento materia
E6b: Constriur con etiquetas<<extend>>
A5d: Activar visor
Controlar patogenos superficie
Controlar patogenos interior
<<extend>>
E4f: Mostrar fin de juego
<<extend>>
B1a: Iniciar nueva partida
B1b: Cargar partida
B1c: Configurar opciones
B1d: Activar pausa
B1e: Reanudar partida
B1f: Guardar partida
B1g: Terminar partida
A5c: Controlar residente hostil
E4g: Mostrar fin de nivel
<<extend>>
E4h: Mostrar emergencia de construccion
<<include>>
<<extend>>
A3c: Controlar proyectil
4.2 ANÁLISIS DE REQUERIMIENTOS
OBTENCIÓN DE LAS ABSTRACCIONES CLAVE
CANDIDATOS A ABSTRACCIÓN RAZÓN PARA ELIMINARLO NOMBRE DE LA ABSTRACCIÓNJuego de video Una sola instancia X
Jugadores No almacenan información XTiempo Representa un sistema externo X
CAS Representa un sistema externo XJuego de disparos Una sola instancia X
Rompecabezas tridimensional Una sola instancia XMateria ------ Materia
Destructor ------- DestructorEtiquetas -------- Etiquetas
Grado de dificultad Propiedad de otro candidato (Nivel) XVisor ---------- Visor
Agentes patógenos --------- PatógenosAntipatogeno -------- Antipatogeno
Contaminación Propiedad de otro candidato (Materia) XNivel ------------ Nivel
Errores Subtipo de otro candidato (GUI) XPuntuación de construcción Subtipo de otro candidato (GUI) X
Resto de etiquetas Una sola instancia XLista de materias completadas Subtipo de otro candidato (GUI) X
Residente hostil -------- HostilElementos tridimensionales Propiedad de otro candidato (materia) X
GUI ------- GuiPartida ------ Partida
AmorpheBios ------ AmorpheBiosProyectil ------ Proyectil
DIAGRAMAS CRC
Materiacompletadamodelo3D
contaminaciónconstriurEtiqueta()
moverMateria()completarMateria()actualizarMateria()
EtiquetasPatógenos
AntipatogenoVisor
Partida
Patógenoestado
nivelResistenciagenerarPatogeno()ataquePatogeno()activarPatogeno()
MateriaProyectilPartida
Gui
60
Etiquetatipo
estadoEtiquetaaplicarEtiqueta()cambiarEstado()renovarEtiqueta()
MateriaVisorGui
Partida
Antipatogenodosisestado
aplicarDosis()
MateriaGui
Partida
Niveldificultad
modificarNivel()iniciarNivel()
Partida
AmorpheBiosiniciar()
actualizar()terminar()
Partida
Proyectilcapacidad
gcrearProyectil()controlarProyectill()
PatógenosHostilGui
Partidaestadonombre
numNivelpuntuación
cambiarConfiguracion()seleccionarNivel()
cargar ()pausarPartida()
reanudarPartida()terminarPartida()
puntuacionPartida()finalizarNivel()iniciarPartida()guardarPartida()
NivelHostil
PatogenoMateria
AntipatogenoVisor
EtiquetasGui
DestructorAmorpheBios
HostilnivelResistencia
nivelVidagenerarHostil()ataqueHostil()
ProyectilMateriaPartida
Gui
GuiestadoPuntuacion
estadoCosntruccionestadoRestoestadoLista
generarError()generarPuntuacion()
actualizarContaminacion()actualizarResto()actualizarLista()
MateriaEtiquetasProyectilPartida
PatógenoHostil
VisorRetardoforma
activarVisro()
MateriaNivel
EtiquetasPartida
61
MODELO DE DOMINIO DEL PROBLEMA
62
Materia<<entity>>
-completada-modelo3D-contaminacion
+moverMateria()+constriurEtiqueta()+completarMateria()+actualizarMateria()+damePosicion()
Etiquetas<<entity>>
-tipo-estadoEtiqueta
+aplicarEtiqueta()+renovarEtiquetas()+cambiarEstado()+actualizarEtiquetas()
Destructor<<entity>>
-estadoDestructor-listaProyectiles
+controlarDestructor()+dispararDestructor()+degradarDestructor()+creaProyectil()
Patogeno<<entity>>
-estado
+activarIAPatogena()+ataquePatogeno()+eliminar()+activarContaminacion()+modificarNivel()
Antipatogeno<<entity>>
-dosis
+aplicarDosis()
Nivel<<entity>>
-difilcultadEnemigos-dificultadEtiquetas-velocidadJuego-cantidadPatogenos
+graduarNivel()+cambiarNivel()
Hostil<<entity>>
-nivelResistencia-nivelVida
+generarHostil()+ataqueHostil()
Gui<<entity>>
+mostrarError()+mostrarPuntuacion()+mostrarEmergencia()+mostrarUrgencia()+mostrarContaminacion()+mostrarLista()+mostrarResto()+menuPausa()+terminarPartida()+finNivel()
Visor<<entity>>
-retardoActivacion-geometriaActivada
+activarVisor()+iniciarRecorrido()+interrumpirRecorrido()+dameGeometria()
AmorpheBios<<entity>>
-estado-numeroNivel-nombre-materiasCompletadas-puntuacionTotal-dosisAntipatogeno-estadoContaminacion-estadoResto
+cargar()+puntuacion()+guardar()+configurar()+crearNivel()+pausar()+reanudar()+iniciar()+terminar()+completarNivel()+actualizarPuntuacion()+actualizarAntipatogeno()+actualizarContaminacion()+actualizarResto()+actualizarLista()
Tiene un >>
11
<<subscribe>>
1
1
<<Ataca1
1
<< Ataca
1 1Cura>>
11
<< Actualiza
1
1
<<Usa 10..*
<<Actualiza
1
1..*
Ataca>> 0..*
1
<<Actualiza
1 1
Tiene>>1
1
<<Crea
1
1
Crea>>
1
1
Crea>>
11
<<Crea
*
1
<<Ataca
1
1..*
Usa>>
1
0..*
Usa >>
0..1
1
<< Actualiza1 1
<<Actualiza
1
1
<<Actualiza
1
1
Contiene>>
1
1
Proyectil<<entity>>
+potencia
+controlarProyectil()+detectarColision()
<<Crea
0..*
1
Ataca>>
1
1
DIAGRAMA DE NAVEGACIÓN
DIAGRAMAS DE SECUENCIA
MOSTRAR CONTAMINACIÓN
63
: Ventana de interfaz principal<<boundary>>
: Control GUI<<control>>
: Gui<<entity>>
: CAS : Tiempo : CAS
: Control partida<<control>>
: Ventana de fin de partida<<boundary>>
: Control partida<<control>>
: AmorpheBios<<entity>>
: Ventana de GUI<<boundary>>
1 : genera contaminacion
2 : actualizarContaminacion()
3 : mostrarFinPartida()
4 : mostrarContaminacion()
5 : despliega()
Ventana inicial Ventana de interfaz principal
Ventana de GUI
Ventana de configuracion
Ventana de fin de partida
Ventana de nivel completado
Ventana de materia
[ iniciar ]
[ opciones ]
[ construir/mover ]
Ventana de pausa
[ pausa ] [ reanudar ]
Ventana de cargar
[ cargar ] [ aceptar ] [ errores/puntuacion/informacion ]
[ terminar ]
[ opciones ]
[ cancelar/guardar ]
[ construir ]
[ contaminacion ]
[ terminar ]
Ventana de guardar
[ guardar ]
[ sobreescribir ]
[ cancelar ]
[ reiniciar ]
[ cancelar ]
[ cancelar/guardar ]
MOSTRAR PUNTUACIÓN
ACTIVAR COMPORTAMIENTO DE PATÓGENOS EN LA SUPERFICIE DE LA MATERIA
64
: CAS
: Ventana de interfaz principal<<boundary>> <<control>>
: Materia<<entity>>
: Gui<<entity>>
: Patogeno<<entity>>
: Control IA<<control>>
: Control enemigos<<control>>
: Control materia<<control>>
1 : activarIAPatogeno
2 : controlarPatogeno()
3 : ataquePatogeno()
4 : verificaColisionMateria()
5 : damePosicion()
6 : iniciaComportamiento()
7 : posicionColisoion()
8 : actualizarVentana()
: Jugador
: Ventana de interfaz principal<<boundary>>
: Control visor<<control>>
: Visor<<entity>>
: Control GUI<<control>>
: Gui<<entity>>
: Control partida<<control>>
: AmorpheBios<<entity>>
: Ventana de GUI<<boundary>>
1 : constriurcon etiqueta
2 : verificarEtiqueta()
3 : dameGeometria()
4 : actualizarPuntuacion()
5 : actualizarPuntuacion()
6 : mostrarPuntuacion()
CONSTRUIR ETIQUETAS
En la figura 4-1 podemos observar el primer prototipo de AmorpheBios implementando algunos de los casos de uso descritos en este capítulo:
65
: Jugador
: Ventana de interfaz principal<<boundary>> <<control>>
: Gui<<entity>>
: Materia<<entity>>
: Etiquetas<<entity>>
: Control materia<<control>>
: Control visor<<control>>
: Visor<<entity>>
: Control de etiquetas<<control>>
: Control GUI<<control>>
: Control partida<<control>>
: AmorpheBios<<entity>>
: Ventana de GUI<<boundary>>
1 : constriurEtiqueta
2 : verificarEtiqueta()
3 : dameGeometria()
4 : actualizarMateria()
5 : actualizarEtiquetas()
6 : aplicarEtiqueta()<<destroy>>
7 : actualizarPuntuacion()
8 : actualizarResto()
9 : actualizarPuntuacion()
10 : actualizarResto()
11 : actualizarMateria()
12 : mostrarPuntuacion()
Figura 4-1
AmorpheBios con la librería GLUT
Adicionalmente en la figura 4-2, se puede observar información visual adicional, ejemplo de algunas de las características no funcionales que no son contempladas en el análisis y diseño del sistema pero indispensables para depurar la aplicación.
Concluyo que al momento de implementar un juego el diagrama UML de mayor utilidad es el diagramas de robustez (o de secuencia en su vista temporal), estos diagramas ayudaron a resolver los problemas más críticos en la comprensión de la aplicación como son la interacción de los actores con objetos de control, la relación entre los distintos objetos de control y el uso específico de cada objeto de entidad, utilizar el principio de desacoplamiento que será útil en el capítulo 5 y definir un mayor número de funciones que no son evidentes a los ojos del programador.
El proceso de desarrollo del juego desde el punto de vista de análisis y diseño llevo a construir un prototipo idéntico en etapas al propuesto por el diseñador del juego, los casos de uso principales son exactamente las primeras etapas del diagrama de flujo del prototipo. Esto indica que en el desarrollo de software (incluyendo los juegos), se utilizan ideas intuitivas compartidos por lo programadores.
Algunas de las limitaciones más importantes en la implementación del juego en esta etapa son el diseño artístico, nuevos descubrimientos y ajustes en la jugabilidad, el modelado 3D y el tiempo estipulado. Debido a que en un juego la jugabilidad es la principal preocupación funcional, al momento de implementar prototipos utilizando la documentación se hacen visibles las deficiencias en el diseño del juego, pues es imposible predecir si una característica será o no entretenida y jugable si no es que se tenga un referente implementado, este proceso de corrección fue muy común lo cual complicaba la correcta documentación.
Con este primer prototipo muchas características no funcionales (despliegue de GUI's, audio, información numérica entre otras) son requeridas, sin embargo continuar utilizando las mismas herramientas para alcanzar ese grado de funcionalidad requeriría un tiempo de desarrollo grande, por este motivo en el capítulo 5 se analizan otras herramientas que permitan acelerar el desarrollo. Adicionalmente se comprobará el principio de desacoplamiento, utilizando en el prototipo la introducción de nuevas herramientas.
66
Figura 4-2
AmorpheBios con información visual: normales
5 LIBRERÍAS PARA DESARROLLO DE
SISTEMAS MULTIMEDIA
Cuando se trata de desarrollo de juegos es importante que el diseñador del juego tenga la menor cantidad posible de limites tecnológicos, límites generalmente establecidos por tareas de bajo nivel (optimización, plataforma, cuadros por segundo, formatos de modelos 3D soportados, etc.) sin embargo el grado de complejidad para implementar la mayoría de los juegos exigen la utilización de herramientas más poderosas que permitan tener una mayor preocupación sobre la jugabilidad y aspectos funcionales del juego, herramientas adecuadas podrán abstraer mayor número de tareas de bajo nivel. Una de las herramientas que auxilian en la construcción de juegos son las conocidas como librerías multimedia, aspectos no funcionales como la carga de “sprites”, animación por tiempo, cuantificar cuadros por segundo, una mayor interacción con aplicaciones y audio son algunos de las tareas que son soportadas por dichas librerías.
En este capitulo se hace una breve investigación sobre las librerías multimedia de distribución libre para ser utilizadas en el juego. Con la librería elegida se mostrarán algunos efectos visuales y pequeños segmentos de programas que son una guía para “montar” la librería sobre el prototipo del capítulo 4, adicionalmente se crean algunos casos de uso para mostrar la utilidad del uso del librería.
67
Figura 5-1
Proceso de implementación de la librería multimedia
5.1 DESCRIPCIÓN DE LIBRERÍAS MULTIMEDIA
Una gran variedad de librerías “open source” para desarrollo de software son actualmente disponibles vía el INTERNET. Algunas de ellas nacieron con la necesidad de implementar aplicaciones como juegos, modeladores 3D o manejadores de gráficas 3D, ejemplos de estos tipos son Allegro, GLFW, FLTK o SDL, entre otras.
El propósito de las librerías desde el punto de vista del programador, es proporcionarle herramientas que faciliten el nivel de abstracción al desarrollo de software. Las librerías como Allegro y SDL tienen una muy reconocida fama en el campo del desarrollo de juegos desde hace algunos años, por ello se describen sus principales características.
● Allegro es una librería portable principalmente enfocada a videojuegos y programación multimedia, originalmente escrita por Shawn Hargreaves. De acuerdo con la Compañía de música Oxford, Allegro proviene del italiano que significa “rápido, animado, brillante”. La primera versión de esta librería proviene del año 1995, cuando el mercado de los juegos estaba plagado de “sprites” y aplicaciones 2D. A pesar de los cambios tecnológicos y la aparición de las aplicaciones 3D, Allegro sigue desarrollándose, quizá los motivos didácticos e incluso aplicaciones serias en 2D justifican este hecho. Para no quedarse atrás en el mundo 3D, Allegro extendió su dominio hacia este tipo de aplicaciones al desarrollarse la librería AllegroGL (una librería que mezcla el render OpenGL con rutinas de Allegro, “add-on” de Allegro), aunque mucho se cuestiona la eficacia y estabilidad de este híbrido su permanencia y éxito entre los desarrolladores de juegos se ha consolidado. Una de las aplicaciones actualmente en desarrollo con estas librerías es Moon3D Engine por el estudiante Steffen Hein.
● SDL (Simple Direct Layer) es una librería portable multimedia diseñada para proveer accesos de bajo nivel hacia audio, teclado, ratón," joystick", hardware 3D a través de OpenGL y video 2D mediante “framebuffer”. Es también utilizado para reproducir video MPEG, emuladores y algunos juegos populares. El autor de esta librería es Sam Lantinga, el inicio de desarrollo de esta librería proviene del año 1997, (algunos años de desarrollo después que Allegro).El propósito original de su creador nos revela el porque de la diversidad de aplicaciones hacia las que esta dirigida la librería. Años más tarde y con la filosofía de diseño del creador permite la mezcla de la API OpenGL con SDL sin ninguna modificación, característica que ofrece una gran ventaja sobre Allegro, según mi opinión.
Entre otros beneficios de este tipo de librerías, es el acceso a recursos de bajo nivel y al mismo tiempo acceso a herramientas de mayor abstracción, características que ayudan al programador en la construcción de aplicaciones de gran estabilidad y solidez. Seguramente el inicio de la creación de un 3D Engine tiene sus inicios desarrollando y/o practicando en alguna de estas librerías, no es de extrañar que al continuar un desarrollo de un juego hasta concluirlo a través de el uso de alguna de estas librerías u otras más primitivas terminaría convirtiéndose en un Engine de una muy cuestionable calidad. La cantidad de trabajo y
68
tiempo para alcanzar la estabilidad y refinamiento de un buen Engine es mucha, la pretensión de utilizar alguna de las librerías mencionadas en AmorpheBios no tiene como propósito la creación de un 3D Engine.
El beneficio de tener una referencia bibliográfica (Focus SDL de Ernest Pazera) además de los tutoriales en INTERNET y la capacidad de albergar instrucciones de OpenGL sin ninguna modificación son algunos de los motivos que me ayudaron a decidir migrar AMORHPE BIOS actualmente implementado con GLUT hacia SDL.
5.2 SDL
Como ya se menciono SDL es un API multiplataforma de distribución libre, encargada de realizar tareas comúnmente asignadas a DirectX. Para el uso de esta librería basta con obtener SDL.dll que es generalmente incluida como parte de las actualizaciones de compiladores de distribución libre. Puede soportar nativamente C/C++ y OpenGL. Al igual que DirectX con sus subsistemas (DirectDraw, Direct3D, DirectSound, DirectMusic, DirectInput y DirectPlay) SDL también contiene subsistemas que se encargan del audio, video y eventos.
No todas las características que contiene DirectX son soportadas por SDL, pero pueden ser soportadas nativamente, una de ellas es OpenGL que tiene su análogo con Direct3D, SDL_net análogo a DirectPlay y SDL_Mixer análogo a DirectMusic.
Para comprender que hace cada uno de los subsistemas que conforman SDL se realiza una pequeña descripción a cada uno de ellos:
Video: encapsula el despliegue de video, controla superficies (rectángulos, colores, paletas y sobré flujos). Soporta llaves de color, transparencias y codificación. En SDL todo despliegue en video es una superficie, entendiendo literalmente esta definición
69
Figura 5-2
Los subsistemas de SDL y el API DirectX de Microsoft
siempre se requiere de una superficie de dibujo principal que es la pantalla en si, dentro de ella se realizan todos los efectos mencionados Manejador de eventos : encapsula el manejo de eventos, es quizá el subsistema más importante debido a que es por esto que la interactividad del jugador se realiza, es equivalente con el “Message Pump” de Win32 Joystick: encapsula el uso de joysticks, independiente de la entrada estándar
Audio: encapsula el trabajo con el hardware de audio
CD-ROM: reproducción de audio vía CD-ROM en tiempo real
Hilos: funciones auxiliares de multihilos, mutexes, semáforos y variables de condición
Timers: eventos y temporización
Con la especificación de los subsistemas el grado de control, optimización y refinamiento que se logra con SDL es altísimo, la desventaja es la gran cantidad de instrucciones de bajo nivel que deben comprenderse para un desarrollo completamente estable.
5.2.1 INICIALIZACIÓN DE SDL
Se requieren como mínimo 6 funciones:
Funciones DescripciónSDL_INIT inicializa 1 o más
subsistemas de SDLSDL_Init_Subsystem inicializa subsistemas
particulares de SDL (solose uso después deSDL_Init)
SDL_Quit termina todos lossubsistemas de SDL
SDL_Quit_Subsystem
termina el subsistemaespecificado
SDL_Was_INIT verifica que subsistemasestán inicializados
SDL_GetError reenvía el último errorinterno reportado por SDL
Tabla 5-1
Funciones principales de SDL
70
Esta ultima función es muy utilizado por los programadores habituados con SDL y es utilizada para generar una bitácora de errores y éxitos generados al ejecutar la aplicación SDL, es muy útil para “debbuggin” y para identificar características específicas del hardware con el que se cuenta.
5.2.2 EL PROBLEMA DE LA PORTABILIDAD
El uso de algunas de las librerías portables, incluyendo SDL implican el reconocimiento de tipos de datos primitivos como int, float, short, char, etc. sin que su variación en bytes perjudique el desempeño o significado de la instrucción. en el caso de SDL ¿cómo se logra esta estabilidad?, la respuesta es: de la forma más sencilla posible.
En vez de utilizar directamente los tipos de datos primitivos para aplicarlos a instrucciones de SDL se utiliza una convención, por ejemplo Uint32 representa un Unsigned int de 32 bits, es quizá el tipo más utilizado en las instrucciones de SDL porque este tipo de dato representa BANDERAS. Este tipo de convención facilita la programación por estar escrita con mnemónicos y específica de manera exacta el tamaño del tipo de dato; así un tipo puede ser S (Signed) o U (Unsigned) seguido de su nombre de tipo primitivo y la cantidad de bits para representarlo 8, 16, 32 o 64.
Con dos instrucciones se puede notar la necesidad de independencia de plataforma según el contexto de la instrucción.
int SDL_Init(Uint32 flags);
int SDL_Initsubsystem(Uint32 flags);
El parámetro de la función debe ser independiente de la plataforma, sin embargo el resultado de esta tarea puede ser 0 si es correcto o -1 si es incorrecto, con la información de estos números hace innecesario el uso estricto de la variable primitiva exacta (un 0 y un -1 en 8, 16, 32 o 64 bits tienen el mismo significado).
El nombre de la variable flags se justifica al mostrar los parámetros requeridos:
SDL_INIT_TIMER
SDL_INIT_AUDIO
SDL_INIT_VIDEO
SDL_INIT_CDROM
SDL_INIT_JOYSTICK
SDL_INIT_EVERYTHING
71
Los parámetros mencionados siguen una relación uno a uno con los subsistemas soportados por SDL, sin embargo el subsistema Event_Handling y Threads no se mencionan, esto es debido a que ambos subsistemas son automáticamente dados de alta al inicializar el VIDEO.
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO);
Inicializa AUDIO, VIDEO, EVENT y THREADS.
#include <fstream.h>
#include <SDL.h>
#include <ostream.h>
int main(int argc, char** argv)
{
SDL_Surface* g_pMainSurface=NULL;
SDL_Event g_Event;
const SDL_VideoInfo *info=NULL;
ofstream error("stderr.txt");
ofstream salida("stdout.txt");
if (SDL_Init(SDL_INIT_VIDEO)<0)
{
error<<"Could not initialize SDL!\n"<<SDL_GetError();
error.close();
exit(1);
}
else
{
salida<<"SDL initialized properly!\n";
atexit(SDL_Quit);
}
info=SDL_GetVideoInfo();
//Carga un modo de video y verifica su correcta respuesta
g_pMainSurface = SDL_SetVideoMode(640,480,0,SDL_ANYFORMAT
...
72
...if(!g_pMainSurface)
{
error<<"Could not create main surface!\n"<<SDL_GetError();
exit(1);
} salida<<"\n"<<"Es posible crear superficies por hardware: "<<info->hw_available<<endl;
salida<<"Un manejador de ventanas esta disponible: "<<info->wm_available<<endl;
salida<<"Blits desde hard a hard son acelerados: "<<info->blit_hw<<endl;
salida<<"Blits hard a hard con informacion alfa son acelerados: "<<info->blit_hw_A<<endl;
salida<<"Blits desde soft a hard son acelerados: "<<info->blit_sw<<endl;
salida<<"Blits desde soft a hard con informacion de \"color keys\" son acelerados: "<<info->blit_sw_CC<<endl;
salida<<"Blits desde soft a hard con informacion alfa son acelerados: "<<info->blit_sw_A<<endl;
salida<<"Rellenos de color acelerados: "<<info->blit_fill<<endl;
salida<<"Memoria de video disponible: "<<(int)info->video_mem<<endl<<endl;
salida<<"----------- Formato de pixeles optimo ------------- "<<endl;
salida<<"Bits por pixel: "<<(int)info->vfmt->BitsPerPixel <<endl;
salida<<"Bytes por pixel: "<<(int)info->vfmt->BytesPerPixel <<endl;
while(1)
{
if(SDL_WaitEvent(&g_Event)==0)
{
error<<"Error while waiting for an event!\n"<<SDL_GetError();
exit(1);
}
//check the type of event
if(g_Event.type==SDL_QUIT)
{
salida<<"Quit event has occurred.\n";
break;
}
}
salida.close();
error.close();
return 0;
73
En el programa anterior se muestra una forma clásica de inicialización de SDL para obtener información acerca del hardware sobre el que la librería se ejecuta, en la bitácora siguiente se muestran los resultados para un máquina P4 3.4Ghz, 1GByte de memoria RAM y tarjeta de video NVidia QUADRO NVS 285 con 64Mbytes.
SDL initialized properly!
Es posible crear superficies por hardware: 1
Un manejador de ventanas esta disponible: 1
Blits desde hard a hard son acelerados: 1
Blits hard a hard con informacion alfa son acelerados: 0
Blits desde soft a hard son acelerados: 1
Blits desde soft a hard con informacion de "color keys" son acelerados: 1
Blits desde soft a hard con informacion alfa son acelerados: 0
Rellenos de color acelerados: 1
Memoria de video disponible: 53240
----------- Formato de pixeles optimo -------------
Bits por pixel: 32
Bytes por pixel: 4
Quit event has occurred.
74
5.2.3 SDL VIDEO
Como elemento indispensable para el despliegue de imágenes en 3D o 2D se requiere de la manipulación de este subsistema. Como anteriormente se menciono el despliegue en la pantalla con SDL se realiza mediante el uso de superficies, incluso la superficie de la aplicación misma que es la superficie principal. Dentro de esta superficie principal es posible dibujar cualquier tipo de efectos que SDL provea y muchos otros que el programador implemente, algunos de las funciones más importantes son:
SDL_Rect: específica el dibujo de un rectángulo en coordenadas con pixeles (sup-izq e inf-der) SDL_Color: guarda información de un determinado color en forma independiente a Formatos SDL_Palette: paletas de colores de 8 bits para realizar animaciones de sprites mediante el cambio de colores, técnica ya no muy utilizada pero que tiene un efecto visual único SDL_Pixel_Format: indica el formato de un pixel como su cantidad de bit, bits por canal, modo RGB, paletas entre otros SDL_Surface: abstracción para un bloque de pixeles rectangulares, es indispensable la creación de una de ellas que sirva como pantalla principal SDL_Overlay: permite el despliegue de video .mpg
Ninguna superficie puede dibujarse utilizando rotaciones, en la figura 5-3 se muestra esta restricción:
75
Figura 5-3
Tipos de superficie soportados por SDL
El calculo de pixeles se efectúa sobre un sistema coordenado bidimensional cuyo origen se encuentra en la parte superior izquierda y termina en la parte inferior derecha, todos las librerías gráficas y 3D Engines utilizan esta convención, la figura 5-4 muestra la convención.
Las superficies pueden dibujarse con muy distintos efectos que provee SDL, algunos de ellos ya no son de un uso tan común sin embargo han permanecido para lograr efectos muy específicos que programadores experimentados deseen.
Para poder dibujar una superficie primero es necesario cargarla en memoria para lo cual se mencionan dos métodos:
● La forma más primitiva de cargar una superficie es utilizando RBG_Surface y se carga directamente en memoria de video
● Otra instrucción de mayor abstracción permite cargar una superficie desde un archivo BMP, la
instrucción se llama SDL_LoadBMP y basta para comenzar a dibujar sprites.
76
Figura 5-4
Sistema coordenado en SDL
5.2.4 MÉTODOS PARA DESPLEGAR SUPERFICIES
Existen tres formas de pintar sobre una superficie, algunas más primitivas que otras y son requeridas según el grado de detalle requerido para el efecto visual.
• Relleno de color (Color Fills): se utiliza para limpiar grandes extensiones de pixeles (mas del
50%)
• Pixeles individuales (Setting individual pixels): la técnica más refinada y elaborada
• Transferencia por bloques (Blitting): la más sencilla y más utilizada además de estar diseñada
para optimizar tiempos de refresco, para dibujar con esta técnica se requieren de dos rectángulos (o superficies) una fuente y otra destino, ello se requiere para lograr los efectos de transparencia y clipping sin interferir con la imagen original
Algunos otros efectos de video que se logran con paletas ya no son tan utilizados, otros como “alpha blending” se utiliza para lograr niveles de transparencia en una imagen para dar efectos de vidrio, fantasmas, “fading out”, etc.
Al utilizar una mayor cantidad de rectángulos en pantalla, independientes unos de otros, surge la necesidad de saber como actualizarlos para ello se cuenta con dos formas que a continuación se describen.
Dirty Rectangles: solo se re-dibujan las secciones rectangulares que se modificaron desde el último ciclo de reloj
void SDL_UpdateRect(...);
void SDL_UpdateRects(...);
Double buffering: se dibuja toda la pantalla y es el método preferido cuando se agrega a SDL instrucciones de OpenGL, opcionalmente se utiliza cuando se ha dado de alta en previa inicialización de video el modo FullScreen y DoubleBuffering
int SDL_Flip(...);
77
A continuación se muestra el código de un ejemplo utilizando algunas técnicas mencionadas:
//INICIALIZACION
…while(1)
{
if(SDL_PollEvent(&g_Event)==0)
{
g_Red=rand()%100;
g_Green=rand()%100;
g_Blue=rand()%100;
//asigna un formato de color segun el formato de la superficie
//donde se desplegara el rectangulo
//formato nativo
g_Color=SDL_MapRGB(g_pDisplaySurface->format,g_Red,g_Green,g_Blue);
//Se genera una posicion aleatoria dentro de la pantalla
g_Rect.x=rand()%SCREEN_WIDTH;
g_Rect.y=rand()%SCREEN_HEIGHT;
g_Rect.w=rand()%(SCREEN_WIDTH-g_Rect.x);
g_Rect.h=rand()%(SCREEN_HEIGHT-g_Rect.y);
//dibuja un rectangulo relleno en la superficie inicializada
//con las coordenadas al azar y el formato de color
SDL_FillRect(g_pDisplaySurface,&g_Rect,g_Color);
SDL_UpdateRect(g_pDisplaySurface,0,0,0,0);
}
else
{
if(g_Event.type==SDL_QUIT)
{
salida<<"Evento SDL_QUIT termina la aplicacion";
break;
}
}
}
78
El resultado es una “lluvia” de rectángulos que se puede observar en la figura 5-5:
5.2.5 OTRAS CARACTERÍSTICAS POR LAS QUE SDL ES CONVENIENTE
1. Permite verificar la viabilidad de una resolución en particular o cargar una lista de modos con un
número particular de bits por pixel por ejemplo
2. Permite ajustar cada canal de color, esta característica a diferencia de otras que contiene, no
puede ser emulada por software. Con el uso de ajuste de canal por color se obtienen los
efectos tan utilizados en los juegos comerciales, se puede crear una interfaz para el usuario para
ajustar una efecto de desvanecimiento hacia el blanco por un extremo o hacia el negro en el otro
3. Permite el despliegue de video .mpg utilizando el formato estándar de los YUV, este despliegue
es conocido como Overlay y se efectúa el despliegue como cualquier otra superficie
79
Figura 5-5
Efectos visuales con SDL
4. Permite la modificación real de un cursor, SDL provee de un cursor por default, la modificación
de este cursor es monocromático algo que sin duda desilusiona, pero mediante el uso de las
máscaras se pueden lograr efectos muy estéticos
Máscara positiva Máscara negativa
El resultado final se muestra en la figura :
80
00000000000000111100000000000000 00000000001111111111100000000000 00000000111111111111111000000000 00000001111111111111111100000000 00000111110000111000011111000000 00001111100000111000001111100000 00001110000000111000000011100000 00011100000000111000000001110000 00111100000000111000000001111000 00111000000000111000000000111000 01110000000000111000000000011100 01110000000000111000000000011100 01110000000000000000000000011100 11110000000000000000000000011110 11111111111100000001111111111110 11111111111100000001111111111110 11111111111100000001111111111110 11110000000000000000000000011110 01110000000000000000000000011100 01110000000000111000000000011100 01110000000000111000000000011100 00111000000000111000000000111000 00111100000000111000000001111000 00011100000000111000000001110000 00001110000000111000000011100000 00001111100000111000001111100000 00000111110000111000011111000000 00000001111111111111111100000000 00000000111111111111111000000000 00000000001111111111100000000000 00000000000000111000000000000000 00000000000000000000000000000000
00000000000000111100000000000000 00000000001111000111100000000000 00000000110000101000011000000000 00000001001111101111100100000000 00000110010000101000010011000000 00001001100000101000001100100000 00001010000000101000000010100000 00010100000000101000000001010000 00100100000000101000000001001000 00101000000000101000000000101000 01010000000000101000000000010100 01010000000000111000000000010100 01010000000000000000000000010100 10010000000000000000000000010010 10111111111100000001111111111010 10000000000100000001000000000010 10111111111100000001111111111010 10010000000000000000000000010010 01010000000000000000000000010100 01010000000000111000000000010100 01010000000000101000000000010100 00101000000000101000000000101000 00100100000000101000000001001000 00010100000000101000000001010000 00001010000000101000000010100000 00001001100000101000001100100000 00000110010000101000010011000000 00000001001111101111100100000000 00000000110000101000011000000000 00000000001111000111100000000000 00000000000000111000000000000000 00000000000000000000000000000000
Figura 5-6
Cursor construidos a partir de mascaras con
SDL
5.3 EL MANEJO DE EVENTOS
Ya que un buen juego tiende a ser controlado por eventos es indispensable conocer la definición y tipos de eventos que soporta SDL. Un evento debe definirse como algún suceso ocurrido, en SDL se distinguen distintos tipos de eventos, para ser exactos 16, estos tipos están descritos dentro de cuatro categorías: teclado, ratón, joystick y sistema.
Teclado: tecla presionada, tecla liberada, tipo de tecla (soporta shift, control y alternate)
Ratón: movimiento, botón presionado y botón liberado
Joystick: movimiento, botones y trackball
Sistema: active, quit, window manager, video resize, video expose, eventos definidos por el usuario
Existen tres métodos para recolectar los eventos y entradas: wating, polling y direct.
WatingEl programa espera a que suceda algo, se desperdicia mucho tiempo de espera, el ciclo se muestra en la figura 5-7:
81
Figura 5-7
Eventos por el método de "waiting"
PollingVerifica constantemente para saber si algún evento ha ocurrido, si es así el programa reacciona ante ello y busca más eventos, si no hay evento la aplicación realiza cualquier otra tarea pendiente para posteriormente volver a buscar, ciclo en la figura 5-8:
Direct
Ciclo en la figura 5-9:
82
Figura 5-8
Eventos por el método de "polling"
Figura 5-9
Eventos por el método "direct"
En la implementación de AmorpheBios se utilizó el método de polling debido que su ciclo propicia el ahorro de recursos.
5.4 ADD-ONS PARA SDL
Otra de las grandes ventajas que ofrece SDL sobre otras librerías es la extensión de la librería original, que a lo largo de varios años de desarrollo ha alcanzado. Algunas de estas librerías presentan características esenciales para la implementación de una aplicación multimedia completa.
● SDL_image: soporta carga de archivos BMP, PNM, XPM, LBM, GIF, JPEG, PNG, TGA lo cual garantiza una flexibilidad en el desarrollo de los modelos
● SDL_ttf: se utiliza para colocar texto de forma personalizada
● SDL_net: que sirve como plataforma para la creación de juegos vía red
● SDL_mixer: extensión del subsistema SDL_AUDIO y provee mucho más variedad de efectos y características que la librería original
5.5 SDL CON OPEN GL
OpenGL es también una superficie. Con esta mezcla de render 2D-3D podemos dibujar en pantalla utilizando dos "renders" distintos:
Render 2D: SDL
Render 3D: OpenGL
Separar los dos tipos de RENDER se menciona en la literatura como el método de mayor optimización, yo no pude corroborarlo. El método alterno, que según el programador Ernest Pazera es menos optimo, es dejar todo el render a SDL (2D y 3D). Este es el método que se utilizo para implementar SDL en AmorpheBios. Para utilizar este método se agrega una bandera de video SDL_OPENGL_BLIT al llamar a la función SDLSetVideoMode(…), para dibujar en pantalla el método Draw se implementa como:
83
void Draw(SDL_Surface* pantalla)
{
assert(pantalla);
Draw3D(pantalla);//OpenGL
Draw2D(pantalla);//sprites, guis, cursor
return;
}
En el método Draw2D se utilizan la técnica recomendada de limpieza de pantalla debido al uso de DoubleBufferin:
void Draw2D(SDL_Surface* pantalla)
{
...
SDL_Flip(pantalla);
...
return;
}
84
Figura 5-10
SDL mezclado con Open GL
En este capítulo pudimos corroborar el principio de desacoplamiento, el proceso de trasladar el juego de la librería GLUT hacia SDL no produjo ninguna complicación.
SDL al igual que GLUT, es una librería que soporta la POO y la estructurada nativamente, este hecho permite flexibilidad de implementación.
Como es visible en la figura 5-11 el manejo de “sprites” con el uso de SDL es óptimo, es posible hacer la transparencia de la imagen sin ningún proceso adicional de las texturas, esta optimización de la librería ofrece mucha flexibilidad para el despliegue de imágenes con gran calidad, característica que en los 3D Engines no es muy eficiente pues estos si obligan un tratamiento especial a la imagen dependiendo el tipo de efecto buscado, además de estar limitado a uno o algunos formatos de imagen.
Continuar el desarrollo utilizando esta librería es una muy buena opción, es por ello que a esta linea de desarrollo se le dejará el nombre de TRUNK y podrá servir como base para la construcción de un Game Engine específico para este juego estando en posibilidades de agregar audio y construir librerías físicas.
Este capítulo lo concluyo mencionando de nuevo la necesidad de contar con herramientas más poderosas, siendo el tiempo el motivo de esta necesidad. Se utilizarán otras herramientas que soporten
85
Figura 5-11
AmorpheBios con la librería SDL
mucho más características comunes a los juegos, en el siguiente capítulo se muestra una herramienta poderosísima para incrementar la interactividad en los juegos, la inteligencia artificial, pero al mismo tiempo se hará uso de un 3D Engine donde nuevamente se utilizará el principio de desacoplamiento, proceso ya descrito en este capítulo, por ese motivo no es necesario repetir al lector dicho proceso.
Con las técnicas de inteligencia artificial que se describirán en el capítulo 6 y el 3D Engine se comenzará una linea de desarrollo BRANCH , herramientas con las que se pretende construir la versión 1.0 de AmorpheBios.
86
6 TÉCNICAS DE INTELIGENCIA ARTIFICIAL10
APLICADAS A VIDEOJUEGOS
Al observar la figura 5-11 en el capítulo 5 podemos notar la existencia de un enemigo sin movimiento, el efecto gráfico ha sido completado pero ¿cómo lograr que ese enemigo pueda moverse?, ¿cómo generar un comportamiento variado según el contexto gráfico?, ¿cuándo atacará el enemigo según los casos de uso y el documento de diseño?
Las respuestas a estas preguntas son las que motivaron una investigación acerca de movimientos autónomos y estados de un objeto desde el punto de vista de la POO, lo cual significaba aprender algunas técnicas de IA11. Existe bibliografía muy especializada en IA orientada a los juegos, con esta referencia se siguió un procedimiento recomendado por los autores.
En el desarrollo del tema de IA se abarcarán dos temas, para cada uno de ellos fue necesario desarrollar dos pequeños proyectos; uno referente a la aplicación de maquinas de estado y el otro referente a los comportamientos dirigidos, por brevedad en este capítulo solo se describe el proceso de implementación de dichas técnicas en AmorpheBios, sin embargo se requirió un proceso de aprendizaje para dichas técnicas.
10 Por brevedad se utilizará el acrónimo IA para referirse a Inteligencia Artificial11 También motivo el estudio de librerías físicas y “scripting lenguages” que quedaron fuera del alcance de este proyecto
87
Figura 6-1
Creación de IA para AmorpheBios
La necesidad de obtener personajes con una mayor interactividad e “inteligencia” han originado la creación de técnicas muy especializadas de IA. Los programadores están obligados a comprender, analizar, implementar pero sobre todo mezclar adecuadamente dichas técnicas si desean construir una juego digno de ser tomado en cuenta.
Como programador de juegos es necesario acotar y definir claramente las necesidades de aprendizaje para rápidamente implementar las técnicas. El acotamiento del estudio queda claramente establecido al definir las siguientes dos clasificaciones:
•IA Académica: tiene dos subdivisiones, “strong AI” (crear sistemas que imitan el pensamiento humano) y “weak AI” (aplicar tecnologías de IA conocidas a problemas del mundo real)
•IA para Juegos: de manera general son algoritmos que toman en cuenta la limitación de recursos de computo, para alcanzar un nivel de desempeño computacional aceptable, esta IA tiene como meta ser entretenida
La cantidad y variedad de algoritmos en fuentes bibliográficas y el Internet son más que suficientes para alcanzar a construir un sofisticado mundo de IA, sin embargo la desorganización de la información y las distintas perspectivas desde las que se aborda este tópico impiden alcanzar rápidamente resultados prácticos.
En este capitulo se identifican solo las técnicas de mayor utilidad según la visión original de AmorpheBios con el fin de alcanzar una implementación rápida y entretenida. Se estudiarán solo dos técnicas de IA para Juegos, las Máquinas de Estados y los Comportamientos Dirigidos (Steering Behavior) ambos se encuentran con mayor detalle y especificación descritos en la fuente bibliográfica Game IA by Example de Matt Buckland, en mi desarrollo pretendo extender y analizar los conceptos así como la algorítmica. Finalmente se desea transmitir al lector una experiencia en el proceso de implementación en AmorpheBios.
A continuación describo el contexto de la IA para Juegos y la necesidades académicas para un comprensión integral del tema.
LA ILUSIÓN DE INTELIGENCIA
Partiendo de la definición IA para Ju egos, podemos asegurar que cuando un jugador “cree” que compite contra algo inteligente, el objetivo de la IA ha sido completado y los personajes proveen la ilusión de inteligencia. Como programadores esta ilusión resulta en algunas ocasiones benéfica, la naturaleza subjetiva de la ilusión permite “engañar” al jugador con mínimas modificaciones a un programa haciéndole pensar que lucha contra algo mas o menos inteligente.
Además de los elementos subjetivos una IA acompañada gráficos y audio resulta en una experiencia más entretenida para el jugador.
88
REQUISITOS ACADÉMICOS
Para poder comprender la implementación de los algoritmos de IA para juegos es suficiente con tener conocimientos matemáticos como: coordenadas cartesianas, vectores y calculo vectorial (2D y 3D). Por otro lado la mayoría de las técnicas de IA para juegos utilizan Física de Newton, suficientes para construir sofisticadas reglas del mundo: tiempo, distancia, masa, posición, velocidad, aceleración y fuerza son algunos de los conceptos clave para comprender la algorítmica. Ampliamente recomiendo que antes de utilizar librerías de Física y Matemáticas (énfasis en vectores 3D) ya construidas, el programador elabore las propias, con ello se alcanzará un mayor grado de confianza para adaptarse a cualquier otra librería. Como motivación mencionare la importancia que los Engines han adoptado en la industria, cada vez es más necesario implementaciones sofisticadas, esta sofisticación sería imposible de alcanzar sin un alto grado de comprensión en lo referente a la Matemática y Física mencionada.
6.1 MÁQUINAS DE ESTADO FINITO (FSM)
Las FSM (por sus siglas en inglés) han sido utilizados como “caballos de batalla” para codificar IA durante muchos años, debido a que:
ü Son simples y rápidos de codificar
ü Fáciles de depurar
ü Requieren pequeños recursos computacionales
ü Son intuitivos: pensamiento humano que sigue secuencias lógicas
ü Son flexibles: pueden combinarse con lógica difusa y redes neuronales
La definición formal de una FSM es:
Una FSM es un dispositivo o modelo de dispositivo, que tiene un número finito de estados quepueden presentarse en cualquier momento dado y pueden controlar entradas para hacer transiciones
de un estado a otro o causar una acción de salida. Una FSM puede tener un solo estado en undeterminado momento
Como programadores basta recordar que es un dispositivo rígidamente formalizado usado por matemáticos para resolver problemas. La FSM más conocida es el dispositivo hipotético de Alan Turing, que ha sido motivo de análisis y estudio académico durante muchos años.
89
Ejemplos de implementaciones de FSM en juegos son:
Los fantasmas en PACMAN estados de Evasion, Persecucion QUAKE estados EncontrarArmadura, EncontrarSalud, BuscarProtección, Escapar Juegos de deportes estados Patear, Barrer, Perseguir, Marcara Los NPC en RTS MoveToPosition, Patrol, FollowPath
La solución más simple y no por ello la más conveniente es el uso de switch (if else, if else en su defecto) para distinguir entre un estado y otro:
void Personaje::UpdateState(tipoEstado estadoActual)
{
case Escapar:
//codigo break;
case Vigilar:
//codigo break;
case Atacar:
//codigo break;
etc.
..
}
Mayor cantidad de estados y condiciones propician un código muy difícil de depurar y por ello esta técnica nunca es utilizada para implementar FSM. La solución más utilizada y elegante es la que hace uso del patrón de diseño “State”, para la implementación de este tipo de modelo es necesario definir algunas herramientas que permitan identificar y ordenar los distintos estados utilizados por un personaje así como sus transiciones.
90
6.1.1 TABLAS DE ESTADOS DE TRANSICIÓN
Para definir una tabla de transición utilicemos el documento de diseño y la obtención de requerimientos en la abstracción clave Patógeno, este puede ser liberado (Liberar), Contaminar y Escapar. Las transiciones de estos estados estarán definidas por la condiciones en las que el personaje se encuentre dentro del mundo.
ESTADO ACTUAL CONDICIÓN ESTADOTRANSICIÓN
Liberar Juego en construcción y sincolisión con Materia
Liberar
Liberar Juego en construcción ycolisión con Materia
Contaminar
Liberar Juego en destrucción EscaparContaminar Juego en construcción ContaminarContaminar Juego en destrucción Escapar
Escapar Juego en destrucción EscaparEscapar Juego en construcción y aún
en colisión con MateriaContaminar
Escapar Juego en construcción y sincolisión con Materia
Contaminar
Tabla 6-1
Estados de transición de Patogeno
6.1.2 REGLAS EMBEBIDAS
Con una tabla de estados de transición definida es posible construir una visión más autónoma donde la propia máquina cambia de estados según algún contexto predefinido, de manera formal “pegar las reglas” a los cambios de estado dentro de los estados mismos. Para ello creamos una interfaz llamada Estado:
class Estado
{
public:
virtual void Execute(Personaje* p)= 0;
}
91
Después se crea la clase Patogeno que contiene atributos relacionados a el mismo como resistencia, velocidad, resistencia y elementos 3D,. así como sus interfases para el ajuste de estos atributos. Una referencia a la interfaz Estado es suficiente para agregar el comportamiento de estados al Patogeno:
class Patogeno
{
Estado* m_pEstadoActual;
public:
void Update()
{
m_pEstadoActual->Execute(this);
}
void cambiarEstado(const Estado*pNuevoEstado)
{
delete m_pEstadoActual;
m_pEstadoActual = pNuevoEstado;
}
};
A continuación creamos una clase por cada estado que este definido para el Patogeno, estas clases son heredadas de Estado:
class Liberar: public Estado
{.
..
};
class Contaminar: public Estado
{.
..
};
etc ...
92
Al transformar estas clases en un diagrama de UML observamos la estructura siguiente en la figura 6-2:
El diagrama de la figura 6-2 es el conocido como patrón de diseño de estados (State Pattern). Se implementa una clase por cada estado de la FSM.
93
Figura 6-2
Diagrama de estados de patógeno
6.1.3 CLASES DE BASE Y EL PATRÓN SINGLETON
La reusabilidad de nuestro diagrama UML al momento de implementación es insuficiente para un juego, es muy recomendable que se defina una clase de base para las entidades (personajes). La clase de base debe contemplar la existencia de otras técnicas de IA para el personaje (además de sus Estados), en este caso se observará que el uso de Update() será incluso utilizado para comportamientos más sofisticados como los Steering Behaviors. Otra característica indispensable para la clase de base es un ID única para cada entidad Patogeno, el recorrido y comparación con elementos del mundo se simplificará la contar con este atributo. Por otra parte además de Execute(), es recomendable que cada estado contenga acciones como entrar y salir, así es posible implementar lógica que debe ser ejecutada una sola vez como la animación al hacer una transición de un estado a otro.
En la figura 6-3 mostramos el diagrama de estados de la figura 6-2 utilizando reusabilidad:
94
Figura 6-3
Diagrama de estados con reusabilidad
Este diagrama UML de la figura 6-3 muestra los distintos estados que puede adoptar el Patógeno en un momento determinado sin embargo dos preguntas surgen:
¿Es necesario que dos estados existan en tiempo de ejecución? ¿En qué forma el Personaje, instancia un estado concreto?
La respuesta a la primera pregunta es no, un personaje solo puede tener un estado por cada momento determinado. Para cumplir con este requerimiento es necesario recurrir a el patrón Singleton. Existen muy diversas metodologías de implementación para este patrón, en este desarrollo se prefiere utilizar el método estático.
Para la responder la segunda pregunta recurriremos al mismo método estático de Singleton Pattern, la decisión de su uso no es solo por su desempeño computacional (pues solo se tiene en memoria el estado que actualmente se ejecuta y se tiene un acceso global) sino que se provee de un método que permite instanciar precisamente al estado concreto, justo lo que se requiere.
El método estático provee muchas ventajas, pero tan solo para mencionar una se plantea la siguiente problemática, ¿qué sucedería si en vez de que cada estado sea Singleton, la clase de base lo sea y todas sus herencias lo requirieran al igual?, en este escenario el método estático no funciona.
95
Figura 6-4
Diagrama de estados con reusabilidad y Singleton
6.1.4 CAMBIOS DE ESTADO: EL MÉTODO INEFICAZ
Para lograr las transiciones entre estados, se ha definido una forma de acceso a estados concretos al Personaje pero aún no se describe un método de transición, por ello se agrega el método cambiarEstado(Estado* estadoNuevo):
void Patogeno::cambiarEstado(Estado* estadoNuevo)
{
assert(estadoActual && nuevoEstado);
estadoActual->Exit(this);
estadoActual = estadoNuevo;
estadoActual->Enter(this);
}
Este método proporciona la versión funcional UML sin optimización que se muestra en la figura 6-5:
96
Figura 6-5
Diagramas de estados con cambio (Update(...))
6.1.5 IMPLEMENTACIÓN DE ESTADOS
La última versión de UML mostrada permite definir la implementación de las clases concretas. Cualquier personaje con estados a partir de este diseño UML deberá cumplir con las siguientes características:
ü A partir de cada estado creamos una clase concreta, las clases deben contener los métodos Enter(), Execute(), Exit(
ü Cuando una transición ocurre el Personaje debe llamar a los métodos del estado Exit(),
reasignar su estado y Enter()
ü Cada estado concreto debe ser implementado como un objeto Singleton, cada entidad del
juego comparte ese estado que es solo uno en un momento determinado
ü Es recomendable que todos los estados de un Personaje se coloquen en un mismo archivo con
el fin de hacerlos reusables
Recordemos que la clase estado es una interfaz:
#ifndef _ESTADO_H
#define _ESTADO_H
#include "patogeno.h"
class Estado
{
public:
virtual ~Estado(){}
virtual void Enter(Patogeno*)=0;
virtual void Execute(Patogeno *)=0;
virtual void Exit(Patogeno*)=0;
};
#endif
97
La implementación de las clases se provee en un solo archivo
...
#include "estado.h"
class Contaminar: public Estado
{
private:
Contaminar (){}
Contaminar (const Contaminar &);
Contaminar & operator=(const Contaminar &);
public:
static Contaminar * Instantiate();
virtual void Entrar(Patogeno*);
virtual void Ejecutar(Patogeno*);
virtual void Salir(Patogeno*);
};
class Liberar: public Estado
{
...
};
class Escapar: public Estado
{
...
};
...
98
Cada uno de los estados contiene una lógica similar por ello describiré solo la implementación de uno de ellos:
/*-------El Singleton----------*/
Escapar* Escapar::Instance()
{
static Escapar instancia;
return &instancia;
}
void Escapar::Enter(Patogeno* p)
{
p->setTime(0.05);
p->dameModeloAnimacion()->caer();
}
void Escapar::Execute(Patogeno* p)
{
switch(p->dameModo())
{
case 1:
if( (p->Pos() - core::vector3df(-3,0,-1) ).getLength() > 20)
p->cambiarEstado(Liberar::Instance());
break;
case 2:
p->cambiarEstado(Liberar::Instantiate());
break;
}
}
void Escapar::Exit(Patogeno* p)
{
p->notifica("Saliendo estado escapar");
}
99
6.1.6 CAMBIOS DE ESTADOS: MÉTODO CON FSM
Hasta este momento hemos asegurado que la lógica asociada al Patogeno y la lógica asociada a los estados este desacoplada, ¿es esto completamente cierto? Recordemos que el último diagrama de UML funcional provee un método para transiciones de los estados y está precisamente dentro de la clase Patogeno, así que no es 100% desacoplado. Plantemos una situación mucho más común, si el personaje deseara guardar una referencia a un estado previo, como sucede en juegos como The Sims, o si fuera necesario un estado global como un daño constante al personaje independiente de sus acciones, ¿que tanta cantidad de lógica relativa a estados se deberá agregar al método cambiarEstado()? Este planteamiento nos obliga a implementar una clase intermedia entre Personaje y Estado, es precisamente una maquina de estados FSM. Aunque la dependencia entre la clase Personaje y la FSM pasara de una agregación que tenia con la clase Estado a una composición, lo cual incrementa su dependencia, pero la lógica de estados es más flexible y desacoplada un 100%. En la figura 6-6 se observa la inserción de la clase FSM (MaqunaEstados).
100
Figura 6-6
Diagrama de estados con FSM
El método cambiarEstado() originalmente ejecutado por el Patógeno es ahora ejecutado por la FSM, por ello el Patogeno ya no contiene referencias hacia algún Estado, en cambio solo contiene una referencia hacia FSM.
void FSM::cambiarEstado(Estado<entity_type>* nuevoEstado)
{
assert(nuevoEstado);
//recordar el estado actual, que sera el previo
m_estadoPrevio = m_estadoActual;
m_estadoActual->Salir(m_entidad);
m_estadoActual = nuevoEstado;
m_estadoActual->Entrar(m_entidad);
}
on este estado previo deshacer cambios a acciones se vuelve sumamente sencillo, el concepto se puede extender para memorizar tantos cambios previos como se puedan. El método Update() del Patogeno ya no utiliza referencias de Estados, en cambio solo invoca a:
void Personaje::Update()
{
m_pStateMachine->Update();
}
101
6.2 MOVIMIENTOS AUTONOMOS12
Durante la década de los 80’s un documental de la BBC mostraba el estado del arte en gráficas por computadora, aquella magia algorítmica de la época logró imitar el comportamiento de una parvada. La algorítmica que se describía estaba basada en reglas muy simples según palabras de su creador, característica que causaba admiración entre los programadores ya que se esperaba una gran sofisticación de código para lograr el efecto de espontaneidad y naturalidad de las aves virtuales. El programador encargado de diseñar estos comportamientos se llama Craig Reynolds. Desde esta presentación en la BBC a esta congregación de aves se le denomino “boids”13 y las reglas simples provenían de lo que el propio diseñador denomino como “Steering Behaviors” o comportamientos dirigidos.
Algunos de estos comportamientos dirigidos se difundieron entre muchos diseñadores de juegos aplicándolos muchos de sus desarrollos. La mayor difusión alcanzada fue en la época del Play Station ya que Craig trabajaba para Sony en aquellos años, logrando un efecto de realismo no imaginado en anteriores épocas ha tenido tal estabilidad la implementación de estos comportamientos que hasta la actualidad sigue siendo utilizado. Craig a partir de aquella publicación en la BBC ha extendido y mezclado sus comportamientos para crear efectos de muy distintos propósitos. El termino comportamientos dirigidos que definió Craig Reynolds es fácilmente comprendido cuando se expresa en el contexto de entidades autónomas o entidades con inteligencia, los comportamientos dirigidos son mandatos o instrucciones que indican con precisión a una entidad de esta naturaleza que dirección tomar a cada instante de tiempo.
Para comenzar el estudio de los comportamientos dirigidos, el concepto de entidad autónoma debe quedar claramente definido.
12 Mejor conocidos en la literatura como Steering Behavior, no es común encontrar referencia utilizando la traducción directamente
13 Acrónimos de Bird Oids
102
Figura 6-7
Boids
¿QUÉ ES UNA ENTIDAD AUTÓNOMA?
Una entidad autónoma es un sistema situado dentro y parte de un ambiente. La entidad sensa elambiente y actúa sobre él a través del tiempo, con un objetivo propio y así puede modificar efectos
futuros en el ambiente
El movimiento autónomo de una entidad puede dividirse en:
Selección de acción: la entidad es responsable de elegir sus metas y decidir que plan seguir, “ve allí y haz A,B o C”
Dirección: esta capa es responsable de calcular las trayectorias requeridas para satisfacer las metas y planes previamente establecidas por la capa de selección. Se producen fuerzas de dirección que describen donde una entidad debe dirigirse y que tan rápido debe hacerlo
Locomoción: esta es la capa de abstracción más baja, locomoción representa aspecto mecánicos del movimiento de la entidad. Es el como viajar de un punto A hacia B, que tan rápido gira, que velocidad lleva, que aceleración soporta, etc.
Desacoplando la capa de dirección y la capa de locomoción es posible reutilizar, con pequeñas modificaciones, los mismos comportamientos de dirección para distintas locomociones, por ejemplo, la misma dirección para un tanque y un helicóptero.
6.2.1 CAPA DE LOCOMOCIÓN: EL MODELO DE MOVIMIENTO
Para iniciar el desarrollo de los algoritmos definiremos la capa de nivel más bajo, la locomoción. Esta pretenderá ser lo más simple posible, un modelo de locomoción genérico llamado Vehiculo será nuestro modelo de locomoción. La lógica requerida para trasladar la librería de un mundo 2D a 3D o viceversa es la misma, basta con modificar los variables definidas en dos dimensiones hacia tres dimensiones.
103
Figura 6-8
Abstracción de la entidad en movimiento
La figura 6-8 nos presenta la generalización de un vehículo a través de la clase Vehiculo, sin embargo
dentro de la locomoción podemos contener cualquier otro tipo de entidades con movimiento.La relación de clases que representa esta abstracción se muestra en la figura 6-9:
El nombre de los atributos están directamente asociados a su significado, 3 atributos son utilizados para controlar el direccionamiento del vehículo, los restantes son atributos numéricos que serán ajustados según la naturaleza del comportamiento, más adelante se muestran valores típicos requeridos para el instrucciones en el método Update() de la clase Patogeno.
104
Figura 6-9
El patógeno y su relación con las
entidades en movimiento
En el diagrama UML de la clase Vehicle se menciona el método Update(…), no olvidemos que este mismo método fue implementado en las entidades de los Estados en la sección anterior. Es claro como pueden ser mezcladas ambas técnicas utilizando este método. La herencia de los personajes en el caso de la técnica de Estados se origina por la clase GameEntiy y en el caso de esta técnica se origina por MovingEntity, para evitar la presencia de herencia múltiple se prefiere una estructura de clases como en la figura 6-10:
El método Update(…) es de suma importancia para el calculo de las fuerzas que se crean con los
algoritmos de SteeringBehaviors, los pasos que se necesitan para este calculo son:
1. Calculo de la fuerza de los “SteeringBehaviors” Calculate()
2. Se calcula una nueva aceleración con la fuerza del paso1 utilizando la formula de la primera ley de Newton a = F/m
3. Se calcula una velocidad con la aceleración del paso2 utilizando la formula de movimiento v = v0+a*t
105
Figura 6-10
La reusabilidad y la entidad en movimiento
4. Se verifica que se ha alcanzado el valor de m_dMaxSpeed para evitar inconsistencias truncate(…)
5. Se actualiza la posición del patógeno según la velocidad actual delta(X) = v delta(t)6. Se actualizan los vectores afectados (dirección y perpendicular a la dirección) por el
cambio del vector velocidad, para que la actualización sea valida el cambio entre la velocidad anterior y la velocidad actual tiene que ser mayor que el mínimo número soportado por la computadora para evitar divisiones entre CERO
El diagrama UML de la figura 6-10 anterior podemos observar una referencia a la clase SteeringBehavior, después de describir el método Update(…) el diagrama de clases incluyendo SteeringBehavior se muestra en la figura 6-11:
A continuación se describen algunos de los comportamientos de la clase SteeringBehavior (en realidad esta clase debe llamarse librería debido a la cantidad de juegos y aplicaciones que la han utilizado).
106
Figura 6-11
La clase SteeringBehavior
6.2.2 CAPA DE DIRECCIÓN: COMPORTAMIENTOS DIRIGIDOS
Se ha definido un modelo de locomoción para el Patogeno, es ahora posible implementar la siguiente capa de IA, la capa que define el modelo de dirección. Una fotografía vectorial del Patogeno en un instante de tiempo debería proporcionar la siguiente información:
El calculo de la fuerzas que dirigen al vehículo se reduce a actualizar estos tres vectores, sin embargo ya hemos definido que el calculo de los vectores Direccion y Perpendicular (m_vHeading y m_vSide respectivamente) se realizan por el método Update(), entonces es suficiente con limitar los cálculos en esta librería al vector Velocidad.
Debido que todos los métodos de dirección requieren el calculo de una fuerza, se prefiere encapsular estos detalles en un método independiente llamado Calculate() (que más adelante se explicará). En los métodos de dirección solo se calculan velocidades y este resultado es reutilizado por el método Calculate() donde si se hace el calculo de la fuerza.
BUSCAR (SEEK)
Se realiza el calculo de una fuerza que dirige a una entidad hacia un blanco fijo, el blanco puede ser obtenido mediante una referencia hacia el mundo del juego, a través de coordenadas generadas por el ratón o aleatoriamente dentro de un límite establecido.
1. Se calcula la velocidad deseada, la velocidad se calcula suponiendo un mundo ideal.
107
Figura 6-12
Componentes vectoriales de la
entidad en movimiento
Representa el vector desde la entidad hasta el objetivo considerando la velocidad máxima delvehículo (m_dMaxSpeed)
2. Este valor ideal es restado de la velocidad actual del vehículo
SVector2D SteeringBehavior::Seek(SVector2D TargetPos)
{
SVector2D DesiredVelocity = (TargetPos - vehiculo->Pos()).normalize() * vehiculo->MaxSpeed();
return (DesiredVelocity - vehiculo->Velocity());
}
HUIR (FLEE)
Huir es lo contrario a Buscar, basta con modificar uno de los signos en el código (la parte que corresponde al diagrama de posiciones) para obtener este resultado.
SVector2D SteeringBehavior::Flee(SVector2D TargetPos)
{
SVector2D DesiredVelocity = (vehiculo->Pos() - TargetPos).normalize() * vehiculo->MaxSpeed();
return (DesiredVelocity - vehiculo->Velocity());
}
Cuando se están implementando estos comportamientos en mundo 2D se puede refinar el comportamiento Huir al definir una distancia de pánico. Por la naturaleza del espacio 2D la distancia de pánico puede ser cuadrática, esta constante permite definir un área determinada donde el vehiculo escapa del blanco hasta un cierto límite. Cuando este límite ha sido sobrepasado el vehículo deja de Huir, este efecto se implementa agregando una condición y regresando el vector CERO cuando no se cumpla.
Dicha distancia pánico es igualmente implementada en 3D pero no es necesaria una distancia cuadrática, basta con la diferencia entre el vector posición y el blanco para asegurar una distancia mínima.
LLEGAR (ARRIVE)
Buscar se utiliza para mover una entidad en la dirección correcta sin embargo el blanco establecido para el vehículo no es suficiente para detenerlo en su totalidad. Para detener a un vehículo en la posición indicada es necesario realizar Buscar. Como se requiere mayor especificación en la función Llegar se agrega una constante de desaceleración pasado como parámetro a la función y una constante de ajuste para los cálculos dentro de la función.
108
Deceleration{slow = 3, normal = 2, fast =1}
SVector2D SteeringBehavior::Arrive(SVector2D TargetPos, deceleration deceleration)
{
SVector2D DesiredVelocity = TargetPos - vehiculo->Pos();
double dist = ToTarget.length();
if(dist > 0)
{
//uso de las constantes y a continuacion proceder como Seek
....
}
return SVector2D(0,0);
}
PERSEGUIR (PURSUIT)
Este comportamiento es útil cuando una entidad es requerida para interceptar a un blanco en movimiento, puede mantenerse la función Buscar respecto a la posición actual del blanco, pero esto no tendrá un efecto de inteligencia. La solución que se ha preferido por la estética es la de predicción, gracias a que el calculo de fuerzas esta basado en las leyes físicas más simples, se puede jugar con el tiempo de una forma muy sencilla. Cuando nos referimos a predicción estamos hablando de un tiempo futuro, en la implementación se buscará una forma de predecir una posición en un tiempo futuro, ¿que tan futuro debe ser ese tiempo? depende del efecto que se este buscando.
1. Si el perseguidor esta cerca del perseguido rápidamente se encontrarán, se utiliza la función
Buscar y no se predice
2. La cantidad de “vistas” hacia el futuro serán dependientes de la separación entre los actores y
sus velocidades(perseguido y perseguidor), se realiza predicción y a continuación se utiliza la
función Buscar
La primera condición es fácilmente resuelta si se utilizan productos punto, los productos punto sirven para obtener una dirección “frente a frente”:
109
double direccionRealtiva = vehiculo->Heading().dot(perseguido->Heading());
if(direccionrelativa < -0.95)
return Seek(perseguido->Posicion());
else
//codigo para predecir
return Seek(perseguido->Posicion + perseguido->Velocidad()*tiempoPrediccion);
La direccionRelativa se puede explicar observando la figura 6-13:
El valor -0.95 representa el producto punto, con la formula UV = |U| |V| cos θ, por lo tanto θ = arccos UV/|U||V|, que en esta caso corresponde a un valor de 18°, este margen de frente a frente es el que se utiliza para utilizar Buscar.
La segunda condición solo agrega el elemento de predicción. La formula que describe el tiempo futuro es t = d/V, d es la que existe del perseguidor al perseguido y V es la suma de la máxima velocidad del perseguidor y la velocidad actual del perseguido.
double direccionRealtiva = vehiculo->Heading().dot(perseguido->Heading());
if(direccionrelativa < -0.95)
return Seek(perseguido->Posicion());
else
//predicción
double lookAheadTime = distanciaHaciaPerseguido()/ (vehiculo->MaxVelocidad() +
perseguido->Velocidad());
return Seek(perseguido->Posicion + perseguido->Velocidad()*tiempoPrediccion);
110
Figura 6-13
Dirección relativa
Para validar las condiciones de predicción y no predicción es necesaria una condición más. Si observamos el diagrama anterior, podemos concluir que existen casos donde el rango de visión se cumpla y no estén posicionados frente a frente, esa condición solo especifica un direccionamiento relativo entre ambos. La figura 6-14 muestra esta condición.
El producto punto de la direccionVehiculo y haciaPerseguido realiza la comprobación.
SVector2D haciaPerseguido = perseguido->Posicion() - vehiculo->Posicion();
double direccionRealtiva = vehiculo->Heading().dot(perseguido->Heading());
if(direccionrelativa < -0.95 && haciaPerseguido.dot(vehiculo->Heading))
return Seek(perseguido->Posicion());
else
//predicción
double lookAheadTime = distanciaHaciaPerseguido()/ (vehiculo->MaxVelocidad() +
perseguido->Velocidad());
return Seek(perseguido->Posicion + perseguido->Velocidad()*tiempoPrediccion);
111
Figura 6-14
Condición para validar predicción
EVADIR (EVADE)
Evadir es el comportamiento contrario a Perseguir, como este efecto es más simple aquí no existe condición para realizar la predicción, en cambio siempre se predice y a continuación invoca el método Huir.
SVector2D haciaPerseguido = perseguido->Posicion() - vehiculo->Posicion();
//predicción
double lookAheadTime = distanciaHaciaPerseguido()/ (vehiculo->MaxVelocidad() +
perseguido->Velocidad());
return Flee(perseguido->Posicion + perseguido->Velocidad()*tiempoPrediccion);
6.2.3 EL MÉTODO DE CÁLCULO DE FUERZAS
Como anteriormente se menciono a menudo se utilizan combinaciones de comportamientos individuales para obtener el efecto deseado, muy raramente se utilizará solo uno.
Generalmente todos los comportamientos individuales son encapsulados en la clase SteeringBehavior, la entidad Patogeno posee una instancia de esta clase y activa o desactiva (On/Off) algunos de los comportamientos. Cada vez que se ejecuta el método Update(…) del Patogeno se utiliza el método Calculate:
Vector3df SteeringForce = m_pStering->Calculate();
SteeringForce es el resultado de todos los comportamientos que previamente activo el Patogeno, como es de esperarse la simple suma de todas ellos no proporcionaría un resultado óptimo, se mencionan tres métodos para un calculo de mayor utilidad.
Weighted Truncated Sum: utiliza una constante de peso distinto para cada comportamiento, se suman y se trunca el resultado según la fuerza máxima Weighted Truncated Running Sum with Prioritization: de mayor optimización en cuanto recursos de computo se refiere, se ordenan en forma descendente los comportamiento de mayor a menor prioridad, además se realiza una suma de fuerzas utilizando una constante como en el caso anterior, para resolver si se excede la fuerza máxima o si es necesario agregar una fuerza según su prioridad se recurre a un método llamado AccumulateForce(…) Prioritized Dithering: método propuesto por Craig donde se utiliza una probabilidad
112
para cada comportamiento activado, tiene un ahorro de recursos muy parecido al método anterior sin embargo la precisión de los cálculos disminuye
De los tres métodos descritos se utilizó el segundo por la precisión y costo computacional tan bajo que ofrece. Como se menciono que se requiere prioridad en la colocación del código se elige por conveniencia los métodos de evasión primero (Evadir Muros y Obstaculos, Huir) y finalmente Buscar, Llegar, Vagabundear, Perseguir, Perseguir Desplazamiento, etc.:
Vector2D SteeringBehaviors::Calculate()
{
m_vSteeringForce.Zero();
SVector2D force;
//grupo de primer prioridad
if( On(Flee) )
{
force = Flee(m_Patogeno->dameBlanco();
if( !AccumulateForce(m_vSteeringForce, force))
return m_vSteeringForce;
}
... ...
//grupo de segunda prioridad
if (On(seek))
{
force = Seek(m_pPatogeno->dameBlanco()) * m_dWeightSeek;
if (!AccumulateForce(m_vSteeringForce, force)) return m_vSteeringForce;
}
if (On(arrive))
...
return m_vSteeringForce;
}
113
El método AccumulateForce encargado de verificar si es posible agregar, trucar o descartar la fuerza.
bool SteeringBehavior::AccumulateForce(vector3df &RunningTot,
vector3df ForceToAdd)
{
//cuanta fuerza de la maxima que tiene el Vehiculo ha sido utilizada
double MagnitudeSoFar = RunningTot.Length();
//cuanta fuerza sobra para ser utilizada
double MagnitudeRemaining = m_pVehicle->MaxForce() - MagnitudeSoFar;
//si no sobra mas fuerza no se cacula nada
if (MagnitudeRemaining <= 0.0) return false;
//se calcula la magnitud de la fuerza a agregar
double MagnitudeToAdd = ForceToAdd.Len
//condicion para truncar de ser necesario
if (MagnitudeToAdd < MagnitudeRemaining)
{
RunningTot += ForceToAdd;
}
else
{
//se agrega ala fuerza de direccion
RunningTot += (Vec2DNormalize(ForceToAdd) * MagnitudeRemaining);
}
return true;
}
114
6.2.4 PROBLEMAS CON LOS COMPORTAMIENTOS DIRIGIDOS
El grado de refinamiento que se ha logrado con el paso de los años y el uso constante de los comportamientos dirigidos han sido materia de estudio por muchos especialistas en la rama de IA para juegos, muchas soluciones no son precisas pero ofrecen un consumo pequeño de recursos de computo lo que ha permitido su sobre vivencia al paso del tiempo, otras soluciones más académicas refinadas y precisas no proporcionan esta ventaja.
SIN SOBREPOSICIÓN
La combinación de ciertos comportamientos y grandes cantidades de entidades provocan el indeseado efecto de sobre posición, una fuerza de Separación no es suficiente para eliminarlo. En muchas aplicaciones es tolerable el efecto pero cuando no se desea se puede proveer al vehículo de un radio frontera y una constante de no penetración, con ambos atributos se puede implementar un método que verifique el traslape, cuando exista la función debe proveer fuerzas opuestas entre entidades vecinas.
Grandes cantidades de entidades aún se traslapan con el uso de este método, sin embargo a la vista del jugador es prácticamente imposible identificarlo, a continuación se muestra el problema en un modelo de 2D.
115
Figura 6-15
Sobreposición en 2D
Muchos de los comportamientos de grupo involucran un recorrido de cada una de las entidades, este recorrido propicia cálculos computacionales que llegan al orden de O(n2), se puede disminuir este orden utilizando técnicas de partición del espacio donde se encuentran las entidades:
Arboles BSP Arboles Quads Arboles Oct
Todas estas soluciones con un alto desempeño en tiempo, pero el gasto de memoria es excesivo. Para evitar el uso de árboles que tantos recursos de memoria consumen, se prefieren las listas ligadas, con un método conocido como “bin-space partitioning”, particionamiento del espacio por celdas.
El espacio es dividido en celdas, cada celda contiene una lista de apuntadores hacia las entidades que contiene, esta lista es actualizada cada que una entidad cambia de una celda hacia otra. De esta forma en vez de verificar en cada ciclo de reloj todas las entidades, solo se verifican que celdas están en la vecindad de un vehículo y se recorren solo las entidades de esa celdas.
116
Figura 6-16
Particionamiento espacial solución para la sobre posición
EL EFECTO DE TEMBLORINA
Cuando una entidad se encuentra entre un muro y al mismo tiempo evitando contacto con otras entidades, el vehículo comienza a sacudirse de un lado a otro que da el efecto de una temblorina, si se requiere de mucha precisión este efecto puede causar muchos problemas, para evitarlo se desacopla la velocidad del vehículo y su dirección, Robin Green de Sony implemento esta propuesta promediando el valor de estos vectores dosificando el calculo en varios ciclos de reloj. La solución no es perfecta pero produce un efecto adecuado a bajo costo.
117
Figura 6-17
Distintas direcciones en
instantes de tiempo muy cortos
En la figura 6-18 se muestra el diagrama de clases utilizado para la creación de la IA del patógeno utilizando las dos técnicas descritas:
118
Figura 6-18
IA del patógeno
Cuando se trata de utilizar técnicas de IA es indispensable practicar creando pequeños proyectos antes de comenzar a utilizarlos directamente en el proyecto personal, concluyo que en el aprendizaje de dichas técnicas no se trata de aplicarlas y saber como implementarlas sino la combinación adecuada de distintos tipos de ellas, ¿cuándo es necesario agregar más o menos de un comportamiento?, es una pregunta que solo puede ser respondida con el criterio y experiencia del programador de la IA.
La implementación de las FSM es de mucha simplicidad por lo que es casi obligado en los juegos el uso de esta técnica, a través del uso y aplicación de dicha técnica se llego a la conclusión de aplicarla en el comportamiento mismo del juego (PAUSA, INICIAR, CARGAR, etc.)14, no se completo esta necesidad ya que originalmente no se pensó en la creación de un editor de niveles, consecuencia de utilizar esta técnica.
En la implementación de los comportamientos dirigidos se obtuvieron los efectos originalmente buscados, sin embargo quedan pendientes dos tareas:
· La tarea de colisionar a los enemigos con la Materia, implementación que involucra el uso de librerías físicas
· La tarea de suavizar la locomoción de las entidades, imperfección que no pudo ser resuelta en el tiempo planeado para el proyecto
14 Estos estados fueron inocentemente pensados como funciones de la entidad AmorpheBios un error común en los diseñadores inexpertos
119
7 CONCLUSIONES
Concluyo que es indispensable en las primeras etapas de desarrollo del juego, se cuente con un claro y conciso enfoque, gracias este fue posible conservar la esencia de la aplicación aún con la inexperiencia en desarrollo de juegos y los constantes detalles de programación. Esta importancia es mencionada por la mayoría de los diseñadores experimentados y es corroborada en este proyecto.
Durante el proceso de desarrollo de este proyecto se han definido con mayor precisión las diferencias que existen entre la creación de un software convencional y la creación de un juego. A continuación menciono las características desde el punto de vista de la funcionalidad de análisis y diseño de sistemas.
Por un lado encontramos las necesidades funcionales que deben ser constantemente refinadas y probadas (en principio por el propio diseñador), problema que desde el punto de vista de análisis y diseño de sistemas se resuelve fácilmente utilizando los modelos iterativos. Algunos pequeños ajustes son necesarios (no aplicables en software convencional), al definir documentación, casos de uso, abstracciones principales y diagramas de robustez, las características sobresalientes que se presentaron son:
La elaboración del documento de requerimientos se hace innecesaria en las primeras etapas de desarrollo de un juego que propone una jugabilidad nueva, ya que a cada iteración de los prototipos se busca un refinamiento que no puede ser previsto documentando. Al obtener un prototipo como el logrado al final de este proyecto si se hace indispensable el documento de requerimientos y el documento de diseño. Si el desarrollo del juego es de reconocida jugabilidad la documentación puede seguirse del mismo modo que un software convencional
La comunicación entre los actores y los objetos de frontera no son únicos para la interacción con la aplicación, ya que las variables como el tiempo y la IA son actores que forman parte del sistema mismo, interactúan directamente con objetos de control
Cuando se plantean casos de uso principales y expandidos debe ser previsto si se desea desarrollar un juego con su propio motor gráfico o desarrollar sobre uno ya completado, este problema no fue previsto en las primeras etapas lo que impacto en la creación de casos de uso suponiendo la existencia de la segunda situación (que es de hecho la situación ideal y
120
más común)
La utilidad del principio de desacoplamiento aplicado a los juegos, fue sobresaliente al hacer la migración de un sistema en GLUT hacia SDL
La necesidad y utilidad de desarrollar juegos sobre el paradigma de POO (más aún orientada a eventos), la mayoría de los programadores de juegos no experimentados utilizan un modelo estructurado en sus primeros desarrollos, sin duda esto retrasa la terminación de sus juegos. El utilizar el enfoque de POO y algunos patrones de diseño considero que aceleraron el proceso de desarrollo de este proyecto
Por otro lado tenemos las necesidades no funcionales (incluyendo el estilo y calidad artística) de mayor cantidad, complejidad y subjetividad. Estas tres características son dependientes de la experiencia del diseñador del juego y el equipo de trabajo, problema que es solucionado dependiendo de la cantidad de tiempo con el que se cuenta para el desarrollo, los recursos económicos, el tamaño del equipo y aspiraciones comerciales de la aplicación. En el caso de este proyecto fue indispensable el aprendizaje de modelado 3D por el programador mismo, una necesidad no funcional que tiene un impacto muy severo en la calidad de la aplicación.
Por los motivos expuestos concluyo que para mejorar el proceso de desarrollo en creadores inexpertos es recomendable la creación de juegos ya conocidos en 2D-3D (PAC-MAN, Mario-Bros, Doom etc.), según el criterio y gusto de los creadores. Esta experiencia sirve como marco de referencia para una implementación de un juego de diseño propio. Se hace indispensable un conocimiento amplio de dibujo (sprites y modelos 3D) por lo que es necesario acotar la implementación a mundos 2D si no se cuenta con experiencia previa en modelado 3D. Con estos lineamientos considero que es posible asegurar la creación de un juego en su totalidad en el lapso de 6 meses, sin involucrar demasiados aspectos no funcionales y artísticos en la creación del mismo.
La parte algorítmica que conforma un juego es extensa y sofisticada de programar, algunas de las técnicas que se utilizaron son fácilmente implementadas gracias a la potencialidad del lenguaje utilizado (iteradores, colecciones, manejo de memoria, rendimiento entre otras), a la reutilización de técnicas utilizadas en otros juegos y la comprensión profunda de temas matemáticos por parte del programador.
En la implementación del juego sobre el 3D Engine fueron necesarias crear algunas funciones matemáticas, estas funciones fueron implementadas en un conjunto de rutinas de C (utilidades.h) que en su mayoría son algoritmos del calculo vectorial y creación de
121
valores aleatorios.
Se ha alcanzado un grado de jugabilidad aceptable en un lapso de 6 meses empezando desde cero, esta jugabilidad es tal y como la perspectiva del diseñador de juegos lo prevé. El refinamiento de esta jugabilidad puede mejorarse en el proceso de creación del editor de niveles, siguiente etapa de desarrollo del juego, donde un equipo de trabajo comienza su participación. La versión que se logró completar es la 0.7, debido a los detalles no perfeccionados de comportamientos dirigidos, la deficiencia de información gráfica (la lista de organismos por ejemplo) y modelado 3D.
122
8 APÉNDICE A Imágenes de AmorpheBios v0.7
123
Imagen B
Construyendo
Imagen A
Ayuda
124
Imagen C
Disparando vista 1
Imagen D
Disparando vista 2
125
Imagen E
Drag and Drop etiquetas
Imagen F
Fin de juego
9 APÉNDICE B Dibujo
9.1 MODELADO 3D
Para el proceso de aprendizaje del paquete de modelado 3D BLENDER fue necesario construir algunos modelos de prueba que se muestran en la imagen 2-8 y 2-9:
126
Imagen G
Prueba de un humano con una corona
127
Imagen H
Muñeco de gengibre
A continuación algunos de los modelos que fueron utilizado en la aplicación.
128
Imagen I
Materia: célula
El patógeno fue construido utilizando la técnica conocida como Bones And Skin, diseñado y modelado por Héctor Carrillo Randolph.
129
Imagen J
Patógeno por Héctor Carrillo Randolph
130
Imagen K
Etiqueta de geometría esférica
131
Imagen L
Visor de geometría cónica
9.2 SPRITES Y TEXTURAS
Los "sprites" que se muestran son los utilizados como GUI's de AmorpheBios.
132
Imagen M
Cursor de AmorpheBios
Imagen N
Blanco en modo de
destrucción
Imagen O
Gui contaminación
133
Imagen P
Patogeno de prueba
Imagen Q
Textura para las etiquetas
134
Imagen R
Textura de la célula
10 APÉNDICE C 3D Engine / Game Engine
¿Qué es un 3D Engine / Game Engine? Los 3D Engine o Game Engine son genéricamente conocidos como motores gráficos, son un conjunto de librerías necesarias para la creación de una aplicación multimedia, existen algunas opciones “open source” fácilmente obtenidas vía el INTERNET como Ogre3D, CrystalSpace, Irrlicht, Moon3D, etc. La diferencia de Game Engine y 3D Engine radica en la diversidad de librerías que se incluyen dentro del motor, generalmente un 3D Engine solo contiene librerías necesarias para rerendear, captura de modelos 3D y optimización, mientras que un GameEngine contiene rutinas de "rerendeo", audio 3D, física, IA, captura de modelos 3D y optimización.
La mayoría de los motores “open source” de la actualidad buscan ser independientes a la plataforma y proporcionar soporte a “scripting lenguajes” (como phyton, lua, ruby entre otros), la decisión de utilizar uno u otro motor queda al criterio y necesidad del programador. En este proyecto se decidió utilizar el 3D Engine Irrlicht por las características de portabilidad y funcionalidad.
Algunas de las rutinas de mayor complejidad de implementación utilizadas para la creación de AmorpheBios se mencionan a continuación.
Ø IAnimatedMesh: objeto que representa todo modelo 3D, este es cargado hacia la aplicación a través de la malla, a pesar de que el nombre indica mallas animadas se pueden contener mallas con un solo cuadro de animación, es decir estáticas, todo modelo 3D es una malla
Ø addAnimatedMeshSceneNode(..) VS addOctTreeSceneNode(...): cuando una malla a sido previamente cargada a la aplicación es momento de crearle un nodo para ser mostrado en escena, cada malla que desee ser desplegada requiere un nodo. Cuando las mallas son escenarios la instrucción alternativa de OctTree permite optimizar el re calculo de los vértices en cada ciclo de reloj intentando rerendear solo los elementos visibles de esa malla con las instrucción getPrimitiveCountDrawed(...) se pueden hacer una estadísticas
Ø draw2Dimage(...): función para la creación de GUI’s, se recurre a esta instrucción que puede incluir en sus parámetros elementos temporales para crear efectos de animación 2D
Ø draw(...): función que permite desplegar letras de BITMAPS
Ø ITriangleSelector: objeto mediante el cual se permite la detección de colisiones entre eventos del jugador y nodos
Ø CollisionResponseAnimator: objeto que representa un nodo con características de gravedad
135
y limite de recorrido
Ø addZipFileArchive(…): función para agregar un sistema de archivos a la aplicación, el sistemas de archivos es un comprimido ZIP que generalmente puede contener los elementos de audio, texturas, modelos, CUT-SCENES, etc
Ø makeColorKeyTexture(...): función que permite hacer la carga de texturas con transparencia, el formato que mejor soporta el .PNG
Ø createRotationAnimator(..): función que crea efectos simples de animación en nodos
Ø getSceneNodeFromScreenCoordinatesBB(...): función que permite obtener una colisión sobre un nodo a partir de la posición del ratón
Ø setDebugDataVisible(...) : función de depuración para obtener las fronteras de los nodos en un modelo de “caja”
136
11 BIBLIOGRAFÍA
Programming Game AI by Example Mat Buckland
Wordware Publishing 2005
Focus on SDLErnest Pazera
Premier Press 2003
C++ Programming for the Absolute BeginnerDirk Henkemans y Mark Lee
Premier Press 2001
OpenGL SuperBible, Second EditionRichard S. Wright, Jr. y Michael Sweet
Waite Group Press 2000
Game Design Theory and Practice, Second EditionRichard Rouse III
Wordware Publishing 2005
Game Design FoundationsRoger E. Pedersen
Wordware Publishing 2003
137