Sprint 4 Player Abilities - UQdeco2800/2021-studio-6 GitHub Wiki
Description
Alongside attacking, movement and dodging the player has an additional ability, which is an act the player can do, offensive/passive, as a last resort. This ability is triggerable with the "E" key and depending on the players settings triggers their ability including; a longer dash, temporary invincibility (alongside an optional non-state allowing for no ability). All abilities have a static long cooldown between instances of them utilising the ability.
Trigger System
Uses PlayerAbilitiesComponent which handles the cooldown and triggering of abilities is attached to the player entity in PlayerFactory. This component holds the players current ability and on the pressing of "E", grabbed in KeyboardPlayerInputComponent, triggers the current ability alongside handling the delay so the player is unable to use the ability until the delay is over.
Public Methods
void setAbility(Abilities ability): Sets the players ability to the given ability enum value
- NONE
- LONG_DASH
- INVINCIBILITY
Abilities getAbility(): Returns the current ability (as above)
Trigger Method
void triggerAbility() Triggered on the event "tryAbility", in turn triggers the correct event corresponding to the ability the player currently has selected.
Design Justifications
The ability code and cooldown are within a component class due to needing to be attached to the player in order to trigger the various abilities, which are based on functionalities achieved by other player components. Additionally, it was given its own class to ensure separation between elements, reduce complexity of the KeyboardPlayerInputComponent and as it generally did not logically incorporate into any other components.
The implementation of the abilities relies on event triggering in order to have as much separation between components as possible as the ability functionality effects multiple separate player components. This overall system also allows new abilities to be easily added and extended through adding them to the enum, then adding the event trigger to the trigger function.
The selection of abilities was done through an enum both to increase legibility of the code (as the initial implementation of integer codes was not easily parse-able) and to better align it with the code for items, as the ability selection mechanism will be similar to that provided through items and therefore it better prepares it for this implementation.
Considering Design Patterns
Ended up looking at design patterns when investigating how to trigger different abilities through one button, based on different settings. The most relevant pattern found was "State" which was focussed on changing behaviours based on internal state (all other semi-relevant patterns revolved around all state behaviours being interconnected/similar). The state pattern was not used as the number of states to be created was quite small (due to game balancing), the state determiner was through player selection and therefore only needed to be dependent on a single variable and the states were dissimilar enough that there was no significant code/behaviour duplication between them (other than the delay timer, but that was handled in a separate event triggering class).
Overall it was instead chosen to simply utilise the pre-existing functions of the observer patterns which allowed reduced dependencies while still allowing the multiple ability functions to communicate through the same key.
Enhanced Dash
On top of the players regular dash is an extended dash that can be chosen as their ability. It is implemented on top of the pre-existing Dash System within PlayerActions, simply utilising a second trigger function for the updateDash which will set the directional velocity to double the original and feed through the longer time specified in PlayerAbilities.
void longDash(long endTime) { dashEndTime = endTime; setDash(dashSpeed*2); }
Design justifications
By implementing it through the pre-existing dash system multiple classes do not jointly effect the players movement controls, removed some duplication code (especially as the same methods are used with different parameters/variable settings) and allowed the methods to be exclusionary to one another without communications systems on top of the pre-existing code.
Additionally, as there is no logical way to further extend the dash implementation without making the gameplay more redundant and effecting the game poorly, there was no issue with including the integration in the PlayerActions class as it would not need to be further extended to include other possible dashes.
Temporary Invincibility
The player will be able to select temporary invincibility as their ability. It is implemented on top of the pre-existing Invincibility System within PlayerCombatStatsComponent, simply utilising a trigger function for the invincibility event, which will set the length of invincibility to that provided in PlayerAbilitiesComponent.
Design justifications
By implementing it through the pre-existing system no additional overhead is to be applied to ensure the player is undergoing the correct behaviour and no additional code duplication needs to be added.
Fire Cracker
Fire cracker ability is slightly differently implemented in comparison to the 2 abilities listed so far. This is because it requires it to be able to damage enemies and at the same time have a different entity used because it is not attached to the player. It is however, done very similar to how player launching bullet which can be found here . It utilizes PlayerRangeAOEComponent.java
to launch fire cracker entity to a direction (that is based on player's most recent facing direction) with specified distance of 5 unit game length. In addition to what was already implemented with the bullets, fire cracker can only be thrown over specific objects. This brings an additional level of realism to the game where objects should not be able to fly over buildings but can fly over smaller objects like bushes. This is accomplished by introducing an additional layer which allows fire cracker entity to distinguish between what can be ignore and what cannot be ignored - this is accomplished with the FireCrackerCollisionComponent.java
. Upon launching, the fire cracker would start to tick and would explode after a few seconds, this is when the area of effect flaming damage would come into play and is accomplished with the update()
method within the FireCrackerCollisionComponent.java
class. Upon explosion, enemies within the vicinity will receive critical damage and after the explosion, enemies will receive normal damage every 2 seconds. This lasts for 6 seconds and the system would continuously keep track of the fire cracker ability AOE duration. Once the ability's duration is over, the entity is then edited back to its original state - ready for firing once again.
Design justifications
This gives users the ability to explore an ability a little more different to the previous abilities where user can inflict damage to enemies that has a bit of a flare to it which could further enhance user's experience further. More code was introduced because of its unique behavior since it needs to be able to distinguish between different layers and behave and change based on the collision in the game. In addition to that, it also has a timing and AOE after effect after explosion which is essential for such an ability.