Combate
El combate no es tanto un sistema discreto, sino uno más abstracto: se trata de la interacción compleja de varios sistemas diferentes trabajando juntos, y la complejidad de la implementación depende mucho de la complejidad del diseño.
En este juego, el diseño es muy sencillo. El jugador tiene una forma de atacar: saltar encima de un enemigo. Los enemigos tienen dos formas diferentes de atacar al jugador: cuerpo a cuerpo y por contacto, dependiendo del tipo de enemigo.
Para el ataque del jugador y el ataque cuerpo a cuerpo del enemigo, los fundamentos son casi los mismos. Hay colocadas una o más cajas de colisión en la malla esquelética del personaje según cómo pueden atacar cuerpo a cuerpo, además de una o más cajas de daño para hacer una aproximación de la zona que queremos que admita prueba de impacto.
En cuanto al ataque por contacto del enemigo, usamos su cápsula de colisión para comprobar si el jugador ha entrado en contacto con ella y ejecutar las mismas acciones de impacto que usamos para el ataque cuerpo a cuerpo. Puedes ver la implementación de lo que ocurre cuando un personaje es golpeado en nuestra clase base de personaje aquí: Parrot\Source\Parrot\Public\Character\ParrotCharacterBase.h. La lógica funcional se encuentra aquí y en las subclases ParrotPlayerCharacter.h y ParrotEnemyCharacterBase.h.
El personaje jugable
La configuración para el jugador tiene un sistema de funcionamiento propio a la hora de atacar a un enemigo. Cuando el jugador se superpone con la caja de daño de un enemigo, el enemigo proporciona esta información al jugador para preguntar si el ataque era válido. En este caso, comprueba si el personaje está sobre la parte superior de la caja de daño para garantizar que el jugador aterriza desde arriba y que no golpea desde los costados o desde abajo. Si el ataque es válido, el enemigo da la señal al jugador para realizar un salto. Si el jugador mantiene presionado el botón de saltar al momento de hacer contacto con la caja de daño, el salto será más alto. Si se suelta antes de hacer contacto con la caja de daño, el salto será más bajo.
El personaje enemigo
La configuración para el enemigo es un poco más complicada por varios motivos. Queremos que los ataques cuerpo a cuerpo se vean realistas, así que las cajas de daño del enemigo se encuentran en los filos de sus armas. La configuración de cajas de colisión, cajas de daño y cápsula de colisión puede verse en el visor de un blueprint de personaje enemigo, como el que vemos aquí: Blueprints > Enemy > Skeleton > BP_EnemyCharacter_Skeleton.
En este ejemplo, puedes observar la caja de daño en la cabeza, la caja de colisión en la espada y la cápsula de colisión. Cada uno de estos activadores impulsa sus eventos de solapamiento a las funciones base en la clase base del personaje.
Además, las animaciones de ataque envían eventos de notificación que solo habilitan la caja de colisión del arma durante la parte de la animación en la que se blande la espada. De esta forma, se ve y se siente como si el jugador estuviera en verdad siendo golpeado por la espada y no solo entrando en contacto con un enemigo y recibiendo daño en un momento cualquiera. Estas notificaciones de animación se insertan en la animación de ataque en puntos específicos para activar la caja de daño y luego desactivarla. Puedes ver las notificaciones de animación en Blueprints > Enemy/EnemyBase > BP_AnimNotify_EnemyAttackBegin y Blueprints > Enemy > EnemyBase > BP_AnimNotify_EnemyAttackEnd con la configuración de la animación de ataque de un personaje enemigo específico, como Assets> Quaternius > PirateKit > Characters > Headless_Skeleton > Animations > Characters_Skeleton_Headless_Anim_CharacterArmature_Sword.
El personaje enemigo es el que comprueba si hay solapamiento y activa los eventos, esto significa que el enemigo activa tanto su función HitCharacter() como la función HitCharacter() del jugador cuando se detectan solapamientos adecuados.
Puedes ver el código que actúa sobre el solapamiento de la caja de colisión y caja de daño aquí: Parrot\Source\Parrot\Public\Character\ParrotEnemyCharacterBase.h en las funciones HitBeginOverlap() y HurtBeginOverlap().
Combate de jefe
Para nuestro combate de jefe, existe una funcionalidad adicional cuando el jugador golpea al jefe para reproducir una secuencia de "ira". Puedes ver el código de blueprint que activa una respuesta del jefe aquí: Blueprints > Enemy > BossShark > BP_EnemyCharacter_BossShark.
Las secuencia de "ira" es una secuencia temporizada sencilla que reproduce una animación telegrafiada “sacudir cabeza” antes de incrementar la velocidad de marcha del jefe y habilitar un componente de Niagara de llamas verdes para VFX. Durante esta secuencia, también desactiva la caja de daño, por lo que el jefe es invencible.