Tipo de proyecto:
Proyecto de la Universidad / Desarrollado en un equipo de 8 personas
Desarrollado en:
Unreal Engine 5.2 / Programado con Blueprints
Mi rol en el proyecto:
Programador general / Gameplay / Audio
El Tren inactivo
Apenas al iniciar el juego el Tren permanece inactivo, sin embargo, aún en este estado ocurren cosas interesantes en su interior, en este video de recorrido por el Tren se puede observar cada uno de los vagones, iniciando en la Cabina, recibiendo nueva información sobre el lugar mediante los altavoces que se encuentran a lo largo del Tren, así como las notas y carteles que explican su funcionamiento y como operar el Tren en este rejalado paseo previo al caos.
Uno de los aspectos más importantes de esta experiencia y del videojuego, es el sonido, el cual me encargué de configurar utilizando Sound Classes, en esta imagen está el Mix que controla a las clases de los diferentes tipos de audio en el juego, siendo SFX, Ambiente y Voz del jefe del Tren, los cuales se encargan de todos los objetos que emiten sonido en el juego de acuerdo a su categoría para que el jugador pueda modificar facilmente el volumen del juego únicamente alterando la salida de la Sound Class a la que pertenece.
Todos los eventos que ocurren en el Tren inician con el TimeManager, el cual primero busca a los Managers de otras funciones del Tren, y después inicia un Timer que cada segundo suma 1 a la variable de tiempo global, la cual se encarga de activar eventos en el Tren para cada uno de los vagones en los Managers, después de esto compara si el tiempo global es igual o mayor al tiempo necesario para ganar el juego sobreviviendo todo el recorrido del tren a su destino, y si esto se cumple hace inicia la secuencia del final, con un fade in del audio.
Por último se hace Play al audio final y al esperar 12 segundos se activa una pantalla en negro y una secuencia de cierre donde se muestran los créditos y detalles del equipo de producción del juego, al terminar el tiempo se reinicia el nivel y se vuelve a la primer escena.
Además de un TimeManager para los eventos, también existe el TrainManager, el cual controla la información del Tren como su estado y que eventos están ocurriendo en cada momento. Al iniciar busca a todos los Managers y objetos con los que se comunica en el BeginPlay, luego inicia un Timer donde compara el número de cosas rotas en el tren y si este es mayor a 0 multiplica la cantidad de cosas rotas para quitarle vida el Tren continuamente hasta que los problemas sean solucionados, mientras esto ocurre se actualizan los Manómetros del Tren los cuales indican su vida y por último si la vida del Tren llega a 0 se inicia la función de perder el juego.
La función PerderJuego inicia con un DoOnce para que no se ejecute múltiples veces y se sobreescriban sus acciones, después hace un fade out a todos los Sound Classes para apagar el sonido del juego y genera la transición a perder el juego, después de un tiempo reproduce un sonido y al pasar un Delay reinicia a la escena principal.
Cuando se cumple el tiempo para un evento en un Manager, este llama a una función específica dependiendo de que elementos controle, pasando un Bool para determinar si este problema reduce la vida del Tren o no, y un int que mide el nivel de alerta el cual se ve reflejado en otras partes del Tren como medidores y Manómetros, después se suma 1 a la cantidad total de cosas rotas en el vagón específico donde ocurrió esto, y si el Bool es verdadero se llama a la función de CosaSeRompe y cambia el estado del Manómetro de ese vagón, también estas funciones se pueden realizar a la inversa dependiendo de los valores que se envíen desde el Manager, pudiendo llamar a la función CosaReparada si las condiciones se cumplen.
Al entrar a las funciones CosaReparada o CosaSeRompe se resta o suma el total de cosas rotas, cuando se rompe algo se compara si el juego está en pausa, y si no lo está se reanuda el Timer que resta la vida al Tren, si algo se repara se realiza una comparación y si el total de cosas rotas es igual a 0 se pausa el timer que afecta el estado del Tren.
Por último existe otra función para perder el juego, que en este caso no es mediante la vida del Tren sino por un ataque de bandidos, al perder de esta forma se llama a la transición de perder el nivel después de un DoOnce y simplemente se reinicia a la escena principal después de un Delay.
Jugabilidad y mecánicas principales
La jugabilidad del juego se compone de diversos factores, la mayoría funcionales mediante el Grab de objetos que es escencial para la experiencia de juego, iniciando el Tren al jalar la cuerda, metiendo las Gallinas a sus jaulas, activando o desactivando los altavoces, rellenando la caldera de carbón, deteniendo un ataque de bandidos, etc. Esta jugabilidad se basa en reparar las fallas del Tren mientras van ocurriendo en los diferentes vagones, manteniendo su estado y obteniendo dinero para facilitar algunas de las tareas hasta llegar a tu destino.
Lo primero es iniciar el juego, tirando de la cuerda que se encuentra en la Cabina, al tomar la cuerda se inicia el Evento OnGrabbed, que activa la mano que agarra la cuerda detectando que mano es mediante el Motion Controller y reproduciendo el sonido de agarre, además inicia el Timer que controla el movimiento de la cuerda.
Si el jugador suelta la cuerda existe la función OnDropped, que pausa el Timer que controla el movimiento de la cuerda y desactiva la mano que está tomando la cuerda con el Motion Controller para reactivar la mano del jugador y si el juego está corriendo se reproduce un sonido al soltar el objeto.
El Timer de la cuerda inicia comparando la posición de la mano del Pawn del jugador con la cuerda, determinando la posición inicial y una relativa después mantiene estos valores mediante un Clamp y convierte esto en el nuevo Transform de la cuerda para moverla, después compara si esta bajó a cierta altura al ser tomado por el jugador y si esto es verdadero se quita la pausa y se inicia el Timer en el TimeManager para ahora si darle inicio al juego al reproducir el sonido de Chu-chu como el silbato del Tren.
Otra función imprescindible del videojuego es la opción de pausa, la cual se encuentra en una palanca de la Cabina, anclada al suelo hasta la altura de la mano del jugador, esta tiene el Evento OnGrabbed que inicia un Timer del movimiento de la palanca, y después realiza la operación para mostrar y ocultar la mano correspondiente del Pawn.
Al igual que los otros objetos estáticos con Grab, la palanca de pausa tiene el Evento OnDropped que pausa el Timer de su movimiento y realiza la misma operación de cambio de manos de manera inversa con la información del Motion Controller.
Para que el jugador pueda accionar la pausa el Timer compara la posición de la mano del Pawn con la de la palanca, obteniendo su rotación para crear una interpolación entre los dos valores para establecer una nueva rotación a la palanca mediante el cálculo de un Rotator, por último se compara si la rotación de la palanca llegó al limite para pausar el juego o reanudarlo, entonces mantiene la posición actual de la palanca estableciendo su valor máximo en ese sentido y llama a la función de PausarJuego o ContinuarJuego respectivamente después de una serie de Branch para determinar si el juego ya está en ese estado.
El volumen del juego es controlado desde la Cabina mediante 3 Switches que se pueden deslizar, cada uno asignado a una Sound Class que controla el nivel de audio de cada elemento en el juego, al iniciar el BeginPlay del Switch establece el volumen inicial en 1 para cada clase del Sound Mix.
La funcionalidad de cada Switch inicia al igual que otros controladores del Tren, mediante el Evento OnGrabbed inicia un Timer que compara la posición de la mano del Pawn con la del Switch y le hace un Clamp a la posición entrante en Z para después asignar ese nuevo Transform a la altura del Switch, luego realiza un Clamp a la nueva posición y asigna este valor al volumen de la Sound Class que controla, por último se compara si se llegó al punto máximo del Switch tanto arriba como para abajo y si alguno de estos dos se cumple se reproduce el audio correspondiente, ocurre lo mismo en el OnDropped del Switch que pausa el Timer y entra directamente a reproducir el sonido.
Siguiendo con la integración del UI como elementos 3D en el escenario del juego, los Manómetros son la mejor forma en la que el jugador puede revisar el estado del Tren en todo momento desde la Cabina o individualmente en cada vagón, cada Manómetro cuenta con una funcionalidad muy simple, al iniciar su BeginPlay establece la rotación de la aguja para mostrar el valor correspondiente, mientras que el Evento CambiarStatus es llamado por el TrainManager en cada momento para actualizar la información del medidor, en este Evento se hace un Clamp al valor entrante para la posición mínima y máxima de la aguja que se envía como la nueva rotación del indicador del estado del tren para el Manómetro correspondiente.
El jugador puede moverse libremente por el Tren en cualquier momento atravesando las puertas, las cuales debe tomar desde su perilla que inicia su función OnGrabbed tomando el Motion Controller y estableciendo un Timer antes de reproducir el sonido de la puerta, al iniciar el Timer compara si el juego está corriendo y después realiza la operación tomando la posición de la mano del Pawn y la de la perilla de la puerta para crear una interpolación y una rotación, luego de esto se ejecuta un Delay y se teletransporta al jugador al otro lado de la puerta, lo que hace el movimiento por los vagones sencillo pero interactivo.
Además de esto la puerta tiene el Evento OnDropped, que se ejecuta si el jugador suelta la perilla antes de que se cumpla el tiempo, aquí se pausa el Timer del movimiento y reproduce el sonido de soltar el objeto, por último tiene un Evento OnBeginOverlap el cual funciona para las Gallinas, que al acercarse se hace un Cast a la Gallina y esta es teletransportada al otro lado y después continúa con su movimiento random.
Eventos y managers
Uno de los eventos que más pueden afectar al jugador son las Luces, las cuales cada cierto tiempo se apagan en un vagón de forma aleatoria, entorpeciendo la visión provocando que el jugador pierda detalles de las cosas que ocurren o incluso le cueste moverse por el lugar, esta funcionalidad inicia con el Evento Timer que es llamado desde el TimeManager, el cual suma 1 al tiempo global e interno de cada Manager, después compara si este tiempo es mayor o igual al necesario para que ocurra un evento, y si esto es verdadero toma un número random y con un SwitchOnInt apaga la luz del vagón correspondiente seleccionado previamente, por último reinicia el tiempo y establece la rotación para la palanca asignada a cada vagón para indicarle al jugador que esta bajó, y por lo tanto la luz está apagada.
Cada palanca puede ser manipulada por el jugador individualmente para restaurar la luz en el vagón que ha ocurrido el problema, iniciando con el Evento OnGrabbed que inicia el Timer del movimiento y realiza el cambio de mano del Pawn a la posición de agarre de la palanca tomando el Motion Controller y ocultando la mano correspondiente.
El Evento OnDropped se activa cuando el jugador suelta la palanca antes de llevarla a una posición de encendido o apagado, aquí se pausa el timer del movimiento y se reactiva la mano del Pawn y se desactiva la mano de agarre en la palanca utilizando la información del Motion Controller.
El Timer de la palanca inicia comparando si el juego está activo, si esto es verdadero crea una interpolación entre la posición de la palanca y la mano del Pawn, para crear una nueva rotación a la palanca según el movimiento del jugador, después compara su valor de rotación y si este es igual al máximo o al mínimo mantiene la posición de la palanca y apaga o enciende las luces dependiendo si se subió o bajó la palanca.
La función de apagar y encender las luces es llamada por el movimiento de la palanca al llegar a su punto máximo o mínimo y el Timer principal, la cual apaga o enciende la luz del vagón que tiene asignado en el PostProcess, después cambia el Bool que indica si el estado de la luz y llama un Evento a la luz principal para reproducir el sonido.
Sin duda el Evento más peligroso de Trouble Train es el asalto de bandidos, iniciando desde el Manager que es llamado por el TimeManager cada segundo, sumando 1 al tiempo local que es comparado en un Branch, y si este es igual al tiempo límite se pasa a comparar si la cantidad cantidad de puertas asaltadas es menor a la total, obtiene una puerta random mediante una función y compara si esta puerta ya está siendo asaltada y llama al Evento PuertaRandom que recibe el Bool, por último si este es falso llama al Evento Asalto para la puerta seleccionada, reinicia el tiempo y aumenta la cantidad de puertas asaltadas.