Jordi Oña Rufí


Gameplay Programmer

OVERVIEW

In this project, I have been part (mainly) of the Player Programming Team. Together with the programmers Adrián Castillo and Daniel López, we have been in charge of implementing the player features like: character controller, player manager (change between characters), UI abilities manager...

On the other hand, I have made improvements and optimizations of our own engine, Culverin Engine, as we will see below.

ENGINE IMPLEMENTATIONS

Scripts compilation and serialization

Using the commands offered by Mono, we compile our recently created scripts into the engine. In this way, through the Windows console, we can visualize all the errors that happen both in compilation and runtime, with detailed information to speed up the solving process.

Once compiled, I proceeded to serialize the scripts base structure to store their variables, with their respective Names, Type and Values.

Geometry import cleaning

To optimize the iteration process of the game objects hierarchy, I implemented a small function that cleans all the dummy nodes (nodes without geometry or animation) of the imported model: all the nodes that contain the symbol "$" in their name are eliminated (characteristic symbol of empty nodes imported through Assimp).

Before cleaning nodes

After cleaning nodes

LOG System

Due to the lack of a debug system implemented in the scripting, I improved the LOG system integrated in the engine's own console that allows filtering the LOG's by departments (Player, IA, Stage, Physics). When marking the corresponding checkboxes, only those LOG's with the specific department tag will appear on the console. LOG's can also be of different colors to facilitate their visualization in runtime.

It's an expandable system: both Department and Color tags are modifiable, and we can add/remove them.

GAMEPLAY IMPLEMENTATIONS

BUILDING THE PLAYER

The main character Base

We can break down the character into a set of specific scripts that will be responsible for controlling its various functions: Movement Controller, Character Controller, Characters Manager

I was in charge of establishing the base of the controller of the main character (CharacterController script), which the player will be controlling in real time.

The base structure consists of a Finite State Machine that detects specific inputs to determine what action the character will perform. Each available action is associated to a specific state (IDLE, ATTACKING, BLOCKING, DYING...) limiting this way the actions the character can do (or not).

This script also manages the character base stats: Health, Stamina/Mana, Abilities (damage, cooldown time, energy cost) and acts as a bridge to link them to all the specific scripts that would require this information. Each ability is associated to a specific input that will trigger the action if the conditions are met (enough energy, ability not in cooldown, character in IDLE state).

Base Character Controller (1st Iteration)

Defining the three characters

This base structure is divided into three children scripts, which are the different characters that appear in the game: Jaime, Daenerys and Theon. I developed the Jaime's Character Controller script.

JAIME CONTROLLER:

  • LEFT ATTACK (Sword Slash combo): Jaime has a combined ability of three sword hits, which is performed if the player repeatedly attacks within a short period of time. It's a combo that can execute 3 different attacks, each stronger than the previous one. If the player fails a hit or receives a blow from the enemy, the combo resets.
  • RIGHT ATTACK (Block): it turns into COVERING state for a few seconds. If during this period of time he receives a blow, he will block it, avoiding receiving the damage.
  • SECONDARY ABILITY (Protector Shield): while we are controlling one of the other two characters, if we cast Jaime's secondary ability, we will activate a shield for a few seconds that will protect the character that we are controlling from the next enemy attack.

Left Attack

Right Attack

Secondary Ability

The other two main characters were developed by my teammates Adrián and Daniel. But I was in charge of the Theon Right Attack.

THEON CONTROLLER:

  • RIGHT ATTACK (Push): it activates the PUSH function (made by IA Department) of the enemy in front of the character

Managing the BEHIND characters

Once the base of the Players Manager script is created by my teammates, I managed to implement the code to keep updating the cooldowns and energy of the BEHIND characters (Left and Right positions) to add more dynamism to the gameplay.

WORKING WITH THE ENEMIES

Player - Enemy Interaction

I kept contact with the AI ​​department to manage the coordination between Enemy and Player (each one reacts as is due to the attack of the opponent by calling the specific functions [GetDamage(), FindEnemyInTile() ...] of each of the scripts, both the player and the enemy).

In the Movement Controller Script, I integrated a set of functions to detect if an enemy is in one of the tiles around you to block his movement and avoid getting inside him.

Enemies "Wait State"

To improve the gameplay, I integrated a function in the enemy base code to make him wait for the complete appearance of the next character (if one of his characters had died in combat), avoiding the player getting a hit without a chance to dodge or block.

ENVIRONMENT INTERACTION

To bring a touch of reality to the game, I integrated a collision detection for some of the attacks of the characters, making them react if they collide with walls or blocking enemies. Basically, a Raycast (developed by the Stage department) is thrown to collect the game object with which it collides and detects if its tag is "Obstacle". If this is the case, the character makes a variation of the attack ("Attack failed").

Together with Pere Rifà, member of the Stage Department, we implemented a script that activates a specific particle system at a specific location if the collision of the two collided objects are enabled. This works with:

  • Jaime Sword Attack: sparks particles are emitted when the sword collides with a wall or an enemy shield.
  • Daenerys Fire Explosion fire/explosion particles are emitted when the fire ball collides with a wall or an enemy.
  • Theon Arrows: another type of sparks are emitted when they collide with walls.
  • Blood: if an enemy receives damage by a non-fire attack, blood particles will be emitted from the enemy hit point

GOD MODE

For testing purposes, I was asked to develop a god mode for the player. We can activate the full god mode, or activate some of its parts separately:

  • NO DAMAGE: the character will perform the HIT state action normally, but without taking damage from any of the enemy attacks .
  • NO ABILITIES COSTS: the costs to perform any ability of any character becomes 0.
  • NO COOLDOWNS: reduces the cooldown time of secondary abilities to 1 second.
An extra feature is enabled if the complete GOD MODE is activated: GOD WALKABILITY (you can walk over the valyrian fire without falling).

HUD MANAGEMENT

We can observe that each character has its own characteristic elements of the HUD: ability buttons, character icon and family flags.

Abilities Controller

Each ability button (game object) has a script that manages the specific ability stats. It manages the Cooldown Time, when the ability is In Cooldown/Ready, and the Associated Ability Function to perform the actions of the character's specific ablity. Buttons can be activated in two different ways:

  • MOUSE CLICK: simply click on the button
  • KEYBOARD/GAMEPAD KEY: by pressing the specific key, we can simulate the clicked state of the associated button.
Apart from this logical structure, the script is responsible of the control of the visuals of the button. Thanks to the UI department, I use specific Radial Fill functions and a Text Component (time counter) to visually represent the cooldown of activated abilities (when a button is being pressed and the specific ability is activated, its cooldown starts: it becomes disabled and being filled radially until the cooldown time ends).

Changing Characters

At the top center of the HUD you can see the characters' icons in the order they are located (LEFT, CENTER, RIGHT). When you change between characters, using UI scripting functions, I change the position and scale of the characters' icons (to match the HUD with the new current team rotation) and the new current character's Abilities Container is enabled (the previous one is disabled).

Health and Energy Bars

The UI Department implemented scripts in the Health/Stamina/Mana bars objects to manage them. I associate these bars with each character to call the correct function at the specific moments of the gameplay to update them:

  • HEALTH BARS: when the player receives damage or is healed, we change the health bar fill value depending on the CURRENT character's health (value normalized from 0 [0 health] to 1 [max health]).
  • STAMINA/MANA BARS: when the player casts an ability, the fill value of the current character's stamina/mana bar is modified, depending on the ability cost (from 0 [0 energy] to 1 [max energy]).
When Changing Characters, the health/energy values are being stored to update the BEHIND characters' icons' bars and the CURRENT character's ones too.

THE "CUTSCENE" MANAGER

At the final level, just before entering the Boss Room, we find the problem that the player can cast ranged abilities against the boss before the fight starts. So we decided to implement a small cutscene where the player automatically enters the boss room, and then, the fight starts.

The system works as follows: when activating the lever that opens the boss's door, the player's state is changed to CUTSCENE, where he completly loses the control until the specific cutscene ends. A list of predefined actions begins to play, in order. These actions can be of 3 different types:

  • WAIT ACTION: the character won't perform any action for a specific time.
  • ROTATE ACTION: the character rotates towards the desired direction (left, right).
  • MOVE ACTION: the character moves 1 tile towards the desired direction (forward, backward, left, right).

AUDIO AND VISUAL FEEDBACK

In order to add more wealth and feedback, I have implemented a series of elements that fulfill this function.

Damage Feedback

Miquel Izquierdo created a shader that, given an alpha value, can modify the alpha of a blood sprite that appears on the screen. So, I developed a script that receives the current health of the current character, and if he gets hit by an enemy, it enables the render of the blood sprite, with the normalized alpha value (alpha value = current health / max health * 100). This texture is rendered for a few seconds

This is accompained with a heart beat sound effect (if the current health is lower than the 30% max health) that is reproduced in loop until the current character is healed or changed.

Jaime Sword Blood

I used another shader to change the alpha value of a secondary sword texture: every hit on an enemy increases the alpha value of the blood in the sword, and every failed hit decreases it.

Pool of Blood

I generated a prefab that contains a blood decal for the floor and a script to control the dimensions of the blood and the time of expansion. When an enemy dies, this prefab is instantiated at the position and its expanded, simulating a pool of blood (this is a GoT game, you know what I mean ;) ).

Combat Music and Sound Effects

The last (but not the least) aportation to the project I made was the implementation of the combat music into the game: when an enemy detects you, the ambient music changes to the combat music by calling the specific Audio function implemented in the Scripting System. This music state changes again (returning to the ambient music) when the enemy dies or loses the sight of you.

I also integrated the specific sound effects calls for every character action, like attacks, hits, breathing...

~ THAT'S ALL FOLKS! ~

Thank you for your attention