Erwin.Ried.cl / Desarrollos / Computación gráfica /
C++, OpenGL, Lagrange y ¡Chuza!

Puede que uses tu computador para entretenerte, especialmente con uno que otro videojuego. ¿Quieres conocer la "magia" que hay tras un sencillo videojuego de Bowling?, probablemente pienses en reformular tus críticas sobre pequeños detalles que ves en los juegos comerciales, especialmente cuando veas el trabajo que puede existir tras detalles tan pequeños como un simple pino de Bowling (23/11/2008 02:42 AM)


Lo primero es conocer nuestro entorno de trabajo. En este caso usaré C++, pero la versión de Borland (con su C++ Builder 6.0) en conjunto con OpenGL.

Para no aburrirlos con configuraciones, lo que necesitan para el proyecto es el entorno de Borland y el siguiente componente de OpenGL:

files/articles/cpp_bowling_001/opengl_panel.zip

Para instalar el componente, se debe copiar a la carpeta de Borland y configurar en "directorios" del proyecto la ruta correcta a la carpeta "OpenGLAPPanel" en donde fue descomprimida.

Algo interesante que trataré de conservar en el transcurso de este pequeño proyecto, será mantener las medidas reales (en lo posible). Una unidad en OpenGL será entonces un centímetro de la vida real, y así toda la escena y sus componentes serán diseñados a escala real. Siguiendo con esta esencia de realidad, se intentará realizar todo por medio de ecuaciones de descripciones absolutas e ideales, como por ejemplo curvas de contorno precisas para los pinos y el canal de la pista, ecuación del lanzamiento aplicando efectos (spin), fuerza de tiro y otras características.

Un punto destacable es que en el código y la interfaz de juego intentaré utilizar inglés como idioma base, por lo que los objetos mantendrán nombres como Bowling, Bowling Pin y otros similares con el fin de evitar equivocaciones implícitas en los nombres no anglosajones.


1. Diseño y clases

Es necesario organizar nuestro trabajo y que mejor, haciendo un diagrama de clases. En particular mi idea es que exista una clase genérica para todas las figuras y cada implementación particular de cada una la herede.

En pocas palabras, un pino, la bola, la pista de juego y el salón completo serán simplemente figuras y cuando yo le indique una acción (moverse, rotar, dibujarse, entre otras acciones) no me interesará en realidad a que figura estoy haciendo referencia:



En base, las figuras serán hechas por medio de ecuaciones para poder mantener una integridad visual ante diferentes situaciones. Se cuenta con la capacidad de poder generar objetos de baja definición para acelerar la visualización o de alta definición para cuando exista un acercamiento (por ejemplo a los pinos de la pista del usuario). Por medio de un parámetro podríamos generar un pino de baja resolución fácilmente:

Código:
Figure3d *figura = new BowlingPin([param1, param2, ..., paramN], BOWLING_LO_FI_SCENERY);



2. El pino de Bowling

Una de las partes más interesantes es el trabajo que apliqué al pino. Primero hay que considerar las medidas estándar de un pino:



Luego dibujo el contorno de la imagen, retocando las posibles fallas agregadas en la perspectiva del pino de la fotografía:



Usando la silueta y un programa de captura de pantalla adecuadamente configurado para reconocer los caracteres de la interfaz del programa de edición gráfica, capturo las coordenadas de todo el contorno a intervalos regulares, intentando obviar capturas en los puntos planos:



Así, obtengo un archivo de texto con todas las coordenadas del contorno de la silueta. De todas formas, aún es necesario ajustar los datos lo que se hace relativamente sencillo en una planilla de cálculo cualquiera.

Para simplificar la tarea de la búsqueda del contorno, haré una especie de conjunción de curvas bezier por medio de dos puntos extremos, en donde los nodos modificadores de cada curva de extremo será definido por un punto en común, es decir de una tradicional curva de bezier, uniré los puntos que modifican cada arista, calculando el polinomio por medio de una interpolación de Lagrange.

De esta forma nuestro contorno inicial se disgrega en un conjunto de curvas sencillas y acotadas, en efecto podemos notar algo del contorno al graficarlas las tres juntas (las que grafiqué fácilmente en Scilab):



Los puntos de las curvas mostrados en las imágenes nos sirven directamente para calcular las ecuaciones que quedan de la siguiente forma (en orden de izquierda a derecha, en el contorno):



Claramente en el programa, el contorno se define por una función que cohesiona las tres ecuaciones anteriores por medio de condiciones (en donde la solución de la incógnita es la misma) y retornando cero para valores fuera del alcance del pino real.

Ahora sólo queda utilizar este contorno y hacer un sólido de revolución. El secreto ahora es rotar los puntos y como si fuera una suma de Riemann, usar sólo trozos del contorno. La rotación debe realizarse manualmente, aprovechando los métodos de la estructura Point3d que permiten rotar un punto (no se puede ir creando una textura usando la rotación de OpenGL directamente, pues no se puede modificar la matriz de transformación de OpenGL con glRotated entre las instrucciones glBegin y glEnd). De esta forma la única forma fue añadiéndole la rotación a Point3d como puede verse en el diagrama de clases anterior.


3. La bola y la pista

La bola se crea simplemente con glutSolidSphere de la librería GLUT. No tiene mucha más ciencia.



Ahora, de forma similar a la del pino, la base para crear la pista de juego es un contorno especial, en esta ocasión de forma de extrusión y no como sólido de revolución. Siguiendo unas medidas adecuadas tenemos que el tablero es así:

Los laterales miden algunos centímetros más que la bola. En esta situación el contorno, antes de interpolar parábolas que generarán los mismos, se presenta así:



Con estos datos es fácil encontrar las dos formulas que generarán los contornos laterales para la pista:




4. El lanzamiento de la bola

En el bowling, el tiro tiene una particularidad. Debido a que el roce de la bola es relativamente despreciable al inicio de la pista (principalmente por la fuerza que lleva y el aceite de la pista) se produce un efecto casi siempre en el tramo final del trayecto.

Así entonces tenemos un tiro según el efecto aplicado a la bola, desde una vista superior, con el final de la pista en la zona del punto uno:



Así, podemos disgregar las características del tiro en una serie de parámetros que alterarán esas trayectorias. Para aclarar las cosas se definirán intervalos válidos de las variables:

Fuerza del tiro: Modificará la velocidad inicial a la que se le irá aplicando una fricción constante. Modifica la altura del punto dos de la trayectoria.



Efecto del tiro: Modifica la posición horizontal del punto uno en la curva de la trayectoria.



Posición inicial del tiro: Modifica la posición de los tres nodos de la trayectoria. Hay que considerar que la pista tiene 106 cms de ancho, en este caso la variable representa la posición desde el centro.



Dirección inicial del tiro: Modifica la posición del nodo uno y dos de la trayectoria, También, hay una relación directamente proporcional entre las dos posiciones nuevas de los nodos.



Luego de tener todos estos valores se puede confeccionar una ecuación de la trayectoria.

Debido a que en la naturaleza es casi imposible simular un fenómeno a la perfección, la solución en esta instancia es implementar un simplificado algoritmo para el tiro:

Primero que todo, la velocidad inicial del tiro está definida por una constante, la cual es reducida ligeramente en cada iteración del ciclo de actualización de juego (60 cuadros por segundo):



Esta fricción cinética simulada es atenuada por la fuerza de tiro, la cual modifica la velocidad de la bola en una manera extremadamente intuitiva, adjuntándose a la expresión anterior:



Ahora, el efecto del tiro (spin) sólo afecta el trayecto final de la bola. El impacto que produce sobre la trayectoria es una modificación de su posición en el plano horizontal que se ajusta a:



De esa manera, mientras más cerca de los pinos esté la bola en su trayectoria, más efecto tendrá, tal como se puede apreciar en tiros reales del juego.

La posición inicial del tiro es evidente, modifica sólo la posición horizontal en una instancia inicial y no vuelve a aplicarse.

La dirección inicial del tiro modifica el ángulo de salida del tiro de una forma también incuestionable:




5. Colisión de la bola con los pinos

Para las colisiones, se usa otra hebra de proceso, representada por otro “timer” que generalmente se encuentra inactivo. Al momento en que se detecta una colisión con un pino de Bowling, se registra el ángulo inicial de colisión y el programa sigue trabajando normalmente:



La verificación de la colisión inicial es sencilla. En el espacio euclídeo de juego, la comprobación sólo se basa en la distancia entre puntos centros de la bola con cada uno de los pinos (distancia euclídea), tal como recordamos de cursos de cálculo básico no es más que:



Ahora bien, ya tenemos claro cuando tocó la bola a un pino, sin embargo: ¿por dónde lo toco?

Este cálculo también es bastante simple:



Ahora, ¿cómo colisionan entre ellos?

Las colisiones siempre han sido un tema importante en computación gráfica y simulaciones físicas. De hecho simular un choque totalmente real sería prácticamente imposible. Desde un punto de vista simplificado, tenemos las posiciones de los pinos. Numerados según son posicionados por mi algoritmo:



Así, es curioso que podemos reducir el problema a un ámbito mucho más manejable:



Entonces, sólo manejaremos una colisión múltiple y posiblemente encadenada cuando el ángulo en que la bola golpee al pino verde genere un ángulo que produzca que uno de los pinos rojos caigan (los que a su vez podrían generar el mismo efecto de forma posterior).

Nota
Claramente este modelo de colisiones es poco preciso y sólo fue implementado así por un tema de tiempo. La idea es proponer a los lectores una idea global sobre la idea tras una colisión y no exactamente una solución.



6. Las texturas

Con formas básicas se puede dar una idea del ambiente, sin embargo si se quiere proporcionar una experiencia envolvente es necesario pulir los detalles y la mejor forma de hacerlo es mediante la incorporación de texturas.

Primero se necesita una base para extraer texturas y que mejor que de un lugar real de juegos como es el Bowling del Mall Curicó Center:



A continuación y a manera de documentación ejemplificaré la forma en que se fueron consiguiendo texturas de alta calidad sin bordes mal alineados ni problemas al repetirlas:

1) En este caso crearemos la textura para la pista. Partimos con la fotografía original capturadas desde una vista superior de la pista:



2) Para crear una textura liviana, elegiremos un segmento con el menor número de detalles e imperfecciones:



3) Preparamos la imagen para la parte final, la misma debe ser ajustada con un ancho y alto idéntico (en este caso 128 píxeles) y con sus características lo más simétricas posibles:



4) Con un filtro de “Offset” podemos retocar nuestro segmento:



La idea es imitar la función de repetición en mosaico que hará OpenGL, para así suavizar los bordes de la textura antes de aplicarla al juego. El resultado es siempre una textura excelente, con la cual incluso pintando a mano alzada obtendremos un buen resultado:




7. Código y ejecutable

Nota
Hay un problema con las normales de las figuras por lo que el juego puede verse de forma incorrecta en tu equipo, dependiendo de tu aceleradora gráfica.

Arreglarlo en este punto es largo y tedioso, y considerando que en mis equipos no se presenta el problema no tengo pensado corregirlo.


Código fuente (Borland C++ Builder 6.0)
files/articles/cpp_bowling_001/bowling_source.rar

Recursos (imágenes, planillas, diagramas usados):
files/articles/cpp_bowling_001/bowling_resources.rar

Capturas del simulador:




Binario (ejecutables y librerías requeridas):
files/articles/cpp_bowling_001/bowling_bin.rar


8. Conclusiones

El programa se desempeña correctamente, aunque faltó algo de funcionalidad para lograr un producto jugable, en general está, a mi parecer bastante completo y espero que sea de utilidad para cualquier persona que trate de crear su proyecto relacionado con computación gráfica.

Algo interesante es ver el Bowling en acción:



Al no basar mi código en trabajo ajeno, ni mis funciones en fórmulas enlatadas y copiadas, el mismo es fácilmente comprensible pues es exclusivo para este simulador.

Haga clic sobre una de las estrellas para calificar este artículo.

Opiniones y comentarios (Escribir un nuevo comentario)
oie este proyecto me gusyta para explicar algo demi carrera de ingenieria justamente me toco este tema me darias algunas sugerencias
Escrito por alma (04/11/2010 10:06 PM)
Lo primero es escribir bien, usando tildes y las letras correctas
Escrito por Erwin Ried (06/11/2010 01:40 PM)
hola erwin tengo problemas con el escritor de ecuaciones de mi hp 50g porque al trabajar en este si me funciona pero al salirme no me queda ningun registro y luego necesito estas para corregir y no me queda nada. bueno de antemano agradesco tu ayuda y gracias por ayudarnos y suerte
Escrito por magt (20/03/2009 02:12 AM)
¿Qué tiene que ver esta pregunta acá?
Escrito por Erwin Ried (21/03/2009 02:40 AM)
gran articulo, como siempre, tu web es de una gran ayuda para los que estamos empezando en la carrera de informática. yo ya pase a 2 :P gracias por compartir tus conocimientos saludos desde concepcion
Escrito por luchex (31/12/2007 03:52 PM)
Solo acotar que hubise sido bueno usar una herramienta gratuita además del magnifico OpenGL, DevC++. Buena reflexión sobre lo que hay detras realmente de los videojuegos, matemáticas y física.
Escrito por MAXIUM (23/12/2007 11:34 PM)
Cierto, aunque las ideas nunca serán restringidas por un entorno o herramienta en particular y mi idea principal es traspasar una idea y no un código
Escrito por Erwin Ried (24/12/2007 12:11 AM)
exelente ejercicio de programacion, muy buena idea
Escrito por Lucho (23/12/2007 09:40 PM)

Copyright © 2013 por Erwin Ried.