Stamina and Mana System Code Implementation - UQdeco2800/2022-studio-2 GitHub Wiki
When modifying stamina and mana, please check the Player-Modification-Framework wiki page!!!
The stamina and mana system would be implemented in two parts. The actions of the player that would decrease the stamina and mana. And the ways of regenerating stamina and mana. The visualisation of the stamina and mana slot would be modified in the later sprint.
For sprint one, the stamina and mana system would be relatively simple. It would at least have one way to consume stamina and mana, and one way to regenerate stamina and mana.
Implemented by @whyhlf
public int getStamina() {
return stamina;
}
public void setStamina(int stamina) {
if (stamina >= 0) {
this.stamina= stamina;
} else {
this.stamina = 0;
}
if (entity != null) {
entity.getEvents().trigger("updateStamina", this.stamina);
}
}
public void addStamina(int stamina) {
setStamina(this.stamina + stamina);
}
public int getMaxStamina(){
return this.maxStamina;
}
public void setMaxStamina(int maxStamina){
if(maxStamina>=0) {
this.maxStamina = maxStamina;
}
else{
this.maxStamina = 0;
}
}
public void setStaminaRegenerationRate(int staminaRegenerationRate){
this.staminaRegenerationRate=staminaRegenerationRate;
if (entity != null) {
entity.getEvents().trigger("getStaminaRegenerationRate", this.staminaRegenerationRate);
}
}
public int getStaminaRegenerationRate(){
return staminaRegenerationRate;
}
The initialisation of the stamina and mana would be implemented in CombatStatsComponent.java . More functions would be added to handle with the value of stamina.
The negative input for regeneration rate is allowed, because the debuff effect would be implemented by other team in the later sprint.
Modified by @whyhlf
void dash() {
if(stamina >=20){
Sound attackSound = ServiceLocator.getResourceService().getAsset("sounds/Impact4.ogg", Sound.class);
attackSound.play();
this.dashDirection = this.walkDirection.cpy();
this.dashing = true;
this.dashStart = System.currentTimeMillis();
this.dashEnd = this.dashStart + DASH_LENGTH;
entity.getEvents().trigger("decreaseStamina", -20);
}
else{
this.dashing=false;
}
}
void teleport() {
if (mana>=40) {
entity.getEvents().trigger("decreaseMana", -40);
skillManager.startTeleport(this.walkDirection.cpy(), entity);
}
}
Add the trigger of event "decreaseStamina" in the dash() function. The if statement would determine whether the stamina is enough for a dash action.
entity.getEvents().addListener("getStamina", this::getStamina);
The stamina is get by call the getStamina function in the create() and update() functions.
Implemented by @whyhlf
void checkrest() {
if (System.currentTimeMillis() > this.restEnd) {
rest();
this.restStart = 0;
}
if (this.restStart == 0) {
this.restStart = System.currentTimeMillis();
this.restEnd = this.restStart + 1000;
}
}
void rest() {
if (stamina < maxStamina) {
entity.getEvents().trigger("increaseStamina", staminaRegenerationRate);
}
if (mana< maxMana) {
entity.getEvents().trigger("increaseMana", manaRegenerationRate);
}
}
Check whether the time has passed 1 second in the game. If it satisfies the condition, the player would regenerate 1 stamina point. This function would be called by update(). The staminaRegenerationRate variable would be got by the create() and update() from the function of CombatStatsComponent.java
@Override
public void update() {
checkrest();
updateSpeed();
}
The display of the Player Stats is handled in PlayerStatsDisplay.java
, this also has listeners, which are called in CombatStatsComponent
, that update the associated text and image to display the correct information based on the logic in checkImage
. It mainly uses addActors to display a table, this table is populated with three rows, health text & health bar, stamina text & stamina bar, mana text & mana image respectively.
Implemented by @whyhlf & @ew-b
private void addActors() {
// Creates a new table
table = new Table();
// Places table at top and to the left of the screen
table.top().left();
table.setFillParent(true);
// Sets padding of table
table.padTop(45f).padLeft(5f);
// Health text
int health = entity.getComponent(CombatStatsComponent.class).getHealth();
CharSequence healthText = String.format("Health: %d", health);
healthLabel = new Label(healthText, skin, LARGE);
// Stamina text
int stamina = entity.getComponent(CombatStatsComponent.class).getStamina();
CharSequence staminaText = String.format("Stamina: %d", stamina);
staminaLabel = new Label(staminaText, skin, LARGE);
// Mana text
int mana = entity.getComponent(CombatStatsComponent.class).getMana();
CharSequence manaText = String.format("Mana: %d", mana);
manaLabel = new Label(manaText, skin, LARGE);
// Adding health bar text and image to the table
table.row();
table.add(heartImage).size(120, 50).pad(10).left();
table.add(healthLabel).right();
stage.addActor(table);
// Adding stamina bar text and image to the table
table.row();
table.add(staminaImage).size(staminaWidth, 50).pad(10).left();
table.add(staminaLabel);
stage.addActor(table);
// Adding mana bar text and image to the table
table.row();
table.add(manaImage).size(60, 60).pad(10).left();
table.add(manaLabel).right();
stage.addActor(table);
}
By @ew-b
Junit tests for the functions implemented in CombatStatsComponent.java will be created.
Junit tests involving player initialization will be skipped at this stage.
Junit tests for playerStatsDisplay have been created, primarly testing checkImage
as testing UI functionality requires headless testing, which is beyond my comprehension - Elias.
The tests should detect if the input is out of range (<0 or > maximum). And the correct value should be reset to the component.
The test will check that the maximum stamina and maximum mana are set correctly and that the value cannot be negative.
The regeneration rate for stamina and mana may be negative, as the player may be debuffed during the game.
Run the game and check that the stats show whether the player's stamina and mana are displayed throughout the game.
In sprint2, the stats display about health bar(plunger), stamina bar(toilet paper roll) and mana bar (water bucket) were be implemented in the game.
public void updatePlayerHealthUI(int health) {
dispose();
ishealth = true;
heartImage = new Image(ServiceLocator.getResourceService().getAsset("images/PlayerStatDisplayGraphics/Health- plunger/plunger_"+checkImage(health), Texture.class));
addActors();
ishealth =false;
CharSequence text = String.format("Health: %d", health);
healthLabel.setText(text);
}
Firstly, all images would be loaded in the main screen texture. Then the relevant image would be displayed depend on the current status.
public String checkImage(int value){
String filename= "";
if (value ==100){
filename= "1.png";
}
else if(value >= 80 &&value< 100 ){
filename= "2.png";
}
else if (value < 80 && value >= 60){
filename= "3.png";
}
else if (value < 60 && value >= 40){
filename= "4.png";
}
else if (value < 40 && value >= 20){
filename= "5.png";
}
else if (value < 20 && value >= 10){
filename= "6.png";
}
else if (value < 10 && value >= 0){
filename= "7.png";
}
return filename;
}
All code that are related to the player's stamina, mana and health are having 0 code smell now. And test covering 90% of the code.