package de.fau.cs.mad.fly.game; import java.util.List; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputMultiplexer; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.PerspectiveCamera; import com.badlogic.gdx.graphics.g3d.ModelBatch; import com.badlogic.gdx.scenes.scene2d.Stage; import de.fau.cs.mad.fly.features.IFeatureDispose; import de.fau.cs.mad.fly.features.IFeatureDraw; import de.fau.cs.mad.fly.features.IFeatureFinish; import de.fau.cs.mad.fly.features.IFeatureInit; import de.fau.cs.mad.fly.features.IFeatureLoad; import de.fau.cs.mad.fly.features.IFeatureRender; import de.fau.cs.mad.fly.features.IFeatureUpdate; import de.fau.cs.mad.fly.player.Player; import de.fau.cs.mad.fly.res.Level; import de.fau.cs.mad.fly.sound.AudioManager; /** * Manages the Player, the Level, the UI, the CameraController and all the * optional Features and calls the load(), init(), render(), finish() and * dispose() methods of those. * <p> * Optional Feature Interfaces: * <p> * load(): - called before the game starts while the loading screen is shown - * should be stuff like loading models, creating instances, which takes a while * <p> * init(): - called the moment the game starts after switching to the game * screen - should be stuff like setting values, resetting counter * <p> * update(): - called every frame while the game is running and not paused - * should be stuff like calculating and updating values * <p> * render(): - called every frame while the game is running or paused - should * be stuff like rendering models * <p> * draw(): - called every frame while the game is running or paused - should be * stuff like drawing overlays * <p> * finish(): - called at the moment the game is over, still in game screen - * should be stuff like showing points, saving the highscore * <p> * dispose(): - called when the game screen is left - should be stuff like * disposing models * * @author Lukas Hahmann */ public class GameController implements TimeIsUpListener { public enum GameState { RUNNING, PAUSED, VICTORY, NO_LIVES, TIME_OVER; } protected static GameController instance = null; protected Stage stage; protected List<IFeatureLoad> optionalFeaturesToLoad; protected List<IFeatureInit> optionalFeaturesToInit; protected List<IFeatureUpdate> optionalFeaturesToUpdate; protected List<IFeatureRender> optionalFeaturesToRender; protected List<IFeatureDraw> optionalFeaturesToDraw; protected List<IFeatureDispose> optionalFeaturesToDispose; protected List<IFeatureFinish> optionalFeaturesToFinish; protected List<GameStateListener> gameStateListeners; protected FlightController flightController; protected CameraController cameraController; protected PerspectiveCamera camera; protected ModelBatch batch; protected Level level; protected Player player; protected ScoreController scoreController; protected AudioManager audioManager; private GameState gameState; private TimeController timeController; private InputMultiplexer inputProcessor; /** Use Builder to initiate GameController */ protected GameController() { } /** * Getter for the singleton game controller. * * @return {@link #instance} */ public static GameController getInstance() { if (instance == null) { instance = new GameController(); } return instance; } /** * Getter for the model batch used to draw the 3d game. * * @return ModelBatch */ public ModelBatch getBatch() { return batch; } /** * Getter for the stage. * * @return {@link #stage} */ public Stage getStage() { return stage; } /** * Getter for the flight controller. * * @return {@link #flightController} */ public FlightController getFlightController() { return flightController; } /** * Getter for the camera. * * @return {@link #camera} */ public PerspectiveCamera getCamera() { return camera; } /** * Setter for the input Processor. * * @param inputProcessor */ public void setInputProcessor(InputMultiplexer inputProcessor) { this.inputProcessor = inputProcessor; } /** * Getter for the level. * * @return {@link #level} */ public Level getLevel() { return level; } /** * Getter for the player. * * @return {@link #player} */ public Player getPlayer() { return player; } /** * This method is called, while the level is loading. It loads everything * the default functions need. Furthermore all optional features in * {@link #optionalFeaturesToLoad} are loaded. */ public void loadGame() { camera = cameraController.getCamera(); ParticleController.getInstance().load(camera, batch); // load features for (IFeatureLoad optionalFeature : optionalFeaturesToLoad) { optionalFeature.load(this); } } /** * This method is called, when the level is initialized. It initializes all * default functions that are needed in all levels, like render the level. * Furthermore all optional features in {@link #optionalFeaturesToInit} are * initialized. */ public void initGame() { // initialize features for (IFeatureInit optionalFeature : optionalFeaturesToInit) { optionalFeature.init(this); } Gdx.input.setCatchBackKey(true); Gdx.input.setInputProcessor(inputProcessor); setGameState(GameState.RUNNING); timeController.initAndStartTimer((int) level.getLeftTime()); Gdx.app.log("GameController.initGame", "OK HAVE FUN!"); } /** * Getter for the game state. * * @return GameState */ public GameState getGameState() { return gameState; } /** * Setter for the game state. * <p> * Calls all {@link #gameStateListeners} and calls {@link #endGame()} if * necessary. */ public void setGameState(GameState newGameState) { if (this.gameState == null || this.gameState == GameState.PAUSED || this.gameState == GameState.RUNNING) { this.gameState = newGameState; for (int i = gameStateListeners.size() - 1; i >= 0; i--) { gameStateListeners.get(i).gameStateChanged(newGameState); } switch (newGameState) { case PAUSED: break; case RUNNING: break; default: endGame(); break; } } } /** * This method is called every frame. Furthermore all optional features in * {@link #optionalFeaturesToRender} are updated and rendered. * * @param delta * Time after the last call. */ public void renderGame(float delta) { stage.act(delta); int len, i; if (gameState == GameState.RUNNING) { // update features if the game is not paused flightController.update(delta); camera = cameraController.updateCamera(); level.update(delta, camera); len = optionalFeaturesToUpdate.size(); for (i = 0; i < len; i++) { optionalFeaturesToUpdate.get(i).update(delta); } CollisionDetector.getInstance().perform(delta); timeController.checkTime(); } Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); // render features batch.begin(camera); level.render(delta, batch, camera); len = optionalFeaturesToRender.size(); for (i = 0; i < len; i++) { optionalFeaturesToRender.get(i).render(delta); } ParticleController.getInstance().render(); batch.end(); // draw features len = optionalFeaturesToDraw.size(); for (i = 0; i < len; i++) { optionalFeaturesToDraw.get(i).draw(delta); } stage.draw(); } /** * This method is called when the game is over. Furthermore all optional * features in {@link #optionalFeaturesToFinish} are finished. */ public void endGame() { timeController.pause(); for (IFeatureFinish optionalFeature : optionalFeaturesToFinish) { optionalFeature.finish(); } } /** * This method is called when the game is over. Furthermore all optional * features in {@link #optionalFeaturesToDispose} are disposed. */ public void disposeGame() { // dispose features for (IFeatureDispose optionalFeature : optionalFeaturesToDispose) { optionalFeature.dispose(); } // remove all objects from a previous level CollisionDetector.getInstance().dispose(); audioManager.dispose(); optionalFeaturesToLoad.clear(); optionalFeaturesToInit.clear(); optionalFeaturesToUpdate.clear(); optionalFeaturesToRender.clear(); optionalFeaturesToDraw.clear(); optionalFeaturesToDispose.clear(); optionalFeaturesToFinish.clear(); gameStateListeners.clear(); gameState = GameState.PAUSED; } /** * Setter for the time controller. * * @param timeController * The time controller to use. */ public void setTimeController(TimeController timeController) { this.timeController = timeController; timeController.registerTimeIsUpListener(this); } /** * Getter for the time controller. * * @return {@link #timeController} */ public TimeController getTimeController() { return timeController; } /** * Getter for the score controller. * * @return {@link #scoreController} */ public ScoreController getScoreController() { return scoreController; } /** * Getter for the audio manager * * @return {@link #audioManager} */ public AudioManager getAudioManager() { return audioManager; } @Override public boolean timeIsUp() { setGameState(GameState.TIME_OVER); return true; } public void registerGameStateListener(GameStateListener listener) { gameStateListeners.add(listener); } public void removeGameStateListener(GameStateListener listener) { gameStateListeners.remove(listener); } }