-
Notifications
You must be signed in to change notification settings - Fork 2
Game Transition Loop
Switching between Game Screens while in-game is a key part of the user experience, designed to tell the player whether they are winning or losing. These transitions can be summarised as "Gameplay" to "Results", and back again. This mechanism is known as the Game Loop.
To facilitate results being displayed to the player, the End Game Screen was created. Currently, the class EndGameScreen
is implemented similarly to MainMenuScreen
. It displays the result as an image, and allows the player to click back into the MainMenuScreen
.
To reach the EndGameScreen
, a win or lose condition must be met. These conditions are observed inside the MainGameScreen
, and directly determine the appearance of EndGameDisplay
, a UIComponent
of EndGameScreen
.
To facilitate the new screen, cases for newScreen
and enumerations for ScreenType
were added:
private Screen newScreen(ScreenType screenType) {
switch (screenType) {
...
case WIN_DEFAULT:
return new EndGameScreen(this, ScreenType.WIN_DEFAULT);
case LOSS_TIMED:
return new EndGameScreen(this, ScreenType.LOSS_TIMED);
case LOSS_CAUGHT:
return new EndGameScreen(this, ScreenType.LOSS_CAUGHT);
...
}
public enum ScreenType {
MAIN_MENU, MAIN_GAME, SETTINGS, WIN_DEFAULT, LOSS_TIMED, LOSS_CAUGHT
}
Notably, each ScreenType
does not correlate to a unique Screen
. This is because the current logic for Win and Lose screens are very similar. Therefore, their implementations were combined.
New events and methods had to be added for each new ScreenType
:
public void create() {
...
entity.getEvents().addListener("winDefault", this::onWinDefault);
entity.getEvents().addListener("lossTimed", this::onLossTimed);
entity.getEvents().addListener("lossCaught", this::onLossCaught);
}
Once a condition is met, the alerted listener will call one of the screen transition methods to switch to EndGameScreen:
private void onWinDefault() {
...
game.setScreen(GdxGame.ScreenType.WIN_DEFAULT);
}
private void onLossTimed() {
...
game.setScreen(GdxGame.ScreenType.LOSS_TIMED);
}
private void onLossCaught() {
...
game.setScreen(GdxGame.ScreenType.LOSS_CAUGHT);
}
Called directly from MainGameScreen
, the EndGameScreen
constructor takes the win/loss condition as a result that determines the list of textures that will be displayed:
private GdxGame.ScreenType result;
private String[] activeDisplayTextures;
public EndGameScreen(GdxGame game, GdxGame.ScreenType result) {
...
this.result = result;
switch (this.result) {
case WIN_DEFAULT:
this.activeScreenTextures = winScreenTextures;
break;
case LOSS_TIMED:
case LOSS_CAUGHT:
default:
this.activeScreenTextures = loseScreenTextures;
}
...
createUI();
}
The EndGameDisplay
passes itself by reference to the EndGameDisplay
constructor in the createUI
method. The display can call methods on the reference to retrieve the level result and active textures this way. It is assumed that the first path location in the String
of loaded assets is the chosen screen background:
public EndGameDisplay(EndGameScreen screen) {
super();
this.screen = screen;
}
private void addActors() {
table = new Table();
...
Image background =
new Image(
ServiceLocator.getResourceService()
.getAsset(this.screen.getActiveScreenTextures()[0], Texture.class));
...
table.setFillParent(true);
table.setBackground(bakground.getDrawable());
...
}
The nextLevelBtn
and mainMenuBtn
functions very similar to the ones found in MainGameDisplay
. It allows the player to go to the next MainGameScreen
level or MainMenuScreen
respectively. A player can only go to the next level if they won the previous one:
private void addActors() {
...
if (this.screen.getResult() == GdxGame.ScreenType.WIN_DEFAULT) {
TextButton nextLevelBtn.addListener(
new ChangeListener() {
@Override
public void changed(ChangeEvent changeEvent, Actor actor) {
logger.debug("Next level button clicked");
entity.getEvents().trigger("nextLevel");
}
});
buttonContainer.addActor(nextLevelBtn);
}
...
}
- In future iterations where desired win/lose displays are more design-dependent,
EndGameScreen
could be split intoWinGameScreen
andLoseGameScreen
to facilitate whatever major differences that may appear - Once design becomes a more important factor against programming, we expect win/lose backgrounds to be redrawn. A simple change to the hardcoded filepath in
EndGameScreen
will suffice this
Entities and Components
Interaction System
Unit Testing
Input Handling
UI
Game Screens and Areas
Map Generation
Basic Interactable Objects Design