Boss Room Dialogue System - UQcsse3200/2024-studio-1 GitHub Wiki

Overview

The Boss Room Dialogue System is a crucial component of our game that enhances boss encounters by implementing dynamic health-based dialogue triggers and enemy summoning mechanics. This system transforms boss fights into engaging, narrative-rich experiences that adapt to the player's progress.

The core idea is to create boss encounters that evolve as the fight progresses, keeping players engaged through contextual dialogue and increasing challenge. As the boss's health decreases, it triggers various events such as taunting dialogue and spawning of additional enemies.

Key Features

  1. Health-based Dialogue Triggers: The boss initiates context-sensitive dialogue at specific health thresholds (75%, 50%, and 25%), adding personality and narrative depth to the encounter.

  2. Dynamic Enemy Summoning: Additional enemies are spawned when the boss reaches 50% health, increasing the challenge and variety of the fight.

  3. Adaptive Boss Behavior: The system is designed to be easily expandable for more complex behavior changes based on boss health.

  4. Seamless Integration: The system integrates smoothly with existing dialogue, combat, and room management systems, ensuring a cohesive gameplay experience.

Class Structure

classDiagram
    class Component {
        +create()
        +update()
    }
    class RenderComponent {
        +draw(SpriteBatch batch)
    }
    class EnemyRoom {
        +spawn(Entity player, GameArea area)
        +removeRoom()
    }
    class BossHealthDialogueComponent {
        -float[] healthThresholds
        -Random random
        -CombatStatsComponent combatStats
        -int currentThresholdIndex
        +create()
        +update()
        -showRandomDialogueAndPause()
        -getRandomBossDialogue(int index): String
        -spawnRandomAdditionalEnemies()
    }
    class BossRoom {
        -NPCFactory npcFactory
        -GameArea area
        -Entity player
        -Entity stairs
        +spawn(Entity player, GameArea area)
        +spawnRandomEnemies(String enemy)
        -getRandomPosition(): GridPoint2
        +removeRoom()
    }
    class DialogComponent {
        -NameComponent nameComponent
        -ShapeRenderer shapeRenderer
        -GlyphLayout layout
        +create()
        +showDialog(String newText)
        -completeDialog()
        +dismissDialog(): boolean
        +draw(SpriteBatch batch)
    }
    Component <|-- BossHealthDialogueComponent
    EnemyRoom <|-- BossRoom
    RenderComponent <|-- DialogComponent
    BossHealthDialogueComponent --> CombatStatsComponent: uses
    BossRoom --> NPCFactory: uses
    BossRoom --> GameArea: uses
    DialogComponent --> NameComponent: uses

Sequence Diagram

sequenceDiagram
    actor P as Player
    participant BHD as BossHealthDialogueComponent
    participant BR as BossRoom
    participant D as DialogComponent
    participant ABS as AlertBoxService

    activate P
    P ->> BHD: Damage Boss
    activate BHD
    BHD ->> BHD: update()
    
    alt Health threshold reached
        BHD ->> BHD: getRandomBossDialogue()
        BHD ->>+ ABS: confirmDialogBox()
        ABS ->>+ D: showDialog()
        D -->>- P: Display Dialogue
        
        alt 50% health threshold
            BHD ->>+ BR: spawnRandomAdditionalEnemies()
            activate BR
            BR ->> BR: getRandomPosition()
            BR -->> P: Spawn Additional Enemies
            deactivate BR
        end
    end
    
    P ->> D: Dismiss Dialogue
    activate D
    D -->>- BHD: Resume Game
    deactivate BHD
    deactivate P

Detailed Component Breakdown

BossHealthDialogueComponent

The BossHealthDialogueComponent is the core of the Boss Room Dialogue System. It's responsible for monitoring the boss's health and triggering appropriate responses.

Key methods:

  • create(): Initializes the component, getting references to necessary components like CombatStatsComponent.
  • update(): Called every frame to check the boss's health and trigger events if thresholds are reached.
  • showRandomDialogueAndPause(): Selects and displays a random dialogue message, pausing the game.
  • getRandomBossDialogue(int index): Selects a random dialogue message based on the current health threshold.
  • spawnRandomAdditionalEnemies(): Triggers the spawning of additional enemies when health reaches 50%.
public class BossHealthDialogueComponent extends Component {
    private final float[] healthThresholds = {0.75f, 0.5f, 0.25f};
    private final Random random = new Random();
    private CombatStatsComponent combatStats;
    private int currentThresholdIndex = 0;

    @Override
    public void create() {
        combatStats = entity.getComponent(CombatStatsComponent.class);
    }

    @Override
    public void update() {
        if (currentThresholdIndex >= healthThresholds.length) {
            return;
        }

        float healthPercentage = (float) combatStats.getHealth() / combatStats.getMaxHealth();

        if (healthPercentage <= healthThresholds[currentThresholdIndex]) {
            if (healthThresholds[currentThresholdIndex] == 0.5f) {
                spawnRandomAdditionalEnemies();
            }
            showRandomDialogueAndPause();
            currentThresholdIndex++;
        }
    }

    // Other methods...
}

BossRoom

The BossRoom class extends EnemyRoom and is responsible for managing the boss encounter environment.

Key methods:

  • spawn(Entity player, GameArea area): Sets up the boss room, including spawning the boss and stairs.
  • spawnRandomEnemies(String enemy): Spawns additional enemies during the fight.
  • getRandomPosition(): Generates a random position within the room for spawning entities.

DialogComponent

The DialogComponent handles the rendering of dialogue on the screen.

Key methods:

  • create(): Sets up the rendering components.
  • showDialog(String newText): Initiates the display of a new dialogue.
  • draw(SpriteBatch batch): Renders the dialogue box and text on the screen.

Visual on the Screen

boss-dialogue

Implementation Details

Health Monitoring

The BossHealthDialogueComponent continuously monitors the boss's health in its update() method. It compares the current health percentage to predefined thresholds:

float healthPercentage = (float) combatStats.getHealth() / combatStats.getMaxHealth();
if (healthPercentage <= healthThresholds[currentThresholdIndex]) {
    // Trigger events...
}

Dialogue System

Dialogue is triggered at specific health thresholds. The system uses a 2D array to store dialogue options for each threshold:

private String getRandomBossDialogue(int index) {
    String[][] dialogueOptions = {
        {
            "Your looks hurt more than your attacks.",
            "If I had a nickel for every time you missed… I'd have a lot of nickels.",
            // ... more options ...
        },
        // ... more thresholds ...
    };

    return dialogueOptions[index][random.nextInt(dialogueOptions[index].length)];
}

The DialogComponent then renders this dialogue on the screen, character by character for a typewriter effect.

Enemy Summoning

When the boss's health reaches 50%, additional enemies are spawned:

private void spawnRandomAdditionalEnemies() {
    GameAreaService gameAreaService = ServiceLocator.getGameAreaService();
    if (gameAreaService.getGameArea() instanceof GameController) {
        GameController area = (GameController) gameAreaService.getGameController();
        if (area.getCurrentRoom() instanceof BossRoom bossRoom) {
            String[] possibleEnemies = {"Dog", "Snake", "rat", "bear", "bat", "dino", "minotaur", "dragon"};
            int numberOfEnemies = determineNumberOfEnemies();
            for (int i = 0; i < numberOfEnemies; i++) {
                String enemy = possibleEnemies[random.nextInt(possibleEnemies.length)];
                bossRoom.spawnRandomEnemies(enemy);
            }
        }
    }
}

The number of enemies spawned depends on the game's difficulty level.

Testing

The system is thoroughly tested using JUnit and Mockito. Key test cases include:

  1. Dialogue triggering at correct health thresholds (75%, 50%, 25%)
  2. No dialogue triggering above thresholds
  3. Enemy spawning at 50% health threshold
  4. Correct random dialogue selection

Example test:

@Test
void testDialogueTriggeredAt75PercentHealth() {
    when(mockCombatStats.getHealth()).thenReturn(74);  // Just below 75% threshold
    component.update();

    verify(mockAlertBoxService, times(1)).confirmDialogBox(
            eq(mockEntity),
            anyString(),
            any(AlertBoxService.ConfirmationListener.class)
    );
}

⬅ Back to Animal Overview