Transition to Boss - UQcsse3200/2024-studio-2 GitHub Wiki
Overview
The transition from the regular game to boss functionality includes the implementation of transitions for three specific bosses: Kanga (Land Boss), Leviathan (Water Boss), and Griffin (Air Boss).
The event starts from triggering the spawn of the respective boss, visual/audio effects during boss encounters, and ends with the pre-combat cutscene. Each boss has a unique transition with thematic elements based on their environment.
Kanga (Land Boss):
Rhythmic jungle-style drums, evoking the raw energy of the wild. The beat sets a tense yet primal tone, matching Kanga's powerful presence.
Audio: sounds/tension-land-boss.mp3
Leviathan (Water Boss):
Eerie soundscape creating an unsettling underwater tension. Haunting, deep reverberations echo through, giving the sense of a vast and mysterious creature lurking beneath the surface.
Audio: sounds/tension-water-boss.mp3
Griffin (Air Boss):
Sinister tone, with sharp, dark melodies that cut through the air. The ominous vibe intensifies the feeling of facing a swift and dangerous enemy from the skies.
Audio: sounds/tension-air-boss.mp3
Implementation
BossFactory
class
Starting with the boss creation in Each of the bosses are created, where they are assigned their unique tasks. They are initialized with AI Task Components like ChaseTask, LeviathanTask, and GriffinTask.
public class BossFactory {
public static Entity createBossNPC(Entity target, Entity.EnemyType type, BaseEnemyEntityConfig config) {
AITaskComponent aiComponent = new AITaskComponent();
// Add specific tasks for each boss type
if (type == Entity.EnemyType.KANGAROO) {
aiComponent.addTask(new ChaseTask(target, 10, 12f, 14f, new Vector2(configs.kangarooBoss.getSpeed(), configs.kangarooBoss.getSpeed()), true))
.addTask(new KangaJoeyTask(target, 9f, 2));
} else if (type == Entity.EnemyType.WATER_BOSS) {
aiComponent.addTask(new LeviathanTask(target, 10, 10f, 16f, 100f, 300));
} else if (type == Entity.EnemyType.AIR_BOSS) {
aiComponent.addTask(new GriffinTask(target, 10, 30f, 300, 100f));
}
.
.
}
}
...Task
component, methods are called to playTensionMusic()
and trigger health bar beat
Then in the ChaseTask
, LeviathanTask
, and GriffinTask
.
Implementations is quite similar for all three bosses in The only notable difference is in line AudioManager.playMusic("sounds/tension-land-boss.mp3", true);
where the audio path need to be change
@Override
public void start() {
super.start();
.
.
.
playTensionMusic();
this.target.getEvents().trigger("startHealthBarBeating");
.
.
}
/**
* Plays the tension music to enhance the experience during the chase.
*/
void playTensionMusic() {
// Play the music using AudioManager
AudioManager.stopMusic();
AudioManager.playMusic("sounds/tension-land-boss.mp3", true);
}
/**
* Stops playing the tension music and play the background music.
*/
void stopTensionMusic() {
// Stop the music using AudioManager
AudioManager.stopMusic();
// Get the selected music track from the user settings
UserSettings.Settings settings = UserSettings.get();
String selectedTrack = settings.selectedMusicTrack; // This will be "Track 1" or "Track 2"
if (Objects.equals(selectedTrack, "Track 1")) {
AudioManager.playMusic("sounds/BGM_03_mp3.mp3", true);
} else if (Objects.equals(selectedTrack, "Track 2")) {
AudioManager.playMusic("sounds/track_2.mp3", true);
}
}
@Override
public void stop() {
super.stop();
movementTask.stop();
stopTensionMusic();
this.target.getEvents().trigger("stopHealthBarBeating");
}
PlayerStatsDisplay
class, add listeners to detect the triggers mentioned
To start the health bar beating, in the // Add listener for kanga chase start/stop to trigger beating effect
entity.getEvents().addListener("startHealthBarBeating", this::startHealthBarBeating);
entity.getEvents().addListener("stopHealthBarBeating", this::stopHealthBarBeating);
Then calls the said methods
public void startHealthBarBeating() {
// Stop any existing beating actions
heartImage.clearActions();
vignetteImage.clearActions();
vignetteImage.setVisible(true);
heartImage.addAction(Actions.forever(
Actions.sequence(
Actions.scaleTo(1.0f, 1.05f, 0.3f), // Slightly enlarge
Actions.scaleTo(1.0f, 0.95f, 0.3f) // Return to normal size
)
));
vignetteImage.addAction(Actions.forever(
Actions.sequence(
Actions.fadeIn(0.3f), // Fade in for vignette effect
Actions.fadeOut(0.3f) // Fade out for vignette effect
)
));
}
public void stopHealthBarBeating() {
heartImage.clearActions();
vignetteImage.clearActions();
vignetteImage.setVisible(false); // Hide vignette when not beating
heartImage.setScale(1.0f); // Reset to normal scale
}
Testing Plan
Testing ensures that the functionalities being developed work as expected, which roughly includes:
- Triggering the boss spawn correctly
- Starting/Stopping audio/visual effects at the right time
- Transitioning into cutscene and combat works correctly
Code Coverage & Reliability Report
Code Coverage Summary:
- Line Coverage: 76.0% - This measures how much of the executable code has been tested. Uncovered lines are mainly tied to graphical rendering, where visual confirmation is more reliable than automated testing.
Bugs and Vulnerabilities:
- Bugs: 0 - No bugs have been identified in the code.
- Vulnerabilities: 0 - No security vulnerabilities were detected, ensuring the system is secure.
Maintainability:
- Code Smells: 7 - These refer to areas in the code that could be improved for readability, maintainability, or efficiency. However, they do not negatively impact the performance or functionality of the game.
Testing Plan
Visual testing, with captioning to explain: https://youtu.be/Ny-1nAlynto?si=SvrpFAjzTigmaW_O&t=25
https://github.com/user-attachments/assets/4553a3ba-251a-412c-804c-97092cabe9dc