Help Menu - UQcsse3200/2024-studio-2 GitHub Wiki

Overview/Description

The Help Window in the Main Menu UI component is a feature designed to assist players by providing them with detailed instructions and information about the game. It offers a series of slides that cover various aspects of gameplay, ensuring that players can navigate and understand the game more effectively. Here’s a breakdown of its features:

Features:

Multi-Slide Structure: The Help Window contains multiple slides, each dedicated to a different topic. The window initially loads with seven predefined slides, each focusing on a different aspect of the game:

  • Movement: Instructions on how to move the player character.
  • Combat: Guidelines for engaging in combat and using various combat mechanics.
  • Storyline: An overview of the game's storyline, providing context and narrative background.
  • Minigames: Information on the Snake minigame
  • Minigames1: Information on the Birdie Dash game
  • Minigames2: Information on the Underwater maze game
  • Stats: Details on how to manage and interpret player stats within the game. Navigation Controls:

Previous/Next Buttons: The window includes buttons to navigate between slides. Players can move back to the previous slide or forward to the next slide as needed.

Keyboard Support: The window supports keyboard inputs (LEFT and RIGHT arrow keys) for easier navigation through the slides.

Resizable and Movable Window: The Help Window is both resizable and movable, allowing players to adjust its size and position on the screen for better readability and convenience.

Close Button: A close button (X) is available to exit the Help Window, returning the player to the main menu without affecting their progress.

Slide Visibility Management: The system ensures that only one slide is visible at a time. As players navigate through the slides, the current slide becomes visible while the others remain hidden.

Dynamic Positioning: The window is centered on the screen upon opening, ensuring that it’s easily accessible and in focus.

Implementation Details:

  • Customizable Appearance: The Help Window uses the game's skin for a consistent look and feel. The background and layout are set up using LibGDX’s Window and Table classes, allowing for a clean and organized UI.

  • Interaction with Game Events: The Help Window is triggered by a "Help" button in the main menu, and it’s integrated with the game's event system, allowing for seamless interaction between the help content and other game components.

  • User Input Handling: It includes an InputListener to handle user inputs, which ensures that keyboard navigation is smooth and intuitive.

Key features (in-depth explanation)

Multi-Slide structure

The Help Window consists of multiple slides, each dedicated to a specific gameplay aspect. These slides are represented as separate classes within the Slides class, making it easy to organize and manage different topics. The slides are dynamically added and managed within a Table container, allowing for organized and flexible content presentation. For example:

public static class MovementSlide extends Table {
    public MovementSlide(Skin skin) {
        Label titleLabel = new Label("Movement Instructions", skin, "title");
        Label contentLabel = new Label("Here are the instructions for movement...", skin);

        add(titleLabel).padTop(20f).expandX().center().row();
        add(contentLabel).padTop(20f).expandX().center().row();
    }
}

Each slide, such as the MovementSlide, is a subclass of Table and is populated with relevant Label widgets that contain the instructions or information. This approach encapsulates each topic into a distinct, manageable component.

Navigation controls

The Help Window provides Previous and Next buttons to navigate through the slides. Additionally, keyboard support for LEFT and RIGHT arrow keys allows players to switch slides without using the mouse. For example:

previousButton.addListener(new ChangeListener() {
    @Override
    public void changed(ChangeEvent event, Actor actor) {
        if (currentSlide[0] > 0) {
            slideInstances[currentSlide[0]].setVisible(false);
            currentSlide[0]--;
            slideInstances[currentSlide[0]].setVisible(true);
            slideTable.clear();
            slideTable.add(slideInstances[currentSlide[0]]).expand().fill();
        }
    }
});

This listener ensures that when the Previous button is clicked, the previous slide becomes visible, while the current slide is hidden.

Resizable, movable and dynamic window

The Help Window can be resized and moved by the player, offering flexibility in how it is viewed. This feature is particularly useful on different screen sizes or when the player needs to access other parts of the interface while reading the help content.

final Window helpWindow = new Window("Help", skin);
final float DIALOG_WIDTH = Math.min(1200f, Gdx.graphics.getWidth() - 100);
final float DIALOG_HEIGHT = Math.min(800f, Gdx.graphics.getHeight() - 100);
helpWindow.setSize(DIALOG_WIDTH, DIALOG_HEIGHT);
helpWindow.setResizable(true);
helpWindow.setMovable(true);

By setting the window as resizable and movable, it allows the player to adjust the Help Window to their preferred size and location. Furthermore, the size of the window is made dependent on the screen size, which is obtained by Gdx.graphics.getWidth() )and height), hence ensuring comparability with both fullscreen and windowed mode.

The Help Window is centered on the screen when opened, ensuring it is prominently displayed, adjusting on both fullscreen and windowed mode.

helpWindow.setPosition(
    (stage.getWidth() - helpWindow.getWidth()) / 2,
    (stage.getHeight() - helpWindow.getHeight()) / 2
);

This code snippet calculates the position to place the window in the center of the stage, making sure it is visually balanced.

Close button

A close button (X) is included to allow players to exit the Help Window easily. This button is placed in the top-right corner of the window.

TextButton closeButton = new TextButton("X", skin);
closeButton.addListener(new ChangeListener() {
    @Override
    public void changed(ChangeEvent event, Actor actor) {
        helpWindow.remove();
    }
});

This listener removes the Help Window from the stage when the close button is clicked, effectively closing it.

Design decisions

Encapsulation and Modularity: (Why not nested methods for slides)

The slides within the Help Window, such as MovementSlide, CombatSlide, etc., are implemented as inner classes within the Slides class. This decision promotes encapsulation, keeping all related slide components together in one file. This modular approach makes the code more organized and easier to maintain since all help-related content is centralized. By grouping these slides under a single Slides class, the design follows the principle of cohesion—keeping similar functionalities together. Each slide shares a common purpose (providing help information), and their close proximity in the codebase reduces the likelihood of errors and makes future modifications straightforward.

public class Slides {
    public static class MovementSlide extends Table...
    public static class CombatSlide extends Table...
    .
    .
    .
    public class <whatever slide> extends Table...
}

Each slide class is a self-contained unit with all the code necessary to display its content. This encapsulation ensures that changes to one slide do not inadvertently affect others. Adding a new slide is straightforward. Simply create a new class following the existing pattern. This modular approach keeps the codebase organized and reduces the risk of introducing bugs when expanding the system.

Testing

Test Cases

Test cases for help button

Movement Slide

The Movement Slide class extends Table and provides a UI slide for movement instructions in the help menu. It includes:

  • Title Label: Displays "Movement Instructions."
  • Content Label: Provides instructions to move the dog using WASD keys.
  • DogActor: A custom actor representing a dog, which responds to WASD key inputs and moves within the slide's boundaries.

Constructor

Initializes the labels and sets up the dog actor with a texture.

public MovementSlide(Skin skin) {
    Label titleLabel = new Label("Movement Instructions", skin, "title");
    Label contentLabel = new Label("Move the dog with WASD keys!!", skin);

    add(titleLabel).padTop(20f).expandX().center().row();
    add(contentLabel).padTop(20f).expandX().center().row();

    dogActor = new DogActor(new Texture(Gdx.files.internal("images/dog2.png")));
    addActor(dogActor);  
}

DogActor Class

Attributes:

  • Texture: Represents the dog's image.
  • Drawable: Used for rendering the dog actor.
  • Position: Managed by dogX and dogY.

Constructor: Initializes the texture and drawable, and sets the actor’s size.

public class DogActor extends Actor {
    private Texture texture;
    private Drawable drawable;
    private float dogX, dogY;

    public DogActor(Texture texture) {
        this.texture = texture;
        this.drawable = new TextureRegionDrawable(new TextureRegion(texture));
        setSize(texture.getWidth(), texture.getHeight());
 }
}

act(float delta) Method:

Updates the dog’s position based on user input.

@Override
public void act(float delta) {
    super.act(delta);
   handleInput(delta);
setPosition(dogX, dogY);
}

draw(Batch batch, float parentAlpha) Method:

Renders the dog actor

public void draw(Batch batch, float parentAlpha) {
    drawable.draw(batch, getX(), getY(), getWidth(), getHeight());
}

handleInput(float delta) Method:

Handles input for movement and checks boundaries to keep the dog within the visible area.

    // Initialize position if it's the first time act is called
    if (dogX == 0 && dogY == 0) {
        dogX = getX();
        dogY = getY();
    }

    // Handle WASD input
    if (Gdx.input.isKeyPressed(Input.Keys.W)) {
        dogY += speed * delta;
    }
    if (Gdx.input.isKeyPressed(Input.Keys.S)) {
        dogY -= speed * delta;
    }
    if (Gdx.input.isKeyPressed(Input.Keys.A)) {
        dogX -= speed * delta;
    }
    if (Gdx.input.isKeyPressed(Input.Keys.D)) {
        dogX += speed * delta;
    }

    // Boundary check to keep the dog inside the help menu (MovementSlide)
    dogX = Math.max(0, Math.min(dogX, getParent().getWidth() - getWidth()));
    dogY = Math.max(0, Math.min(dogY, getParent().getHeight() - getHeight()));
}

Movement Control:

WASD Keys: Control the dog's movement up, down, left, and right respectively. Speed: The dog's movement speed is controlled by the speed variable.

Boundary Check: Ensures the dog remains within the help menu's viewable area by clamping its position.

UML DIAGRAM (Slides)

image

Sequence Diagram (HelpWindow)

image

Sequence Diagram (Slides)

image