Skip to content

Loading Bar

raneechu edited this page Oct 5, 2021 · 3 revisions

Purpose

The loading screen uses a loading bar to let the player know that the game is loading, and how much has loaded, rather than the player pressing the start button seeing no change to the screen when the assets are being loaded.

Implementation

Key Components

  • LoadingScreen Handles the loading of the assets for the level and sets the game screen when the loading is finished.
  • LoadingDisplay Handles the UI of the loading screen
  • GDXGame Adds LoadingScreen as a screen in the game as well as passes through the ResourceService into other screens to allow access of assets between the loading screen and game areas.

The LoadingScreen class initialises the textures to be loaded similar to the game areas. For example:

/* Textures only needed for level 2 */
private static final String[] level2Textures = {"images/background_mars.png",
        "images/background_mars_ground.png",
        "images/background_mars_surface.png",
        "images/background_mars_star.png"};

When calling the constructor method, the resourceService parameter that is passed through by GDXGame is registered with the ServiceLocator and the assets are then loaded and the UI is created. Note that this loadAssets() method replaces the ones in the game areas.

public LoadingScreen(GdxGame game, ResourceService resourceService) {
    this.game = game;

    logger.debug("Initialising main menu screen services");
    ServiceLocator.registerResourceService(resourceService);

    loadAssets();
    createUI();
}

Within the loadAssets() method, all of the textures common across all the assets are loaded every time the loading screen is created. However, the method runs a check on which level the game is loading to in order to decide if other assets are required. For example in level 2:

private void loadAssets() {
    if (game.getScreenType() == GdxGame.ScreenType.LEVEL_TWO_GAME) {
        logger.info("loading level2 assets");
        resourceService.loadTextures(level2Textures);
    }
}

The render method then checks if all the assets are fully loaded. If so, then the game changes to the relevant screen.

@Override
public void render(float delta) {
    ServiceLocator.getEntityService().update();

    // If all assets are loaded, then switch to the correct screen of the game.
    if (resourceService.getAssetManager().update()) {
        switch (game.getScreenType()) {
            case MAIN_GAME:
                this.game.setScreen(GdxGame.ScreenType.MAIN_GAME);
                break;
            case CHECKPOINT_REPLAY:
                this.game.setScreen(GdxGame.ScreenType.CHECKPOINT_REPLAY);
                break;
            case CHECKPOINT:
                this.game.setScreen(GdxGame.ScreenType.CHECKPOINT);
                break;
            case RESPAWN:
                this.game.setScreen(GdxGame.ScreenType.RESPAWN);
                break;
            case LEVEL_TWO_GAME:
                this.game.setScreen(GdxGame.ScreenType.LEVEL_TWO_GAME);
                break;
            case LEVEL_THREE_GAME:
                this.game.setScreen(GdxGame.ScreenType.LEVEL_THREE_GAME);
                break;
        }
    } else {
        logger.info("Loading... {}%", (int) (resourceService.getAssetManager().getProgress() * 100));
    }
    renderer.render();
}

Getter and setter methods were created in GDXGame to help the loading screen keep track of which level is being loaded, so the correct assets can be loaded and the game can switch to the correct screen. Where the game used to automatically set the screen based on the player's input e.g. inside PopupMenuActions, the game now sets the screen type, which can then be accessed by LoadingScreen so that it can switch to the right screen once all assets have been loaded.

public void onNextLevel() {
    if (this.currentLevel == 1) {
        game.setScreenType(GdxGame.ScreenType.LEVEL_TWO_GAME);
        game.setScreen(GdxGame.ScreenType.LOADING);
    } else if (this.currentLevel == 2) {
        game.setScreenType(GdxGame.ScreenType.LEVEL_THREE_GAME);
        game.setScreen(GdxGame.ScreenType.LOADING);
    }
}

In LoadingDisplay updating the loading bar follows similar functionality to the progress bar.

@Override
protected void draw(SpriteBatch batch) {
    // Gets how much of the assets are loaded as an percentage integer
    updateLoadingBar((int) (ServiceLocator.getResourceService().getAssetManager().getProgress() * 100));
}

private void updateLoadingBar(int currentLoad) {
    if (currentLoad % 10 == 0 && currentLoad > 0) {
        switch (currentLoad) {
            case 10:
                loadingStatus.setDrawable(new SpriteDrawable
                        (new Sprite(resourceService.getAsset("images/10percent.png", Texture.class))));
                break;
...
}

Usage

When creating a new level, within LoadingScreen create a string of textures that need to be loaded for that level.

/* Textures only needed for level 3 */
private static final String[] level3Textures = {"images/background_europa.png",
        "images/background_europa_ground.png",
        "images/background_europa_surface.png",
        "images/background_europa_star.png"};

Inside loadAssets() add an if condition to load these assets if the screenType is the right level:

private void loadAssets() {
    if (game.getScreenType() == GdxGame.ScreenType.LEVEL_TWO_GAME) {
        ...
    } else if (game.getScreenType() == GdxGame.ScreenType.LEVEL_THREE_GAME) {
        logger.info("loading level3 assets");
        resourceService.loadTextures(level3Textures);
    }
}

Inside the level screen, allow the resourceService to be passed through as a parameter and register it with the ServiceLocator

public LevelThreeScreen(GdxGame game, ResourceService resourceService) {
    ServiceLocator.registerResourceService(resourceService);
}

Note: Although the assets for each level are loaded within LoadingScreen, a copy of the textures is still required in each game area, as that is where the assets are unloaded. However, there may be a less redundant way to do this. Within LevelThreeArea:

private void unloadAssets() {
    logger.debug("Unloading assets");
    ResourceService resourceService = ServiceLocator.getResourceService();
    resourceService.unloadAssets(forestTextures);
    resourceService.unloadAssets(forestTextureAtlases);
    resourceService.unloadAssets(forestSounds);
    resourceService.unloadAssets(forestMusic);
}

UML Documentation

Table of Contents

Home

Introduction

Main Menu

Main Game Screen

Gameplay

Player Movement

Character Animations

Enemy Monster Design and Animations

Game basic functionalities

User Testing

GitHub Wiki Tutorial

Game Engine

Getting Started

Documentation

Entities and Components

Service Locator

Loading Resources

Logging

Unit Testing

Debug Terminal

Input Handling

UI

Animations

Audio

AI

Physics

Game Screens and Areas

Terrain

Concurrency & Threading

Settings

Troubleshooting

MacOS Setup Guide

Clone this wiki locally