com.forerunnergames.peril.client.ui.screens.ScreenController.java Source code

Java tutorial

Introduction

Here is the source code for com.forerunnergames.peril.client.ui.screens.ScreenController.java

Source

/*
 * Copyright  2011 - 2013 Aaron Mahan.
 * Copyright  2013 - 2016 Forerunner Games, LLC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package com.forerunnergames.peril.client.ui.screens;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Screen;

import com.forerunnergames.peril.client.ui.music.MusicChanger;
import com.forerunnergames.tools.common.Arguments;
import com.forerunnergames.tools.common.Strings;
import com.forerunnergames.tools.common.controllers.ControllerAdapter;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class ScreenController extends ControllerAdapter implements ScreenChanger {
    private static final Logger log = LoggerFactory.getLogger(ScreenController.class);
    private static final int SCREEN_HISTORY_DEPTH = 10;
    private final Deque<ScreenId> screenIdHistory = new ArrayDeque<>(SCREEN_HISTORY_DEPTH);
    private final BiMap<ScreenId, Screen> screens = HashBiMap.create(ScreenId.values().length);
    private final AtomicBoolean isScreenTransitionInProgress = new AtomicBoolean();
    private final Game game;
    private final MusicChanger musicChanger;
    private final ScreenFactoryCreator screenFactoryCreator;
    private ScreenFactory screenFactory;

    public ScreenController(final Game game, final MusicChanger musicChanger,
            final ScreenFactoryCreator screenFactoryCreator) {
        Arguments.checkIsNotNull(game, "game");
        Arguments.checkIsNotNull(musicChanger, "musicChanger");
        Arguments.checkIsNotNull(screenFactoryCreator, "screenFactoryCreator");

        this.game = game;
        this.musicChanger = musicChanger;
        this.screenFactoryCreator = screenFactoryCreator;
    }

    @Override
    public void toPreviousScreenOrSkipping(final ScreenId defaultScreenId, final ScreenId... skipScreenIds) {
        Arguments.checkIsNotNull(defaultScreenId, "defaultScreenId");
        Arguments.checkIsNotNull(skipScreenIds, "skipScreenIds");
        Arguments.checkHasNoNullElements(skipScreenIds, "skipScreenIds");

        if (isScreenTransitionInProgress.get()) {
            log.warn("Not going to previous screen because screen transition already in progress.");
            return;
        }

        final ImmutableCollection<ScreenId> skipScreenIdsCopy = ImmutableList.copyOf(skipScreenIds);

        log.debug("Attempting to go to previous screen from [{}], while avoiding the following screens: {}...",
                getCurrentScreenId(), skipScreenIdsCopy);

        final Iterator<ScreenId> screenIdHistoryIterator = screenIdHistory.descendingIterator();

        int historyDepth = 1;

        while (screenIdHistoryIterator.hasNext()) {
            final ScreenId previousScreenId = screenIdHistoryIterator.next();

            if (!skipScreenIdsCopy.contains(previousScreenId)) {
                log.debug("Success, {} back is [{}].", Strings.pluralizeS(historyDepth, "screen"),
                        previousScreenId);
                toScreen(previousScreenId);
                return;
            }

            log.debug("Failed, {} back is [{}].", Strings.pluralizeS(historyDepth, "screen"), previousScreenId);

            ++historyDepth;
        }

        log.debug("Going to default screen [{}] from [{}]", defaultScreenId, getCurrentScreenId());

        toScreen(defaultScreenId);
    }

    @Override
    public void toScreen(final ScreenId id) {
        Arguments.checkIsNotNull(id, "id");

        if (isScreenTransitionInProgress.get()) {
            log.warn("Not going to screen [{}] because screen transition already in progress.", id);
            return;
        }

        isScreenTransitionInProgress.set(true);

        if (id == getCurrentScreenId())
            return;
        if (!screens.containsKey(id))
            screens.put(id, screenFactory.create(id));
        if (screenIdHistory.size() == SCREEN_HISTORY_DEPTH)
            screenIdHistory.remove();

        final ScreenId previousScreenId = getCurrentScreenId();
        screenIdHistory.add(previousScreenId);
        game.setScreen(screens.get(id));
        musicChanger.changeMusic(getCurrentScreenId());

        log.info("Changed from {} [{}] to {} [{}].", Screen.class.getSimpleName(), previousScreenId,
                Screen.class.getSimpleName(), id);

        isScreenTransitionInProgress.set(false);
    }

    @Override
    public boolean isScreenTransitionInProgress() {
        return isScreenTransitionInProgress.get();
    }

    @Override
    public void initialize() {
        screenFactory = screenFactoryCreator.create(this);
        toScreen(ScreenId.SPLASH);
    }

    @Override
    public void shutDown() {
        for (final Screen screen : screens.values()) {
            screen.dispose();
        }

        screens.clear();
    }

    private ScreenId getCurrentScreenId() {
        final Screen currentScreen = game.getScreen();

        return currentScreen != null ? screens.inverse().get(currentScreen) : ScreenId.NONE;
    }
}