package de.fau.cs.mad.fly;
import java.util.ArrayList;
import java.util.List;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.scenes.scene2d.Event;
import com.badlogic.gdx.scenes.scene2d.EventListener;
import de.fau.cs.mad.fly.db.FlyDBManager;
import de.fau.cs.mad.fly.game.GameController;
import de.fau.cs.mad.fly.game.GameControllerBuilder;
import de.fau.cs.mad.fly.game.ParticleController;
import de.fau.cs.mad.fly.profile.LevelGroupManager;
import de.fau.cs.mad.fly.profile.PlayerProfileManager;
import de.fau.cs.mad.fly.res.Assets;
import de.fau.cs.mad.fly.ui.SkinManager;
import de.fau.cs.mad.fly.ui.screens.GameScreen;
import de.fau.cs.mad.fly.ui.screens.LoadingScreen;
import de.fau.cs.mad.fly.ui.screens.MainMenuScreen;
/**
* Manages the different game screens.
* <p>
* Includes screens for SplashScreen, LoadingScreen, GameScreen, MainMenuScreen,
* OptionScreen, HelpScreen and LevelChooserScreen.
* <p>
* All screens should be loaded only when they are needed.
*
* @author Tobias Zangl
*/
public class Fly extends Game implements Loadable<Fly> {
/**
* The version of the app. (works only on android)
*/
public static String VERSION = "1.1.0";
/**
* True if debug mode is enabled, false otherwise.
* <p>
* Currently debug mode only disables the level dependencies.
*/
public static boolean DEBUG_MODE = true;
private LoadingScreen<Fly> splashScreen;
private GameScreen gameScreen;
private MainMenuScreen mainMenuScreen;
private GameController gameController;
private List<ProgressListener<Fly>> listeners = new ArrayList<ProgressListener<Fly>>();
private int progress = 0;
@Override
public void create() {
// init Assets, has to be done in the main Tread because it needs the
// OpenGl context that is only offered by the main Thread.
Assets.init();
// load SkinManager, has to be done in the main Tread because it needs
// the OpenGl context that is only offered by the main Thread.
SkinManager.getInstance();
addProgressListener(new ProgressListener.ProgressAdapter<Fly>() {
@Override
public void progressFinished(Fly fly) {
if (mainMenuScreen == null) {
mainMenuScreen = new MainMenuScreen();
}
mainMenuScreen.set();
}
});
Runnable runnable = new Runnable() {
@Override
public void run() {
init();
}
};
Thread loadingThread = new Thread(runnable);
loadingThread.start();
setSplashScreen();
}
protected void init() {
LevelGroupManager.createLevelManager();
progress = 10;
PlayerProfileManager.getInstance().getCurrentPlayerProfile();
progress = 90;
ParticleController.createParticleController();
progress = 100;
}
/**
* Allows to add a listener, to listen for the loading progress of the app.
*/
public void addProgressListener(ProgressListener<Fly> listener) {
this.listeners.add(listener);
}
/**
* Method that is called by by the {@link LoadingScreen} during the loading
* progress to get the current loading progress.
*/
public void update() {
int size = listeners.size();
int i;
for (i = 0; i < size; i++) {
listeners.get(i).progressUpdated(progress);
}
if (progress >= 100) {
for (i = 0; i < size; i++) {
listeners.get(i).progressFinished(this);
}
progress = 0;
}
}
@Override
public void resume() {
super.resume();
}
@Override
public void dispose() {
mainMenuScreen.dispose();
mainMenuScreen = null;
FlyDBManager.getInstance().dispose();
Loader.getInstance().dispose();
SkinManager.getInstance().dispose();
Assets.dispose();
}
public GameController getGameController() {
return gameController;
}
/**
* Switches the current screen to the {@link LoadingScreen}.
*/
public void setSplashScreen() {
if (splashScreen == null) {
splashScreen = new LoadingScreen<Fly>(this, null);
}
setScreen(splashScreen);
}
/**
* Switches the current screen to the {@link GameScreen}.
*/
public void setGameScreen() {
if (gameScreen == null) {
gameScreen = new GameScreen();
}
setScreen(gameScreen);
}
/**
* set screen. Add new check if it is switching between 2d and 3d screen
*
* @param screen
* may be {@code null}
*/
@Override
public void setScreen(Screen screen) {
int newMode = getScreenMode(screen);
if (getScreenMode(screen) != current3d2dMode) {
onMode3d2dChanged(newMode);
}
super.setScreen(screen);
}
public MainMenuScreen getMainMenuScreen() {
return mainMenuScreen;
}
/**
* Initializes the GameController for the current level
*/
public void initGameController() {
GameControllerBuilder builder = new GameControllerBuilder();
builder.init(this);
gameController = builder.build();
Gdx.app.log("Fly.initGameController", "Controller built.");
gameController.loadGame();
}
protected ArrayList<EventListener> mode3d2dChangedListeners = new ArrayList<EventListener>();
protected int current3d2dMode = Mode3d2dChangedEvent.MODE_2D;
private OrientationProvider orientationProvider;
public void add3d2dChangedListeners(EventListener listener) {
if (listener != null) {
mode3d2dChangedListeners.add(listener);
}
}
public void remove3d2dChangedListeners(EventListener listener) {
mode3d2dChangedListeners.remove(listener);
}
/**
* To be called when UI change between 2d and 3d
*
* @param newMode
*/
public void onMode3d2dChanged(int newMode) {
if (mode3d2dChangedListeners != null) {
for (EventListener listener : mode3d2dChangedListeners) {
listener.handle(new Mode3d2dChangedEvent(newMode));
}
}
current3d2dMode = newMode;
}
/**
* if @param is instance of GameScreen or LoadingScreen, then return turn.
*
* @param screen
* @return
*/
private int getScreenMode(Screen screen) {
if (screen == null) {
return 0;
}
if (screen instanceof GameScreen) {
return Mode3d2dChangedEvent.MODE_3D;
}
return Mode3d2dChangedEvent.MODE_2D;
}
/**
* Event happens when user switches between 2d UI and 3dUI
*
* @author Lenovo
*
*/
public class Mode3d2dChangedEvent extends Event {
public static final int MODE_3D = 3;
public static final int MODE_2D = 2;
public int mode = 2;
public Mode3d2dChangedEvent(int mode) {
this.mode = mode;
}
}
/**
* This method is called by a component that controls weather the screen may
* be swapped or not. It is necessary for {@link #orientationSwapped}.
*
* @param orientationProvider
*/
public void addOrientationProvider(OrientationProvider orientationProvider) {
this.orientationProvider = orientationProvider;
}
/** Method to check weather the screen is swapped or not */
public boolean orientationSwapped() {
if (orientationProvider == null) {
return false;
} else {
return orientationProvider.orientationSwapped();
}
}
}