lunes, 11 de octubre de 2010

GAMEFEST 2010

music: COMBICHRIST mixing -"100%"-


El Documento de Especificación de Requisitos del Pong "sigue su cauce normal", así que cambio un rato de tema: hablemos de Gamefest 2010.

La verdad es que ha sido todo un éxito en lo que a asistencia de público se refiere y, al contrario que el supuestamente fallido S2e de 2003, este seguro que repite el año que viene.

Se respiraba en el ambiente un aire de profesionalidad, y mucho jolgorio; principalmente, yo me encontré a caballo entre el stand que Gamelab había instalado, asistiendo a las ponencias, y el montado por RetroMadrid. Por cierto... ¡al fin le eché mano a la recreativa Space Invaders de la gente de AUMAP!.


Y por el camino: volver a encontrarme con gente del sector del videojuego, y conocer alguna que otra persona nueva.

También pude ver (aunque no probar) la versión de Sniper Elite que han hecho para Wii, rifle de francotirador incluído.


Preguntas y respuestas rápidas:

¿Espectacularidad?. A raudales.

¿Novedades?. Aunque escuché algunos comentarios referentes a la escasez de novedades en el evento, no me pareció así; incluso cosas que no me esperaba ver, como la segunda parte de The Conduit y Dead Space.

¿Escena clásica?. Me equivocaba de todas, todas, creyendo que poco debía faltar ya por ver, y la exposición del stand de RetroMadrid me mostró de bruces dicha realidad.

Asimismo, espero que puedan verse el año que viene, en el stand de RetroWorks, los remakes de La Abadía del Crimen y Livingstone Supongo.

¿Kinect/Move?. Anécdotas curiosas, pero no sé si tendrán cabida en la clase de videojuegos que me interesan; supongo que tendré que echarle más imaginación al asunto...

¿S. Balmer?. No lo , no procede. :P

¿El Gamelab stand?. Bien, aunque sería deseable que en la siguiente edición de Gamefest pudiera situarse en un lugar más alejado, o poner mamparas aislantes de ruido, o algo por el estilo... pues el barullo del resto del evento dificultaba mucho la actividad del stand; aparte de la dificultad para seguir con atención las ponencias los micros se acoplaban mucho. Mención especial a la ponencia de motores gráficos del domingo, pero aquellos que teníamos interés en ella... ¡¡¡queríamos MÁÁÁÁÁÁÁÁÁÁS!!!.

¿Castlevania: Lords of Shadow?. Bien, muy chulo; si no le ponen una protección más estúpida de lo normal cuando salga en PC (como sucedió, por ejemplo, con la versión PC de Assasin's Creed II) seguro que me lo compro.

¿Freaks disfrazados?. Los justos y necesarios para darle la vida y el color necesarios que un evento así necesita, sin que se vuelva una parodia carnavalesca.

Y como colofón final, tras una divertida historia... ¡¡¡Runaway en pantalla grande!!!.

Hasta otra. :P

lunes, 20 de septiembre de 2010

Análisis y Diseño Orientado a Objetos con Aplicaciones

music: NINA HAGEN -"New York, New York"- / -"Wir Leben Immer... Noch"-


Otra de las cosas que he estado haciendo en estas últimas semanas ha sido repasar la teoría relacionada con el Modelo de Objetos, Análisis y Diseño Orientado a Objetos (desde ahora, AOO y DOO) y, en general, con Ingeniería del Software. Para ello me ha venido muy bien uno de los pesos pesados de dicha materia: el libro "Análisis y Diseño Orientado a Objetos con Aplicaciones", de G.Booch (ficha en Wikipedia); libro que he devorado con avidez e intensidad durante este tiempo.

Está dividido en tres partes:

  • Una primera, que describe las características inherentes del Modelo de Objetos (Clases, Objetos, características -Abstracción, Encapsulamiento, Modularidad, Herencia....-, tipos de relaciones entre clases /colaboraciones entre objetos, Parametrización de clases, Polimorfismo, etc.)
  • Una segunda parte en la que se explica una metodología de desarrollo Orientada a Objetos (desde ahora, OO) y la notación correspondiente para aplicarla. Destacar, en cualquier caso, la insistencia que se hace durante todo el libro de no ser el desarrollo de sistemas complejos algo que se pueda realizar mediante una perfecta guía o fórmula de recetario.
  • Una última parte en la que se estudian ejemplos de varios tipos de Sistemas OO, de diversos tipos, empleando la metodología adaptada para cada ejemplo. En esta parte ha resultado muy útil la creación de un pequeño guión /resumen para cada sistema, en el que se vayan enumerando en el orden en que aparecen cosas como tipos de diagramas que se emplean (según la fase de desarrollo), nuevas clases que van surgiendo, y nuevos métodos que se añaden a las clases.
Respecto a la implementación de dichos sistemas el lenguaje empleado es C++, pero no se olvida de otros lenguajes Basados en Objetos y OO como Smalltalk, Ada y CLOS, que son citados a menudo y se comparan sus características. De hecho, en el Apéndice se puede ver un resumen con una fichas de las características principales de los lenguajes citados y de alguno más.

Sin embargo, he encontrado en este libro un punto bastante negativo: la expresión, el lenguaje empleado al escribirlo. Demasiado rimbombante, demasiado sonoro. Como queriendo tapar algún tipo de hueco o carencia, o pretendiendo hacer más "grande" algo que es en realidad mucho más pequeño y sencillo. En mi caso, la alarma ha sonado varias veces cuando, tras haber visto un par de veces un determinado concepto X (me ha sucedido con varios) y quedarte literalmente igual, se llega a un tercer punto del libro en el que el autor comenta algo del tipo "...X, cuya explicación ya la habíamos realizado en el capítulo tal...". Ahí te paras y dices: "¡Eh, para el carro!. ¡¿Que dices que esto ya lo has explicado, en este otro capítulo?!. Pues yo me quedé igual...". He sentido en esos casos que no se empleara un lenguaje más llano, más directo, para expresar ciertas cosas.

Es en momentos como ese cuando he echado mano de "Software Engineering for Game Developers", de J. P. Flynt, un libro que sí emplea un lenguaje así, para comprender qué había querido decir Booch entre tanta frase etérea y floritura narrativa.

En resumen: un libro que, aunque engorroso de manejar en ciertos momentos, contiene una descripción muy completa sobre el Modelo OO, alguna que otra explicación muy interesante acerca del funcionamiento interno de C++, y varios ejemplos de los que se pueden sacar ideas y/o aplicar diseños adaptados a nuestras necesidades. Si además tienes a mano un libro de ayuda del que puedas tirar cuando notes que "suena la alarma"... recomendado. : )

Hasta otra. :P

miércoles, 25 de agosto de 2010

Objetos Producer-per-Platform

music: THE PRETTY RECKLESS -"Make Me Wanna Die"-

Durante todo este tiempo que he estado sin actualizar he estado realizando unos cambios a nivel de estructura interna del engine e incoporádole algunas cosillas. Una de ellas es la inclusión de una nueva clase de la que heredarán sucesivas clases hijas con las que se crearán un nuevo tipo de objetos: los Producer-per-Platform.

Un Producer-per-Platform es un objeto servidor, encargado de crear y entregar al objeto cliente objetos dependientes de plataforma. Entiéndase por plataforma una parte del sistema o el engine, normalmente situada en lo que llamaríamos "bajo nivel", que puede variar según nuestras preferencias o disponibilidad (S.O., Bibliotecas de creación de ventanas, de audio, gráficas, etc.). Según la clase a la que pertenezca el objeto Producer-per-Platform, éste creará unos u otros objetos "Product" (ventanas, render devices, audio devices, etc.). Y la clase concreta del Product que creará se decidirá, por directivas de preprocesador, en tiempo de compilación.

Debe aclararse, por tanto, que los objetos Producer-per-Platform (desde ahora, Producer) no son los dependientes de plataforma, sino los objetos product que crearán (desde ahora, Product).

La relación entre el Producer y el objeto cliente (desde ahora, Cliente) será de USO, y normalmente adoptará la siguiente forma:

0) El Cliente poseerá, como atributo privado, un puntero polimórfico de la clase de Product que el Producer debe crear.

1) La generación del Product se producirá dentro de un método del Cliente; en la implementación de dicho método el cliente poseerá, como objeto estático local, el Producer necesario.

2) El producer creará el product dependiendo de la directiva de precompilador actualmente establecida para ese Product (estará establecida en la propia implementación del Producer) y entregará el Product en el puntero polimórfico del cliente como valor de retorno.

3) La implementación del método finalizará, y el Producer quedará destruído. El Cliente tiene comunicación directa con el Product a través del interfaz de éste último.

4) La responsabilidad de ordenar la inicialización del estado del Product recae en el Cliente; éste será quien llamará al método Init del Product.

5) Asimismo, la responsabilidad de finalizar la vida del Product recae también en el cliente; éste será el encargado de destruir el Product, liberando la memoria que ocupaba.

Como puede intuirse un Producer NO ES UN MANAGER; es un concepto mucho más sencillo que el de un objeto Manager que carga recursos en memoria, lleva la cuenta de la cantidad de instancias (referencias) de recurso que hay empleadas en el sistema y, cuando el número de referencias de un determinado recurso llega a 0, elimina realmente dicho recurso de la memoria.

a) El Producer surge de la necesidad de crear objetos (Product) dependientes de plataforma. SOLAMENTE en este contexto tiene sentido el Producer. De saber a ciencia cierta que va a emplearse únicamente una plataforma el Cliente generaría el Product de forma directa, sin Producer.

b) Gracias a los Producer tendremos un mayor control sobre el engine sabiendo dónde hay establecidas directivas de preprocesador que determinan compilación para una u otra plataforma: en los módulos del los Producer.

He creado ya un Producer de ventanas que devuelve al Cliente (que en este caso es el Objeto Aplicación) una ventana creada mediante la biblioteca Win32. Ahora podría crearse una clase ventana creada mediante, por ejemplo, la biblioteca GLUT y el mismo Producer de ventanas creará y devolverá a la Aplicación una ventana creada mediante GLUT con sólo cambiar la directiva de precompilación en el Producer de ventanas (de crear ventanas Win32 a crear ventanas GLUT).

El siguiente paso en el que emplear esta técnica es en el render device. A ello voy.

Hasta otra. :P

martes, 25 de mayo de 2010

Probando nVidia PerfHUD

music: BLUE ÖYSTER CULT -"See You In Black"-

En estos días he estado probando nVidia PerfHUD (versión 6.62), un programa tipo profiler que puede ayudar a detectar cuellos de botella en el pipeline gráfico. Quiero ver si la caída en el framerate que comenté en la anterior entrada tuviera también algo que ver con un mal uso de Direct3D.

De momento no he tenido mucho éxito. Durante la instalación, se me indica que me van a ser actualizados los drivers de la tarjeta gráfica... el problema es que mi tarjeta está ahora mismo un poco anticuada y no pasa la prueba del logotipo de Windows con esos últimos drivers con lo que el asunto, como puede esperarse, no pinta muy bien. Y así ha sido: el programa se cuelga cada dos por tres, y el ordenador se ha quedado algo inestable hasta que le he vuelto a reinstalar los drivers anteriormente instalados.

Total, que voy a probar con una versión más antigua, a ver si así hay más suerte.

Hasta otra. :P

(** EDIT 31/05/2010 **) Ídem de ídem con la versión 5.2, y ya no se ven versiones más antiguas del entorno. Así que este asunto, al menos por el momento, así se va a quedar... :(

miércoles, 12 de mayo de 2010

Super Pong y el Modo Debug

music: WENDY O'WILLIAMS singing -"It's My Life"- / KISS -"Rock and Roll Hell"-

De vuelta al trabajo. Ya estoy dándole duro otra vez al Super Pong; de ahora en adelante voy a intentar actualizar más a menudo, como muy tarde cada dos semanas; aunque será como todo, dependerá de los progresos y cómo me cunda el asunto. : )

Durante la semana anterior he estado arreglando algunas cosas y haciendo que la información de los AABBs quede guarde como un centro y unos "radios" o Halfwidths en X,Y y Z; de esta manera, se guarda la mitad de la longitud (y no la longitud entera) en X,Y y Z del AABB, lo que ahorra tener que dividir entre 2 (o multiplicar por 0.5) en un montón de sitios dentro del juego. : )

He estado marcando objetivos y, entre ellos, está el hecho de crear algún tipo de sombra o proyección de la pelota contra las paredes del recinto, para que el jugador pueda hacerse una mejor idea de lo cerca que está la pelota de la raqueta suya. También voy a meterle algo de musica, aunque aún no he logrado crear el efecto cross-fading que me había planteado.

Sin embargo, sigo arrastrando todavía un problema "curioso": la diferencia brutal de rendimiento entre crear un ejecutable en Release y ejecutarlo separadamente del entorno de programación en Modo Pantalla Completa... y ejecutar el juego en Debug, dentro del entorno de programación(sea en Pantalla Completa ó en modo Ventana). Sigue sucediendo lo mismo: en modo Debug el rendimiento SE VA A PIQUE. Tal es la caida que no se puede llevar una partida con normalidad, lo cual hace muy difícil la depuración del código.
No sería tan importante si, estando en Debug, mantuviera un rendimiento aceptable en Pantalla Completa pues el asunto se resolvería mediante dos monitores (como en el trabajo: uno para tener a la vista el código, otro para ver la ejecución del juego). Pero no, es algo que he estado probando este fin de semana y se ralentiza igual.

El cuello de botella parece producirse en los componentes IA_NPC y LogicaPelota, posiblemente por las llamadas al componente Colision3D; es por ello que deseo modificar el sistema de Collision Detection and Response y hacer algo que sea más eficiente (aparte: solucionar los eventuales problemas con el tunnelling).

En fín, iré compaginando esto con las otras cosas que quiero hacer y veamos en qué acaba el asunto en las próximas semanas. Esta imagen lleva congelada demasiado tiempo.


Hasta otra. :P

jueves, 29 de abril de 2010

¿Seguridad en el cálculo ó Fallo en la programación?.

music: MOBY -"Natural Blues"-

Bueno, pues al fín terminé de vér cómo funciona el sistema de Collision Detection. Pero hay algo que no termino de enterarme, y no sé si lo están haciendo por seguridad ó es un bug de la demo. Anoto aquí la duda sobre el asunto, el cual explico resumidamente:

1-Por una parte tenemos 8 vértices, y tenemos que comprobar que alguno de ellos, está ó no dentro de un espacio cuadrado delimitado por cuatro vértices que están dentro de un plano. Para ello vamos a tener un bucle for que lo que va a ir haciendo es coger cada uno de dichos vértices (de entre los 8 a comprobar), hallar la proyección ortogonal de ellos sobre el plano, y comprobar si dicha proyección está ó no dentro del espacio cuadrado del plano. OK

2-En cuanto se demuestra que la proyección ortogonal sobre el plano de uno de estos 8 vértices está, además, dentro del espacio cuadrado, se procede a calcular la distancia existente entre el vértice y su proyección; si es aproximadamente 0, se considera que el vértice mismo está colisionando contra ese plano. Y además, se rompe el bucle for y no se siguen comprobando el resto de los vértices. También OK.

3-Hasta aquí, todo bien. El asunto es que al citado bucle for de los 8 vértices lo engloba un bucle infinito; si se cumple todo lo del paso 2, se incrementará un contador... ¡PERO PERMANECEREMOS DENTRO DEL BUCLE INFINITO!. En la siguiente iteración de dicho bucle infinito NO se pasa a evaluar otro grupo de 8 vértices, sino los mismos; no se cambia de plano (ni de su correspondiente espacio cuadrado, sigue siendo el mismo). Con lo cual volverá a evaluarse y volverá a salir, digo yo, EL MISMO VÉRTICE; se volverá a incrementar el contador, se rompe el bucle for de los 8 vértices, volvemos a entrar en el bucle infinito...

4-...y así, hasta que el valor almacenado contador sea mayor que 20, y ahora sí, salimos del bucle infinito. Momento en que, si bien los 8 vértices van a ser los mismos, se toma un nuevo plano (el cual tendrá su correspondiente espacio cuadrado definido por cuatro vértices que están dentro de él) y se pasa al punto 1.

OK, pero... ahí está la duda: hasta llegar al punto 4 ,hemos realizado el proceso explicado en el punto 3... ¡¡¡20 VECES!!!. Y lo que no llego a ver es si esto algo que se desea realizar de esa manera por alguna razón (quizás por seguridad, para evitar posibles errores de punto flotante, o lo que sea)... o es directamente un fallo en la programación.

Pero bueno, ahí se va a quedar la cosa; ya me enteraré otro año.

Hasta otra. :P

viernes, 23 de abril de 2010

No eran proyecciones, sino ecuaciones de planos...

music: COPTIC RAIN -"Barefoot / Perfect Lie"-

Estos días los he pasado averiguando cómo funcionaba el sistema de C0llision Detection de la famosa demo de los Donuts, algo en lo que me había quedado encasquillado en otra ocasión... pero esta vez he tenido más éxito.

El problema radicaba, principalmente, en el enfoque. Mientras veía el funcionamiento del método encargado de realizar la Colission Detection estaba entendiéndolo como una serie de proyecciones de cada uno de los vértices del Bounding Box del primer objeto (aquel que realiza la Collision Detection con el resto de objetos) sobre las normales de las caras del Bounding Box del "segundo objeto (en cada caso, éste último será el objeto digno del análisis de Collision Detection por parte del primer objeto; cabe destacar que Objeto 1 siempre será distinto de Objeto 2).

Bajo esta perspectiva la explicación "casi funcionaba", pero me fallaba algo: no comprendía cómo con una simple resta del vértice actual del Objeto 1 sobre lo que yo consideraba "la proyección de él mismo" sobre la normal de la cara actual del Objeto 2 hallábamos ya la proyección de dicho vértice actual sobre la cara actual del Objeto 2.

La solución ha venido de la mano del libro "Real-Time Collision Detection", del cual ya puedo decir que ha merecido la pena el dinero invertido aunque sólo sea por esto (no obstante, espero tener más razones aún en el futuro). :P

Como preliminares:

1) Volví a repasar algo el tema de vectores, recordando un elemento clave: un vector representa una magnitud, dirección y sentido... pero NO posee dirección.

2) Volví a ver las ecuaciones del plano, y las propiedades asociadas a dichas ecuaciones.

A partir de aquí, lo ví claro: lo que verdaderamente se estaba haciendo NO era proyectar sobre las normales... sino hallar el punto más cercano de cada vértice del Bounding Box del Objeto 1 a cada una de las caras del Bounding Box del Objeto 2, tratando dichas caras como planos mediante la ecuación del plano:

n · X - d = 0, siendo:

--> · la operación Producto Escalar,
--> n, la normal de la cara actual del Objeto 2,
--> d = n · P, tal que P sea un punto perteneciente a la cara actual del Objeto 2.

Dicho punto más cercano, si prefiere verse así, puede verse directamente como la proyección del
vértice actual del Bounding Box del Objeto 1 sobre la cara actual del Bounding Box del Objeto 2.

Desde aquí:

-Si a dicho punto más cercano lo llamamos R y al vértice actual del Bounding Box del Objeto 1 lo llamamos Q,

-Y si tenemos en cuenta que las normales de los Boundings van a estar normalizadas...

... la cosa queda así: R = Q - [(n · Q) - d]n <-- Esta es la citada resta, ahora sí teniendo sentido, que comentaba más arriba; esto es lo que verdaderamente se hace en la demo.

Y ahora sí: una vez hallado ese punto más cercano a Q, R (o esa proyección de Q, R, si prefieres verlo así), se comprueba que se encuentra dentro de los límites de la cara actual del Bounding Box del Objeto 2; si lo está, se puede decir "con la boca pequeña" que ambos objetos están colisionando; si no, debe proseguirse con el análisis.

Pues ya quedan poquitas cosas de las que quería ver de esta demo. Tengo que ponerme a realizar un recuento de objetivos a realizar para Super Pong.

Por cierto, todo esto me ha dado una idea acerca de algo que tenía ganas de hacerle: poder proyectar puntos, líneas o algo así desde la posición de la pelota hacía las paredes del recinto para que el jugador pueda hacerse una mejor idea sobre la distancia a la que se encuentra la pelota de la raqueta, que dada la cámara a veces no sabes muy bién dónde está.

Hasta otra. :P