CutsceneTextDisplay - UQcsse3200/2024-studio-3 GitHub Wiki
Introduction
The CutsceneTextDisplay class is responsible for displaying scrolling text during cutscenes. It shows text one character at a time, creating a typing effect to engage the player. Players can press ENTER to skip to the full text immediately. This class adds immersion to the cutscenes by introducing a gradual reveal of dialogue or narrative content, supporting the cinematic storytelling experience.
Key Features
- Text Display with Typing Effect: The text is displayed one character at a time, mimicking a typing effect. The display automatically updates every few milliseconds (based on a delay) to reveal the next character in the text string.
- Input Listener for Skipping Text: If the player presses the ENTER key during the cutscene, the text display skips the typing effect and immediately shows the full text. This allows the player to speed up the cutscene if they don’t want to wait for the text to finish typing out.
Code Implementation
create()
This method is responsible for setting up the UI components and laying out the text display on the screen. It:
-
Initialises the visibility: It ensures that the text display is hidden initially, meaning it won’t show up until text is set.
-
Sets up the layout: A Table is used to hold the text display. The table fills the screen and is aligned at the bottom, mimicking a typical "textbox" layout often seen in cutscenes.
-
Creates the background image: The background image (or "textbox") is loaded from the resources and added to the layout. This image visually frames the text to distinguish it as dialogue or narration.
-
Initialises the text label: The text is displayed using a Label object, which wraps and scales the text based on the screen size. The label is placed inside the table, and padding is added to give it appropriate spacing.
-
Sets up an input listener: The method adds an input listener to detect when the ENTER key is pressed, allowing the player to skip the typing effect.
@Override
public void create() {
super.create();
setVisible(false);
table.setFillParent(true);
table.center().bottom();
stage.addActor(table);
Stack stack = new Stack();
Texture textboxTexture = ServiceLocator.getResourceService().getAsset("images/textbox.png", Texture.class);
Drawable textboxDrawable = new TextureRegionDrawable(textboxTexture);
Image textboxImage = new Image(textboxDrawable);
textboxImage.setScale(1.25f);
stack.add(textboxImage);
BitmapFont defaultFont = new BitmapFont();
Label.LabelStyle labelStyle = new Label.LabelStyle(defaultFont, Color.BLACK);
label = new Label("", labelStyle);
label.setFontScale(3.0f);
label.setWrap(true);
label.setAlignment(Align.top | Align.left);
Table labelTable = new Table();
labelTable.add(label).padLeft(140).padBottom(10).size(
(int) (Gdx.graphics.getWidth() * 0.5), (int) (Gdx.graphics.getHeight() * 0.2));
stack.add(labelTable);
table.add(stack).padBottom(70).size(
(int) (Gdx.graphics.getWidth() * 0.5), (int) (Gdx.graphics.getHeight() * 0.2));
setupInputListener();
entity.getEvents().addListener("SetText", this::setText);
}
update()
This method handles the gradual typing effect. It checks the current time and updates the currentText string with the next character from the text string when the delay has passed. The text is displayed in the label, and the method continues to update until the full text is displayed.
@Override
@Override
public void update() {
long time = ServiceLocator.getTimeSource().getTime();
if (this.text != null && charIndex < this.text.length()) {
if (time - lastUpdate >= delay) {
lastUpdate = time;
this.currentText.append(text.charAt(charIndex));
label.setText(currentText.toString());
charIndex++;
}
}
}
setupInputListener()
This method sets up an input listener for the ENTER key. If the ENTER key is pressed, the text is immediately set to the full text string, skipping the typing effect.
private void setupInputListener() {
stage.addListener(new InputListener() {
@Override
public boolean keyDown(InputEvent event, int keycode) {
if (keycode == com.badlogic.gdx.Input.Keys.ENTER) {
label.setText(text); // Display full text
charIndex = text.length(); // Skip to the end
return true;
}
return false;
}
});
}