# Tecnologías multimedia e interacción/Curso 2016-2017: Caso 8

En esta sección trata sobre el caso 8 de la asignatura (Shoot'em up con control vía webcam), que consiste en el diseño y desarrollo del videojuego titulado "Unnamed Space" haciendo uso de Unity3D y OpenCV.

## Descripción del juego
### Concepto y características

El juego Unnamed Space consiste en un shoot ‘em up con ambientación espacial en el que el jugador se hace con el control de una nave espacial con la que debe hacer frente a distintas hordas de enemigos. La principal particularidad de este juego respecto a otros con la misma temática es que además del clásico control por teclado el jugador puede controlar la nave mediante controles gestuales usando su mano haciendo uso de la webcam del ordenador.
El juego cuenta con gráficos 3D mostrados por una cámara fija que nos da una vista del entorno desde arriba. Dicho entorno consiste en un espacio limitado por los extremos de la ventana de juego dentro del cual se desarrollan todos los eventos. La única variación que se produce en dicho entorno son los obstáculos y enemigos que van apareciendo dentro del espacio jugable por la parte superior de la pantalla.
La principal característica en cuanto a jugabilidad (gameplay) consiste en la posibilidad de controlar la nave mediantes gestos con la mano haciendo uso de la webcam del ordenador. Este apartado se explica con más detalle más adelante, en la sección "Sistema de control".

### Género

Este juego pertenece al género de los shoot 'em up, un género de videojuegos en los que el jugador controla un personaje u objeto solitario, generalmente una nave espacial, un avión o algún otro vehículo, que dispara contra hordas de enemigos que van apareciendo en pantalla. Popularmente se los conoce también como matamarcianos o marcianitos.
También puede clasificarse dentro del subgénero fixed shooter, donde se incluyen juegos que constan de niveles cada uno de los cuales cabe en una sola pantalla, el movimiento del protagonista está fijado a un único eje, y los enemigos atacan en una única dirección (descender desde la parte superior de la pantalla o apareciendo por los laterales).

### Plataformas compatibles

Al estar desarrollado con Unity el juego es compatible con plataformas Windows, macOS y Linux.

### Influencias

Las principales influencias se basan en clásicos shoot ‘em up de naves como son Space Invaders o R-Type. En cuanto al control gestual con la mano, se toman como referencia juegos de la plataforma Kinect de Xbox o juegos como Eye Toy, de PlayStation 2.

## Gameplay y mecánicas

El objetivo principal del jugador en Unnamed Space es aguantar el máximo tiempo posible destruyendo naves enemigas para conseguir una mayor puntuación.
Para lograr este objetivo el jugador debe ir eliminando las oleadas de naves enemigas que se le vayan apareciendo antes de que la suya sea destruida. También aparecerán ocasionalmente lluvias de asteroides en cuyo caso el jugador podrá optar por esquivar o destruir las rocas, siendo más recomendable desintegrar el mayor número posible de ellas para obtener una puntuación más alta en la partida así como para obtener distintos items.
En cuanto a las mecánicas implementadas se pueden consultar con detalle en el documento de diseño del juego.

## Implementación

Para el desarrollo del proyecto se ha utilizado OpenCV para aplicar los algoritmos de visión artificial y reconocer los gestos del jugador, el lenguaje de programación C# y el motor Unity3D para desarrollar un juego que sirva como muestra o demo.

### Tecnologías empleadas: OpenCV y Unity3D

* OpenCV es una biblioteca libre de visión artificial originalmente desarrollada por Intel. Desde que apareció su primera versión en 1999, se ha utilizado en infinidad de aplicaciones. Desde sistemas de seguridad con detección de movimiento, hasta aplicaciones de control de procesos donde se requiere reconocimiento de objetos. Esto se debe a que su publicación se da bajo licencia abierta, que permite que sea usada libremente para propósitos comerciales y de investigación con las condiciones en ella expresadas. OpenCV es multiplataforma, existiendo versiones para GNU/Linux, Mac OS X y Windows. Contiene más de 500 funciones que abarcan una gran gama de áreas en el proceso de visión, como reconocimiento de objetos (reconocimiento facial), calibración de cámaras, visión estérea y visión robótica.
* Unity3D es una de las plataformas para desarrollar videojuegos más completas que existen. Permite la creación de juegos para múltiples plataformas a partir de un único desarrollo, incluyendo juegos para consola (PlayStation, Xbox y Wii), escritorio (Linux, PC y Mac), navegador, móviles y tabletas (iOS, Android, Windows Phone y BlackBerry).

### Hand Motion Controller

La arquitectura interna del juego se divide en dos partes: por una parte tenemos el HandMotionControler, que encarga del reconocimiento de gestos de la mano con la cámara, y por otra parte tenemos el propio juego desarrollado con Unity. Una representación gráfica de la arquitectura lógica se puede encontrar en el siguiente enlace: http://i.imgur.com/YADQZpO.png

#### Gesture Recognition

Esta es la clase principal del proyecto Hand Motion Controller, la cual se encarga de detectar la posición de la mano y la cantidad de dedos levantados. Esta clase utiliza EmguCV que es un wrapper de OpenCV para C#. Para la detección, se realizan llamadas a las funciones de procesamiento de imágenes de OpenCV.
* Captura de imagen. Se hacen llamadas a bajo nivel invocando a OpenCV para que inicialice la cámara del ordenador y empiece a capturar imágenes para posteriormente procesarlas.
* Detección de la posición de la mano. Se efectúan algoritmos de sustracción de fondo, desenfoque gaussiano y thresholds para detectar el cambio de la región de interés.
* Detección de los dedos de la mano. Se efectúan algoritmos de sustracción de fondo, desenfoque gaussiano y thresholds para detectar el cambio de la región de interés.
* Guardar datos de detección en memoria dinámica. Se guardan en memoria dinámica y a tiempo real la posición de la mano (coordenadas X e Y) y el número de dedos levantados. Estos datos serán de acceso público por cualquier otra clase utilizando una API diseñada para tal propósito.

#### Gesture Input Controller

Esta es la clase que se encarga de proporcionar la configuración para la detección de la posición de la mano y la cantidad de dedos levantados para la clase Gesture Recognition y además se encarga de proporcionar el acceso a los datos de detección obtenidos por el juego. En otras palabras, se encarga de inicializar todas las fases de Gesture Recognition, las ejecuta y por último, envía los datos de detección recogidos por OpenCV al juego.
Por cada Gesture Input Controller debe existir un Gesture Recognition y varios Gesture Input Controller no pueden utilizar el mismo Gesture Recognition.
* Configurar preferencias de detección. HMC posee unos parámetros de configuración para mejorar la detección en determinados escenarios. Gesture Input Controller permite configurar dichos parámetros desde el propio editor de Unity. Además, cada Gesture Input Controller puede tener diferentes parámetros configurados por lo que se pueden situar cámaras en diferentes sitios, configurarlas adecuadamente y poder utilizarlos simultáneamente y a tiempo real sin problemas en el juego. Una posible aplicación para esta característica sería la posibilidad de tener varias cámaras colocadas por una habitación para cada jugador y permitir el multijugador local utilizando diferentes Gesture Input Controller. Las preferencias de detección son:
** Camera ID: establece el identificador de la cámara a utilizar. OpenCV utiliza un número entero desde el 1 para identificar cada cámara conectada al equipo. De esta forma, se pueden utilizar varias cámaras en un mismo juego.
** Num Cycles Finger Change: velocidad de refresco de la detección del cambio del número de dedos levantados.
** Min Area: tamaño mínimo de la mano que se supone que hay que detectar.
** Max Area: tamaño máximo de la mano que se supone que hay que detectar.
** Width Prop: proporción en la anchura de la imagen capturada por la cámara que debe ser tenida en cuenta para la detección.
** Height Prop: proporción en la altura de la imagen capturada por la cámara que debe ser tenida en cuenta para la detección.
** X Margin Multiplier: ajusta el margen de la imagen capturada por la cámara en la coordenada X.
** Y Margin Multiplier: ajusta el margen de la imagen capturada por la cámara en la coordenada Y.
** Refresh Multiplier: velocidad de refresco de los datos de detección. Cuanto menor sea este parámetro, con mayor velocidad se irán obteniendo nuevos datos de detección pero se introduce más carga para el ordenador.
* Exponer API para el acceso a los datos de detección. Gesture Input Controller expone un conjunto de métodos que pueden ser accesibles desde otras clases del proyecto para poder obtener fácilmente los datos de detección captados por Gesture Recognition.
** GetDetectedFingerNumbers devuelve el número de dedos levantados detectados en las imágenes captadas por la cámara.
** GetHandPosition devuelve las coordenadas X e Y de la mano detectada en las imágenes captadas por la cámara.
** GetAxis(String axis) funciona de forma similar al Input.getAxis(...) de Unity. Los valores admitidos en el parámetro axis son: Horizontal, Vertical, RelativeHorizontal y RelativeVertical.

#### Player Input Controller

Esta es una clase genérica que cualquier juego debería implementar para el movimiento del jugador. Hand Motion Controller requiere que exista al menos un Player Input Controller que se encargue de obtener los datos de detección a través del Gesture Input Controller para poder procesarlos y saber qué hacer con ellos. Esta clase sería la encargada de, por ejemplo, mover el jugador cuando la persona mueve la mano o disparar un misil cuando se levanta un dedo.
Por cada Player Input Controller debe existir un Gesture Input Controller.
* Llamar a la API para el acceso a los datos de detección. Para que la clase pueda obtener los datos de detección, tiene que hacer llamadas a la API expuesta por Gesture Input Controller. De esta forma, se puede acceder tanto a la posición de la mano (coordenadas X e Y) como al número de dedos levantados.
* Obtener datos de detección. Al hacer llamadas a cada método de la API expuesta por Gesture Input Controller, esta clase va a ir obteniendo los datos de detección recopilados por OpenCV pero tratados para poder ser utilizados de forma sencilla en el juego.
* Procesar datos de detección. En esta etapa, se deben procesar los datos de detección obtenidos en las etapas anteriores para desencadenar acciones. Por ejemplo, si la mano se mueve a la derecha, que el jugador se mueva a la derecha. Gesture Input Controller sigue un esquema de tratamiento de datos similar a la clase Input de Unity (existe una función getAxis(...) igual a la función getAxis(...) de Unity, donde se puede poner el eje a utilizar (Horizontal o Vertical) y este devolverá un valor comprendido entre -1 y 1).

## Integración

La integración de HMC con cualquier juego es bastante sencilla. Basta con clonar el proyecto desde el repositorio oficial y trasladar la carpeta correspondiente dentro de la carpeta Assets del juego. Cabe destacar que se debe elegir entre una de las dos carpetas que se encuentran en el repositorio de acuerdo si contamos con un sistema de 32 o 64 bits. Posteriormente, habría que añadir un Gesture Input Controller y un Player Input Controller a la entidad que debe ser manejada por el jugador utilizando los gestos. Desde el panel de la derecha podemos modificar ciertos parámetros para mejorar la precisión del sistema.

## Repositorios

El código fuente del juego se encuentra almacenado en dos repositorios de Github, uno corresponde al código del propio juego, y el otro al control gestual.
Se recomienda además la consulta del documento de diseño completo del juego, del que ha sido extraído todo el contenido de esta página de forma resumida y que contiene información más extensa sobre el diseño y las mecánicas así como imágenes, capturas de pantalla y detalles del control.