Vídeo del proyecto

20 julio 2011

El proyecto ya ha sido evaluado (con una matrícula de honor). Os dejo un vídeo de como se ve en funcionamiento:

Últimos retoques

31 May 2011

Podría decirse que ya he terminado por fin:
-Eliminado que la pantalla se ponga rojiza al recibir daño de un enemigo ya que no ha sido posible conseguir que funcione correctamente.
-Añadidas animación al andar el enemigo. Se ha intentado añadir animaciones cuando ataca y muere, pero la memoria del teléfono no permite cargar ni un sólo keyframe más.
-Añadida vibración al disparar y al recibir daño.
-Añadidos sonidos de disparo y de golpe.

Con esto el proyecto está terminado, aunque aun quiero intentar encontrar una solución para la bajada de rendimiento en dos de los enemigos, que se mueven más lentos sin causa aparente.

El fin está cerca

26 May 2011

Estos días he hecho un montón de cosas:

-Al disparar a un enemigo se pone de color rojizo y reduce su vida un 25%, de forma que al perderla por completo se desvanece y pasado un tiempo reaparece en su posición inicial de nuevo.
-Al acercarse un enemigo a nosotros nos va reduciendo nuestra vida un 10% cada cierto tiempo, reflejándolo en el HUD. También he añadido un efecto rojizo a la pantalla cuando recibo daño, aunque aun da algunos problemas y tengo que perfeccionarlo. Al llegar la vida a cero la pantalla se vuelve negra y aparece un mensaje de Game Over.
-He replicado el único enemigo existente para tener varios en el mapeado. Esto ha supuesto un duro problema, y es que con tan sólo un segundo enemigo el juego colapsaba por completo y se quedaba congelado. Tras optimizar el código reduciendo cálculos innecesarios y optimizando los necesarios, he conseguido tener a tres enemigos en el mapa con una tasa de 15-20 frames. No es mucho, pero es jugable. Aun no sé la razón, pero el segundo y tercer enemigo, a pesar de ser copias del primero, se mueven mucho más lentos por el mapa. Es algo que tendré que intentar arreglar si le encuentro alguna lógica a este misterio.

El proyecto ya está practicamente terminado. Me falta intentar añadir animaciones, sonidos y vibración. He llegado también al límite de lo que me permite el sistema, ya que la aplicación carga en exceso al teléfono. Le daré un repaso para optimizarla, pero dificilmente podré hacer nada teniendo en cuenta la cantidad de recursos que utiliza.

¡Que alguien dispare a esos enemigos!

24 May 2011

Antes de nada, estuve probando «in situ» que los cambios de escala no afectaban al cálculo con la posición GPS. Malas noticias, había algún tipo de error. Tras comprobar los cálculos de las fórmulas de transformación, no encontraba problema alguno, pero pude ver que el desfase era constante, por lo que he añadido una corrección de posición a base de pruebas para solucionar el error.

Hora de hacer el HUD, necesario para empezar a recibir daño y dañar a los enemigos. Está compuesto por dos sencillos elementos, una imagen en el centro de la pantalla para el punto de mira y un icono de salud con la cantidad actual. Una vez colocados estos elementos… ¿por qué no probar a disparar a algún enemigo?.

Para disparar utilizo las pulsaciones del trackball del teléfono, de forma que al registrar una pulsación realizo una comprobación de colisión del vector al que apunta la cámara con el enemigo. Por desgracia parece que la función para esto no quería funcionar (algo que ya me pasaba cuando comprobaba si estaba en el campo de visión del enemigo, lo que me hace pensar que hay algo que no funciona bien con esa función, ya que no reconoce colisiones a grandes distancias). ¿Qué hacer entonces? hay un método que permite a partir de una posición y una dirección (como en el chequeo de colisión), comprobar la distancia mínima con un objeto según esos vectores. La comprobación es entonces sencilla, si en la dirección en la que estoy mirando hay algún enemigo, y la distancia es menor a la que me de el mapa en esa dirección, entonces es que estoy acertando con los disparos.

Con esto ya es cuestión de reducir la vida del enemigo con los disparos y hacerlo desaparecer al morir, a la vez que el enemigo debería reducir la vida del jugador a intervalos regulares cuando se encuentra pegado a él.

Un poco de inteligencia

20 May 2011

Con el enemigo ya en el escenario, falta ponerlo a andar. El comportamiento de los enemigos está construido como una máquina de estados, donde el enemigo está unos segundos quieto, para pasar a un estado en el que gira sobre si mismo un cantidad aleatoria y pasar a andar una corta distancia en línea recta antes de volver a empezar todo el ciclo. En este mecanismo hay implementado también una detección de colisiones para que el enemigo no atraviese las paredes del escenario.

Este comportamiento cíclico se interrumpe en un caso: cuando el jugador entra dentro del ángulo de visión del enemigo, momento en el que se encara con nosotros y empieza a avanzar en nuestra dirección en una persecución contínua, hasta pararse a una corta distancia de nosotros desde la que atacará. Se puede interrumpir este comportamiento haciendo que pierda contacto visual con el jugador.

Durante este trabajo he detectado un excesivo problema de clipping cuando los objetos están muy cerca de la cámara, aun cuando los valores para evitarlo ya estaban configurados en su máximo valor. La forma de solucionar este pequeño contratiempo ha sido aumentar la escala de todo el mundo y lo que contiene, así como corregir la altura de la cámara para eliminar este efecto de agrandamiento. Faltan realizar comprobaciones con el GPS para asegurarse de que no hay problemas a la hora de colocar correctamente al jugador, algo que no debería pasar con las correcciones realizadas.

El juego estará completo con poder disparar al enemigo, que nos pueda atacar y replicarlos para que haya varios de ellos. Lo demás serán pequeños ajustes para añadir un HUD, vibración, sonido y animar a los enemigos para que tengan cierto movimiento al andar y al atacar. Ya queda poco.

¡Una Teresiica salvaje apareció!

12 May 2011

Hace un tiempo que decidí poner a la mascota de la escuela, Teresiica, como enemigos. Ya hice y enseñé aquí un modelo 3D, pero tenía más de 3400 polígonos (aun sin triangular), lo que resultaba excesivo, es por ello que he realizado otro modelo mucho más sencillo que cuenta con poco más de 300 polígonos.

Una vez serializado el modelo ya he podido cargarlo en Android, con textura incluida. Ahora falta añadir varias copias y empezar a moverlos por el escenario persiguiendo al jugador y atacándole.

Adios escenario

11 May 2011

He estado varias semanas muy liado con muchas cosas y ahora toca ponerse a todo gas para terminar el proyecto a tiempo, por suerte no falta mucho. La semana pasada estuve hablando con mi director de proyecto para contarle lo que tenía y me faltaba y estuvimos hablando de como hacer que el escenario sea invisible pero que sirva como máscara de recorte para ocultar a los enemigos que hay tras él. En principio esto se hace con la funcionalidad «stencil» de OpenGL, que al parecer no está soportada por el motor gráfico que estoy utilizando. Menudo fastidio.

Pero no perdamos las esperanzas… si recordais cuando hablaba de las capas que componían cada frame, había una de fondo con la imagen de la cámara del teléfono, sobre la que se dibujaba la capa de OpenGL, que tenía un color de borrado con un valor alpha totalmente transparente. De ahí ha venido dos posibles ideas… la primera prueba ha sido hacer totalmente transparente el objeto que contiene el escenario, aunque no ha funcionado, pero si que añadía algo de transparencia a los objetos que había detrás… interesante. Viendo que un objeto transparente estaba provocando transparencias sobre objetos traseros, parecía claro que era posible utilizar eso para hacer esa especie de máscara de recorte que estaba buscando.

¿La solución? Si un color de borrado para el fondo con un valor alpha totalmente transparente permite ver la imagen de la cámara de la capa inferior de la aplicación, era lógico pensar que pintar un objeto con ese mismo color permitiría conseguir el efecto que estaba buscando. Creamos una textura de tamaño mínimo con valor alpha a 0, la aplicamos al escenario y arrancamos la aplicación… ¡Eureka! El escenario se comporta como una máscara de recorte en la que no se muestran los objetos 3D tras el mismo, pero si que se muestra la imagen que está capturando la cámara del dispositivo.

Ahora el escenario es invisible, de forma que será la propia imagen de la cámara del teléfono la que forme el escenario, con enemigos que aparecerán ocultos tras los edificios que capture la cámara, asomándose tras las esquinas… eso sí, siempre dependiendo de la precisión que de el GPS.

Poniendo cara al enemigo

29 marzo 2011

Cuando hice el prototipo con imágenes del proyecto los enemigos eran soldados. Ahora que ha llegado el momento de ponerme con los enemigos manos a la obra me ha surgido un problema, y es que las opciones para tener soldados así en el proyecto son dos:

-Consigo un modelo de un soldado por ahí y lo utilizo… algo que no me llama ya que prefiero hacer el juego por completo yo mismo siempre que sea posible.
-Modelo yo el soldado, algo sumamente complejo y que no se limita a modelar, sino también a realizar la textura.

Además de esto, existe otro problema. Meter varios modelos como esos, que tendrán un número de polígonos considerable, puede reducir tanto el rendimiento que sea totalmente imposible jugar en condiciones, al menos en el HTC Hero que estoy utilizando. Había que buscar otro enemigo, más sencillo de realizar y menos complejo en cuanto a carga del modelo.

Tras pasar bastante tiempo buscando y pensando posibilidades, de repente dí con la idea mientras estaba en un laboratorio de la universidad. En el fondo de pantalla estaba Teresiica, la mascota de la escuela, un personaje apropiado en contexto, sencillo, pero que tiene la suficiente complejidad para dar mucho juego y que podía ser perfecta. Ya de paso mato dos pájaros de un tiro, ya que estoy con una asignatura de diseño 3D en la que utilizamos Maya, y tenía que pensar en un proyecto que entregar como trabajo para aprobar ¡y el modelo de la mascota es perfecto para utilizarlo en ambos sitios!

Dicho y hecho, aquí está el resultado. De momento lo importaré así al proyecto, en la pose de referencia, para introducirle los patrones de movimiento que siga, que ataque, que reciba daño, etc… más adelante, cuando tenga esto, ya introduciré también las distintas animaciones. Quizás entonces tenga que modificar mucho de lo que haga ahora, pero prefiero no preocuparme por las animaciones de momento y dejar esas labores artísticas para más adelante.

Como curiosidad, en la asignatura de diseño 3D utilizaré el modelo para hacer una especie de sketch del estilo a los de los Raving Rabbids

Pequeños retoques

8 marzo 2011

Antes de ponerme con los enemigos he realizado algunos pequeños retoques relacionados con el escenario. Cuando cargué el escenario por primera vez algunas paredes no se veian correctamente debido a las normales de los polígonos, por lo que mediante culling pude solucionar esto. El problema ahora es que las normales afectan en el cálculo de colisiones, por lo que he tenido que editar el modelo del escenario para que las paredes de los edificios tengan sus normales hacia el exterior, como debe ser.

El otro pequeño arreglo consitía en situar la cámara a la altura correcta (1,70m), que hasta ahora estaba situada a ojo. Aun no se la razón por la que los desplazamientos en vertical dentro del proyecto no se corresponden a los cálculos esperados, por lo que he tenido que situar en el escenario un plano a la altura que debería estar la cámara y utilizarlo como referencia para colocar la cámara a la altura correcta. Para hacerlo nada más sencillo que hacer una relación de la escala a la que está el modelo, es decir, la correspondencia entre las unidades de las coordenadas del mismo y metros del mundo real (para lo que Google Earth puede ayudar muchísimo)

Colisiones

27 febrero 2011

Con la base en funcionamiento va siendo hora de transformar esto en un shooter. Lo más básico en un FPS es el disparar a donde estamos apuntando con la cámara, para lo que es necesario detectar si hay algún enemigo a la vista (al que dañaremos) en la dirección a la que estamos mirando. En este sentido el motor gráfico (JPCT-AE) ofrece posibilidades para calcular colisiones.

Para empezar a realizar pruebas he colocado un cubo en el escenario y utilizando el método checkCollision de la clase World para cambiar su color si estoy mirando hacia él o no. Este método toma un origen y un vector de dirección, junto a una distancia máxima, para detectar si se colisiona con algún objeto y cual es este. Para ello previamente hay que indicar que objetos podrán ser colisionados, en nuestro caso el cubo y el propio escenario (que puede ocultar el cubo). De esta forma, si el centro de la pantalla puede ver el cubo, se colorea de otro color (lo que identifica la colisión), mientras que si no estamos mirándolo o una pared bloquea la vista, seguirá de color blanco.

Este sistema permitirá, al disparar, detectar si hemos acertado a un enemigo y a cual en concreto para hacerlo desaparecer, reducir su vida, cambiar su animación… Además, servirá tambien para que al moverse los enemigos por el escenario, se impida que atraviesen los límites del escenario o que incluso no choquen entre ellos.